<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//
// Contributors: Kirsten Weber

#ifndef DUNE_GDT_DISCRETEFUNCTION_DEFAULT_HH
#define DUNE_GDT_DISCRETEFUNCTION_DEFAULT_HH

#include <memory>
#include <type_traits>

#include <dune/common/exceptions.hh>
#include <dune/common/fvector.hh>

#include <dune/grid/io/file/vtk.hh>

#include <dune/stuff/la/container/interfaces.hh>
#include <dune/stuff/functions/interfaces.hh>
#include <dune/stuff/common/memory.hh>

#include <dune/gdt/spaces/interface.hh>

#include "local.hh"

namespace Dune {
namespace GDT {

template <class SpaceImp, class VectorImp>
class ConstDiscreteFunction
    : public Stuff::LocalizableFunctionInterface<typename SpaceImp::EntityType, typename SpaceImp::DomainFieldType,
                                                 SpaceImp::dimDomain, typename SpaceImp::RangeFieldType,
                                                 SpaceImp::dimRange, SpaceImp::dimRangeCols>
{
  static_assert(is_space<SpaceImp>::value, "SpaceImp has to be derived from SpaceInterface!");
  static_assert(Stuff::LA::is_vector<VectorImp>::value, "VectorImp has to be derived from Stuff::LA::VectorInterface!");
  static_assert(std::is_same<typename SpaceImp::RangeFieldType, typename VectorImp::ScalarType>::value,
                "Types do not match!");
  typedef Stuff::LocalizableFunctionInterface<typename SpaceImp::EntityType, typename SpaceImp::DomainFieldType,
                                              SpaceImp::dimDomain, typename SpaceImp::RangeFieldType,
                                              SpaceImp::dimRange, SpaceImp::dimRangeCols> BaseType;
  typedef ConstDiscreteFunction<SpaceImp, VectorImp> ThisType;

public:
  typedef SpaceImp SpaceType;
  typedef VectorImp VectorType;
  typedef typename BaseType::EntityType EntityType;
  typedef typename BaseType::LocalfunctionType LocalfunctionType;

  typedef ConstLocalDiscreteFunction<SpaceType, VectorType> ConstLocalDiscreteFunctionType;

  ConstDiscreteFunction(const SpaceType& sp, const VectorType& vec, const std::string nm = "gdt.constdiscretefunction")
    : space_(sp)
    , vector_(vec)
    , name_(nm)
  {
    assert(vector_.size() == space_->mapper().size() && "Given vector has wrong size!");
  }

  ConstDiscreteFunction(const ThisType& other)
    : space_(other.space())
    , vector_(other.vector_)
    , name_(other.name_)
  {
  }

  ConstDiscreteFunction(ThisType&& source)
    : space_(source.space())
    , vector_(source.vector_)
    , name_(source.name_)
  {
  }

  virtual ~ConstDiscreteFunction()
  {
  }

  ThisType& operator=(const ThisType& other) = delete;

  virtual ThisType* copy() const override
  {
    return new ThisType(*this);
  }

  virtual std::string name() const override
  {
    return name_;
  }

  const SpaceType& space() const
  {
    return *space_;
  }

  const VectorType& vector() const
  {
    return vector_;
  }

  std::unique_ptr<ConstLocalDiscreteFunctionType> local_discrete_function(const EntityType& entity) const
  {
    assert(space_->grid_view().indexSet().contains(entity));
    return DSC::make_unique<ConstLocalDiscreteFunctionType>(*space_, vector_, entity);
  }

  virtual std::unique_ptr<LocalfunctionType> local_function(const EntityType& entity) const override
  {
    return local_discrete_function(entity);
  }

  void visualize(const std::string filename, const bool subsampling = (SpaceType::polOrder > 1),
                 VTK::OutputType vtk_output_type = VTK::appendedraw) const
  {
    BaseType::template visualize<typename SpaceType::GridViewType>(
        space().grid_view(), filename, subsampling, vtk_output_type);
  } // ... visualize(...)

  bool dofs_valid() const
  {
    return vector().valid();
  }

protected:
  const DS::PerThreadValue<SpaceType> space_;

private:
  const VectorType& vector_;
  const std::string name_;
}; // class ConstDiscreteFunction

template <class SpaceImp, class VectorImp>
class DiscreteFunction : Stuff::Common::StorageProvider<VectorImp>, public ConstDiscreteFunction<SpaceImp, VectorImp>
{
  typedef Stuff::Common::StorageProvider<VectorImp> VectorProviderBaseType;
  typedef ConstDiscreteFunction<SpaceImp, VectorImp> BaseType;
  typedef DiscreteFunction<SpaceImp, VectorImp> ThisType;

public:
  typedef typename BaseType::SpaceType SpaceType;
  typedef typename BaseType::VectorType VectorType;
  typedef typename BaseType::EntityType EntityType;
  typedef typename BaseType::LocalfunctionType LocalfunctionType;

  typedef LocalDiscreteFunction<SpaceType, VectorType> LocalDiscreteFunctionType;

  DiscreteFunction(const SpaceType& sp, VectorType& vec, const std::string nm = "gdt.discretefunction")
    : VectorProviderBaseType(vec)
    , BaseType(sp, VectorProviderBaseType::storage_access(), nm)
  {
  }

  DiscreteFunction(const SpaceType& sp, VectorType&& vec, const std::string nm = "gdt.discretefunction")
    : VectorProviderBaseType(vec)
    , BaseType(sp, VectorProviderBaseType::storage_access(), nm)
  {
  }

  DiscreteFunction(const SpaceType& sp, const std::string nm = "gdt.discretefunction")
    : VectorProviderBaseType(new VectorType(sp.mapper().size()))
    , BaseType(sp, VectorProviderBaseType::storage_access(), nm)
  {
  }

  // manual copy ctor needed bc. of the storage provider
  DiscreteFunction(const ThisType& other)
    : VectorProviderBaseType(new VectorType(other.vector()))
    , BaseType(other.space(), VectorProviderBaseType::storage_access(), other.name())
  {
  }

  // manual move ctor needed bc. of the storage provider
  DiscreteFunction(ThisType&& source)
    : VectorProviderBaseType(new VectorType(source.vector()))
    , BaseType(source.space(), VectorProviderBaseType::storage_access(), source.name())
  {
  }

  virtual ~DiscreteFunction()
  {
  }

  ThisType& operator=(const ThisType& other) = delete;

  virtual ThisType* copy() const override
  {
    return new ThisType(*this);
  }

  using BaseType::vector;

  VectorType& vector()
  {
    return this->storage_access();
  }

  using BaseType::local_discrete_function;

  std::unique_ptr<LocalDiscreteFunctionType> local_discrete_function(const EntityType& entity)
  {
    assert(space_->grid_view().indexSet().contains(entity));
    return DSC::make_unique<LocalDiscreteFunctionType>(*space_, this->storage_access(), entity);
  }

private:
  using BaseType::space_;
}; // class DiscreteFunction

template <class SpaceType, class VectorType>
ConstDiscreteFunction<SpaceType, VectorType>
make_const_discrete_function(const SpaceType& space, const VectorType& vector,
                             const std::string nm = "gdt.constdiscretefunction")
{
  return ConstDiscreteFunction<SpaceType, VectorType>(space, vector, nm);
}

template <class SpaceType, class VectorType>
DiscreteFunction<SpaceType, VectorType> make_discrete_function(const SpaceType& space, VectorType& vector,
                                                               const std::string nm = "gdt.discretefunction")
{
  return DiscreteFunction<SpaceType, VectorType>(space, vector, nm);
}

template <class VectorType, class SpaceType>
DiscreteFunction<SpaceType, VectorType> make_discrete_function(const SpaceType& space,
                                                               const std::string nm = "gdt.discretefunction")
{
  return DiscreteFunction<SpaceType, VectorType>(space, nm);
}

namespace internal {

template <class D>
struct is_const_discrete_function_helper
{
  DSC_has_typedef_initialize_once(SpaceType) DSC_has_typedef_initialize_once(VectorType)

      static const bool is_candidate = DSC_has_typedef(SpaceType)<D>::value && DSC_has_typedef(SpaceType)<D>::value;
};

} // namespace internal

template <class D, bool candidate = internal::is_const_discrete_function_helper<D>::is_candidate>
struct is_const_discrete_function
    : public std::is_base_of<ConstDiscreteFunction<typename D::SpaceType, typename D::VectorType>, D>
{
};

template <class D>
struct is_const_discrete_function<D, false> : public std::false_type
{
};

template <class D, bool candidate = internal::is_const_discrete_function_helper<D>::is_candidate>
struct is_discrete_function : public std::is_base_of<DiscreteFunction<typename D::SpaceType, typename D::VectorType>, D>
{
};

template <class D>
struct is_discrete_function<D, false> : public std::false_type
{
};

} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_DISCRETEFUNCTION_DEFAULT_HH
<commit_msg>[discretefunction.default] minor update and a little docu<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//
// Contributors: Kirsten Weber

#ifndef DUNE_GDT_DISCRETEFUNCTION_DEFAULT_HH
#define DUNE_GDT_DISCRETEFUNCTION_DEFAULT_HH

#include <memory>
#include <type_traits>

#include <dune/common/exceptions.hh>
#include <dune/common/fvector.hh>

#include <dune/grid/io/file/vtk.hh>

#include <dune/stuff/la/container/interfaces.hh>
#include <dune/stuff/functions/interfaces.hh>
#include <dune/stuff/common/memory.hh>

#include <dune/gdt/spaces/interface.hh>

#include "local.hh"

namespace Dune {
namespace GDT {

template <class SpaceImp, class VectorImp>
class ConstDiscreteFunction
    : public Stuff::LocalizableFunctionInterface<typename SpaceImp::EntityType, typename SpaceImp::DomainFieldType,
                                                 SpaceImp::dimDomain, typename SpaceImp::RangeFieldType,
                                                 SpaceImp::dimRange, SpaceImp::dimRangeCols>
{
  static_assert(is_space<SpaceImp>::value, "SpaceImp has to be derived from SpaceInterface!");
  static_assert(Stuff::LA::is_vector<VectorImp>::value, "VectorImp has to be derived from Stuff::LA::VectorInterface!");
  static_assert(std::is_same<typename SpaceImp::RangeFieldType, typename VectorImp::ScalarType>::value,
                "Types do not match!");
  typedef Stuff::LocalizableFunctionInterface<typename SpaceImp::EntityType, typename SpaceImp::DomainFieldType,
                                              SpaceImp::dimDomain, typename SpaceImp::RangeFieldType,
                                              SpaceImp::dimRange, SpaceImp::dimRangeCols> BaseType;
  typedef ConstDiscreteFunction<SpaceImp, VectorImp> ThisType;

public:
  typedef SpaceImp SpaceType;
  typedef VectorImp VectorType;
  typedef typename BaseType::EntityType EntityType;
  typedef typename BaseType::LocalfunctionType LocalfunctionType;

  typedef ConstLocalDiscreteFunction<SpaceType, VectorType> ConstLocalDiscreteFunctionType;

  ConstDiscreteFunction(const SpaceType& sp, const VectorType& vec, const std::string nm = "gdt.constdiscretefunction")
    : space_(sp)
    , vector_(vec)
    , name_(nm)
  {
    assert(vector_.size() == space_->mapper().size() && "Given vector has wrong size!");
  }

  ConstDiscreteFunction(const ThisType& other)
    : space_(other.space())
    , vector_(other.vector_)
    , name_(other.name_)
  {
  }

  ConstDiscreteFunction(ThisType&& source)
    : space_(source.space())
    , vector_(source.vector_)
    , name_(source.name_)
  {
  }

  virtual ~ConstDiscreteFunction()
  {
  }

  ThisType& operator=(const ThisType& other) = delete;

  virtual ThisType* copy() const override
  {
    return new ThisType(*this);
  }

  virtual std::string name() const override
  {
    return name_;
  }

  const SpaceType& space() const
  {
    return *space_;
  }

  const VectorType& vector() const
  {
    return vector_;
  }

  std::unique_ptr<ConstLocalDiscreteFunctionType> local_discrete_function(const EntityType& entity) const
  {
    assert(space_->grid_view().indexSet().contains(entity));
    return DSC::make_unique<ConstLocalDiscreteFunctionType>(*space_, vector_, entity);
  }

  virtual std::unique_ptr<LocalfunctionType> local_function(const EntityType& entity) const override
  {
    return local_discrete_function(entity);
  }

  void visualize(const std::string filename, const bool subsampling = (SpaceType::polOrder > 1),
                 const VTK::OutputType vtk_output_type = VTK::appendedraw) const
  {
    BaseType::template visualize<typename SpaceType::GridViewType>(
        space().grid_view(), filename, subsampling, vtk_output_type);
  } // ... visualize(...)

  bool dofs_valid() const
  {
    return vector().valid();
  }

protected:
  const DS::PerThreadValue<SpaceType> space_;

private:
  const VectorType& vector_;
  const std::string name_;
}; // class ConstDiscreteFunction

template <class SpaceImp, class VectorImp>
class DiscreteFunction : Stuff::Common::StorageProvider<VectorImp>, public ConstDiscreteFunction<SpaceImp, VectorImp>
{
  typedef Stuff::Common::StorageProvider<VectorImp> VectorProviderBaseType;
  typedef ConstDiscreteFunction<SpaceImp, VectorImp> BaseType;
  typedef DiscreteFunction<SpaceImp, VectorImp> ThisType;

public:
  typedef typename BaseType::SpaceType SpaceType;
  typedef typename BaseType::VectorType VectorType;
  typedef typename BaseType::EntityType EntityType;
  typedef typename BaseType::LocalfunctionType LocalfunctionType;

  typedef LocalDiscreteFunction<SpaceType, VectorType> LocalDiscreteFunctionType;

  DiscreteFunction(const SpaceType& sp, VectorType& vec, const std::string nm = "gdt.discretefunction")
    : VectorProviderBaseType(vec)
    , BaseType(sp, VectorProviderBaseType::storage_access(), nm)
  {
  }

  DiscreteFunction(const SpaceType& sp, VectorType&& vec, const std::string nm = "gdt.discretefunction")
    : VectorProviderBaseType(vec)
    , BaseType(sp, VectorProviderBaseType::storage_access(), nm)
  {
  }

  DiscreteFunction(const SpaceType& sp, const std::string nm = "gdt.discretefunction")
    : VectorProviderBaseType(new VectorType(sp.mapper().size()))
    , BaseType(sp, VectorProviderBaseType::storage_access(), nm)
  {
  }

  // manual copy ctor needed bc. of the storage provider
  DiscreteFunction(const ThisType& other)
    : VectorProviderBaseType(new VectorType(other.vector()))
    , BaseType(other.space(), VectorProviderBaseType::storage_access(), other.name())
  {
  }

  // manual move ctor needed bc. of the storage provider
  DiscreteFunction(ThisType&& source)
    : VectorProviderBaseType(new VectorType(source.vector()))
    , BaseType(source.space(), VectorProviderBaseType::storage_access(), source.name())
  {
  }

  virtual ~DiscreteFunction()
  {
  }

  ThisType& operator=(const ThisType& other) = delete;

  virtual ThisType* copy() const override
  {
    return new ThisType(*this);
  }

  using BaseType::vector;

  VectorType& vector()
  {
    return this->storage_access();
  }

  using BaseType::local_discrete_function;

  std::unique_ptr<LocalDiscreteFunctionType> local_discrete_function(const EntityType& entity)
  {
    assert(space_->grid_view().indexSet().contains(entity));
    return DSC::make_unique<LocalDiscreteFunctionType>(*space_, this->storage_access(), entity);
  }

private:
  using BaseType::space_;
}; // class DiscreteFunction

template <class SpaceType, class VectorType>
ConstDiscreteFunction<SpaceType, VectorType>
make_const_discrete_function(const SpaceType& space, const VectorType& vector,
                             const std::string nm = "gdt.constdiscretefunction")
{
  return ConstDiscreteFunction<SpaceType, VectorType>(space, vector, nm);
}

template <class SpaceType, class VectorType>
typename std::enable_if<is_space<SpaceType>::value && Stuff::LA::is_vector<VectorType>::value,
                        DiscreteFunction<SpaceType, VectorType>>::type
make_discrete_function(const SpaceType& space, VectorType& vector, const std::string nm = "gdt.discretefunction")
{
  return DiscreteFunction<SpaceType, VectorType>(space, vector, nm);
}

/**
 * This can be used like \code
auto discrete_function = make_discrete_function< VectorType >(space);
\endcode
 */
template <class VectorType, class SpaceType>
DiscreteFunction<SpaceType, VectorType> make_discrete_function(const SpaceType& space,
                                                               const std::string nm = "gdt.discretefunction")
{
  return DiscreteFunction<SpaceType, VectorType>(space, nm);
}

namespace internal {

template <class D>
struct is_const_discrete_function_helper
{
  DSC_has_typedef_initialize_once(SpaceType) DSC_has_typedef_initialize_once(VectorType)

      static const bool is_candidate = DSC_has_typedef(SpaceType)<D>::value && DSC_has_typedef(SpaceType)<D>::value;
};

} // namespace internal

template <class D, bool candidate = internal::is_const_discrete_function_helper<D>::is_candidate>
struct is_const_discrete_function
    : public std::is_base_of<ConstDiscreteFunction<typename D::SpaceType, typename D::VectorType>, D>
{
};

template <class D>
struct is_const_discrete_function<D, false> : public std::false_type
{
};

template <class D, bool candidate = internal::is_const_discrete_function_helper<D>::is_candidate>
struct is_discrete_function : public std::is_base_of<DiscreteFunction<typename D::SpaceType, typename D::VectorType>, D>
{
};

template <class D>
struct is_discrete_function<D, false> : public std::false_type
{
};

} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_DISCRETEFUNCTION_DEFAULT_HH
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_LOCALOPERATOR_INTERFACES_HH
#define DUNE_GDT_LOCALOPERATOR_INTERFACES_HH

#include <vector>

#include <dune/common/dynmatrix.hh>

#include <dune/stuff/common/crtp.hh>
#include <dune/stuff/common/type_utils.hh>
#include <dune/stuff/functions/interfaces.hh>

#include <dune/gdt/discretefunction/local.hh>

namespace Dune {
namespace GDT {

template <class Traits>
class LocalOperatorInterface : public Stuff::CRTPInterface<LocalOperatorInterface<Traits>, Traits>
{
public:
  typedef typename Traits::derived_type derived_type;

  /**
   * \brief Applies the local operator.
   * \param source Should be a Stuff::LocalizableFunctionInterface or a ConstDiscreteFunction.
   */
  template <class SourceType, class RangeSpaceType, class VectorType>
  void apply(const SourceType& source, LocalDiscreteFunction<RangeSpaceType, VectorType>& local_range) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp().apply(source, local_range));
  }
}; // class LocalVolumeTwoFormInterface

template <class Traits>
class LocalVolumeTwoFormInterface : public Stuff::CRTPInterface<LocalVolumeTwoFormInterface<Traits>, Traits>
{
public:
  typedef typename Traits::derived_type derived_type;

  /**
   *  \brief Applies the local operator as a two-form.
   *  \tparam T       Traits of the test Stuff::LocalfunctionSetInterface implementation
   *  \tparam A       Traits of the ansatz Stuff::LocalfunctionSetInterface implementation
   *  \tparam D       DomainFieldType
   *  \tparam d       dimDomain
   *  \tparam R       RangeFieldType
   *  \tparam r{T,A}  dimRange of the of the {test_base,ansatz_base}
   *  \tparam rC{T,a} dimRangeCols of the {test_base,ansatz_base}
   */
  template <class T, class A, class D, size_t d, class R, size_t rT, size_t rCT, size_t rA, size_t rCA>
  void apply2(const Stuff::LocalfunctionSetInterface<T, D, d, R, rT, rCT>& test_base,
              const Stuff::LocalfunctionSetInterface<A, D, d, R, rA, rCA>& ansatz_base,
              Dune::DynamicMatrix<R>& ret) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp().apply2(test_base, ansatz_base, ret));
  }
}; // class LocalVolumeTwoFormInterface

template <class Traits>
class LocalCouplingTwoFormInterface : public Stuff::CRTPInterface<LocalCouplingTwoFormInterface<Traits>, Traits>
{
public:
  typedef typename Traits::derived_type derived_type;

  /**
   *  \brief Applies the local operator associated with inner faces as a two-form.
   *  \tparam TE      Traits of the entity test Stuff::LocalfunctionSetInterface implementation
   *  \tparam AE      Traits of the entity ansatz Stuff::LocalfunctionSetInterface implementation
   *  \tparam TN      Traits of the neighbor test Stuff::LocalfunctionSetInterface implementation
   *  \tparam AN      Traits of the neighbor ansatz Stuff::LocalfunctionSetInterface implementation
   *  \tparam IntersectionType
   *  \tparam D       DomainFieldType
   *  \tparam d       dimDomain
   *  \tparam R       RangeFieldType
   *  \tparam r{T,A}  dimRange of the of the {test_base*,ansatz_base*}
   *  \tparam rC{T,a} dimRangeCols of the {test_base*,ansatz_base*}
   */
  template <class TE, class AE, class TN, class AN, class IntersectionType, class D, size_t d, class R, size_t rT,
            size_t rCT, size_t rA, size_t rCA>
  void apply2(const Stuff::LocalfunctionSetInterface<TE, D, d, R, rT, rCT>& test_base_entity,
              const Stuff::LocalfunctionSetInterface<AE, D, d, R, rA, rCA>& ansatz_base_entity,
              const Stuff::LocalfunctionSetInterface<TN, D, d, R, rT, rCT>& test_base_neighbor,
              const Stuff::LocalfunctionSetInterface<AN, D, d, R, rA, rCA>& ansatz_base_neighbor,
              const IntersectionType& intersection, Dune::DynamicMatrix<R>& entityEntityRet,
              Dune::DynamicMatrix<R>& neighborNeighborRet, Dune::DynamicMatrix<R>& entityNeighborRet,
              Dune::DynamicMatrix<R>& neighborEntityRet) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp().apply2(test_base_entity,
                                              ansatz_base_entity,
                                              test_base_neighbor,
                                              ansatz_base_neighbor,
                                              intersection,
                                              entityEntityRet,
                                              neighborNeighborRet,
                                              entityNeighborRet,
                                              neighborEntityRet));
  }
}; // class LocalCouplingTwoFormInterface

namespace internal {

template <class Tt>
struct is_local_operator_helper
{
  DSC_has_typedef_initialize_once(Traits)

      static const bool is_candidate = DSC_has_typedef(Traits)<Tt>::value;
};

template <class Tt>
struct is_local_volume_twoform_helper
{
  DSC_has_typedef_initialize_once(Traits)

      static const bool is_candidate = DSC_has_typedef(Traits)<Tt>::value;
};

} // namespace internal

template <class T, bool candidate = internal::is_local_operator_helper<T>::is_candidate>
struct is_local_operator : public std::is_base_of<LocalOperatorInterface<typename T::Traits>, T>
{
};

template <class T>
struct is_local_operator<T, false> : public std::false_type
{
};

template <class T, bool candidate = internal::is_local_volume_twoform_helper<T>::is_candidate>
struct is_local_volume_twoform : public std::is_base_of<LocalVolumeTwoFormInterface<typename T::Traits>, T>
{
};

template <class T>
struct is_local_volume_twoform<T, false> : public std::false_type
{
};

} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_LOCALOPERATOR_INTERFACES_HH
<commit_msg>[localoperator.interfaces] add first draft of LocalBoundaryTwoFormInterface<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_LOCALOPERATOR_INTERFACES_HH
#define DUNE_GDT_LOCALOPERATOR_INTERFACES_HH

#include <vector>

#include <dune/common/dynmatrix.hh>

#include <dune/stuff/common/crtp.hh>
#include <dune/stuff/common/type_utils.hh>
#include <dune/stuff/functions/interfaces.hh>

#include <dune/gdt/discretefunction/local.hh>

namespace Dune {
namespace GDT {

template <class Traits>
class LocalOperatorInterface : public Stuff::CRTPInterface<LocalOperatorInterface<Traits>, Traits>
{
public:
  typedef typename Traits::derived_type derived_type;

  /**
   * \brief Applies the local operator.
   * \param source Should be a Stuff::LocalizableFunctionInterface or a ConstDiscreteFunction.
   */
  template <class SourceType, class RangeSpaceType, class VectorType>
  void apply(const SourceType& source, LocalDiscreteFunction<RangeSpaceType, VectorType>& local_range) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp().apply(source, local_range));
  }
}; // class LocalVolumeTwoFormInterface

template <class Traits>
class LocalVolumeTwoFormInterface : public Stuff::CRTPInterface<LocalVolumeTwoFormInterface<Traits>, Traits>
{
public:
  typedef typename Traits::derived_type derived_type;

  /**
   *  \brief Applies the local operator as a two-form.
   *  \tparam T       Traits of the test Stuff::LocalfunctionSetInterface implementation
   *  \tparam A       Traits of the ansatz Stuff::LocalfunctionSetInterface implementation
   *  \tparam D       DomainFieldType
   *  \tparam d       dimDomain
   *  \tparam R       RangeFieldType
   *  \tparam r{T,A}  dimRange of the of the {test_base,ansatz_base}
   *  \tparam rC{T,a} dimRangeCols of the {test_base,ansatz_base}
   */
  template <class T, class A, class D, size_t d, class R, size_t rT, size_t rCT, size_t rA, size_t rCA>
  void apply2(const Stuff::LocalfunctionSetInterface<T, D, d, R, rT, rCT>& test_base,
              const Stuff::LocalfunctionSetInterface<A, D, d, R, rA, rCA>& ansatz_base,
              Dune::DynamicMatrix<R>& ret) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp().apply2(test_base, ansatz_base, ret));
  }
}; // class LocalVolumeTwoFormInterface

template <class Traits>
class LocalCouplingTwoFormInterface : public Stuff::CRTPInterface<LocalCouplingTwoFormInterface<Traits>, Traits>
{
public:
  typedef typename Traits::derived_type derived_type;

  /**
   *  \brief Applies the local operator associated with inner faces as a two-form.
   *  \tparam TE      Traits of the entity test Stuff::LocalfunctionSetInterface implementation
   *  \tparam AE      Traits of the entity ansatz Stuff::LocalfunctionSetInterface implementation
   *  \tparam TN      Traits of the neighbor test Stuff::LocalfunctionSetInterface implementation
   *  \tparam AN      Traits of the neighbor ansatz Stuff::LocalfunctionSetInterface implementation
   *  \tparam IntersectionType
   *  \tparam D       DomainFieldType
   *  \tparam d       dimDomain
   *  \tparam R       RangeFieldType
   *  \tparam r{T,A}  dimRange of the of the {test_base*,ansatz_base*}
   *  \tparam rC{T,a} dimRangeCols of the {test_base*,ansatz_base*}
   */
  template <class TE, class AE, class TN, class AN, class IntersectionType, class D, size_t d, class R, size_t rT,
            size_t rCT, size_t rA, size_t rCA>
  void apply2(const Stuff::LocalfunctionSetInterface<TE, D, d, R, rT, rCT>& test_base_entity,
              const Stuff::LocalfunctionSetInterface<AE, D, d, R, rA, rCA>& ansatz_base_entity,
              const Stuff::LocalfunctionSetInterface<TN, D, d, R, rT, rCT>& test_base_neighbor,
              const Stuff::LocalfunctionSetInterface<AN, D, d, R, rA, rCA>& ansatz_base_neighbor,
              const IntersectionType& intersection, Dune::DynamicMatrix<R>& entityEntityRet,
              Dune::DynamicMatrix<R>& neighborNeighborRet, Dune::DynamicMatrix<R>& entityNeighborRet,
              Dune::DynamicMatrix<R>& neighborEntityRet) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp().apply2(test_base_entity,
                                              ansatz_base_entity,
                                              test_base_neighbor,
                                              ansatz_base_neighbor,
                                              intersection,
                                              entityEntityRet,
                                              neighborNeighborRet,
                                              entityNeighborRet,
                                              neighborEntityRet));
  }
}; // class LocalCouplingTwoFormInterface

template <class Traits>
class LocalBoundaryTwoFormInterface : public Stuff::CRTPInterface<LocalBoundaryTwoFormInterface<Traits>, Traits>
{
public:
  typedef typename Traits::derived_type derived_type;

  /**
   *  \brief Applies the local operator associated with boundary faces as a two-form.
   *  \tparam T       Traits of the test Stuff::LocalfunctionSetInterface implementation
   *  \tparam A       Traits of the ansatz Stuff::LocalfunctionSetInterface implementation
   *  \tparam IntersectionType
   *  \tparam D       DomainFieldType
   *  \tparam d       dimDomain
   *  \tparam R       RangeFieldType
   *  \tparam r{T,A}  dimRange of the of the {test_base,ansatz_base}
   *  \tparam rC{T,a} dimRangeCols of the {test_base,ansatz_base}
   */
  template <class T, class A, class IntersectionType, class D, size_t d, class R, size_t rT, size_t rCT, size_t rA,
            size_t rCA>
  void apply2(const Stuff::LocalfunctionSetInterface<T, D, d, R, rT, rCT>& test_base,
              const Stuff::LocalfunctionSetInterface<A, D, d, R, rA, rCA>& ansatz_base,
              const IntersectionType& intersection, Dune::DynamicMatrix<R>& ret) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp().apply2(test_base, ansatz_base, intersection, ret));
  }
}; // class LocalBoundaryTwoFormInterface

namespace internal {

template <class Tt>
struct is_local_operator_helper
{
  DSC_has_typedef_initialize_once(Traits)

      static const bool is_candidate = DSC_has_typedef(Traits)<Tt>::value;
};

template <class Tt>
struct is_local_volume_twoform_helper
{
  DSC_has_typedef_initialize_once(Traits)

      static const bool is_candidate = DSC_has_typedef(Traits)<Tt>::value;
};

} // namespace internal

template <class T, bool candidate = internal::is_local_operator_helper<T>::is_candidate>
struct is_local_operator : public std::is_base_of<LocalOperatorInterface<typename T::Traits>, T>
{
};

template <class T>
struct is_local_operator<T, false> : public std::false_type
{
};

template <class T, bool candidate = internal::is_local_volume_twoform_helper<T>::is_candidate>
struct is_local_volume_twoform : public std::is_base_of<LocalVolumeTwoFormInterface<typename T::Traits>, T>
{
};

template <class T>
struct is_local_volume_twoform<T, false> : public std::false_type
{
};

} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_LOCALOPERATOR_INTERFACES_HH
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_MAPPER_DEFAULT_PRODUCTFV_HH
#define DUNE_GDT_MAPPER_DEFAULT_PRODUCTFV_HH

#include <dune/common/dynvector.hh>

#include <dune/stuff/common/debug.hh>
#include <dune/stuff/common/type_utils.hh>

#include "../../mapper/interface.hh"
#include "fv.hh"

namespace Dune {
namespace GDT {
namespace Mapper {

// forward
template <class GridViewImp, size_t rangeDim = 1, size_t rangeDimCols = 1>
class ProductFiniteVolume
{
  static_assert(AlwaysFalse<GridViewImp>::value, "Not available for these dimensions!");
};

namespace internal {

template <class GridViewImp, size_t rangeDim, size_t rangeDimCols>
class ProductFiniteVolumeTraits : internal::FiniteVolumeTraits<GridViewImp, rangeDim, rangeDimCols>
{
public:
  typedef ProductFiniteVolume<GridViewType, rangeDim, rangeDimCols> derived_type;
};

} // namespace internal

template <class GridViewImp, size_t rangeDim>
class ProductFiniteVolume<GridViewImp, rangeDim, 1>
    : public ProductMapperInterface<internal::ProductFiniteVolumeTraits<GridViewImp, rangeDim, 1>>,
      public FiniteVolume<GridViewImp, rangeDim, 1>
{
  typedef ProductMapperInterface<internal::ProductFiniteVolumeTraits<GridViewImp, rangeDim, 1>> InterfaceType;
  typedef FiniteVolume<GridViewImp, rangeDim, 1> BaseType;
  static const size_t dimRange = rangeDim;

public:
  typedef internal::ProductFiniteVolumeTraits<GridViewImp, rangeDim, 1> Traits;
  typedef typename Traits::GridViewType GridViewType;
  typedef typename Traits::BackendType BackendType;
  typedef typename Traits::EntityType EntityType;

  ProductFiniteVolume(const GridViewType& grid_view)
    : BaseType(grid_view)
  {
  }

  using BaseType::backend;
  using BaseType::size;
  using BaseType::numDofs;
  using BaseType::maxNumDofs;
  using BaseType::globalIndices;

  Dune::DynamicVector<size_t> globalIndices(const size_t factor_index, const EntityType& entity) const
  {
    Dune::DynamicVector<size_t> ret(numDofs(entity), 0);
    globalIndices(factor_index, entity, ret);
    return ret;
  }

  size_t mapToGlobal(const size_t factor_index, const EntityType& entity,
                     const size_t& UNUSED_UNLESS_DEBUG(localIndex)) const
  {
    assert(localIndex == 0);
    assert(factor_index < numDofs(entity));
    return (dimRange * (backend_.index(entity))) + factor_index;
  }
}; // class ProductFiniteVolume< ..., rangeDim, 1 >

} // namespace Mapper
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_MAPPER_DEFAULT_PRODUCTFV_HH
<commit_msg>[mapper.default.productvf] minor fixes<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_MAPPER_DEFAULT_PRODUCTFV_HH
#define DUNE_GDT_MAPPER_DEFAULT_PRODUCTFV_HH

#include <dune/common/dynvector.hh>

#include <dune/stuff/common/debug.hh>
#include <dune/stuff/common/type_utils.hh>

#include "../../mapper/interface.hh"
#include "fv.hh"

namespace Dune {
namespace GDT {
namespace Mapper {

// forward
template <class GridViewImp, size_t rangeDim = 1, size_t rangeDimCols = 1>
class ProductFiniteVolume
{
  static_assert(AlwaysFalse<GridViewImp>::value, "Not available for these dimensions!");
};

namespace internal {

template <class GridViewImp, size_t rangeDim, size_t rangeDimCols>
class ProductFiniteVolumeTraits : internal::FiniteVolumeTraits<GridViewImp, rangeDim, rangeDimCols>
{
public:
  typedef ProductFiniteVolume<GridViewImp, rangeDim, rangeDimCols> derived_type;
};

} // namespace internal

template <class GridViewImp, size_t rangeDim>
class ProductFiniteVolume<GridViewImp, rangeDim, 1>
    : public ProductMapperInterface<internal::ProductFiniteVolumeTraits<GridViewImp, rangeDim, 1>>,
      public FiniteVolume<GridViewImp, rangeDim, 1>
{
  typedef ProductMapperInterface<internal::ProductFiniteVolumeTraits<GridViewImp, rangeDim, 1>> InterfaceType;
  typedef FiniteVolume<GridViewImp, rangeDim, 1> BaseType;
  using BaseType::dimRange;

public:
  typedef internal::ProductFiniteVolumeTraits<GridViewImp, rangeDim, 1> Traits;
  using typename BaseType::GridViewType;
  using typename BaseType::EntityType;

  ProductFiniteVolume(const GridViewType& grid_view)
    : BaseType(grid_view)
  {
  }

  using BaseType::numDofs;
  using BaseType::globalIndices;

  Dune::DynamicVector<size_t> globalIndices(const size_t factor_index, const EntityType& entity) const
  {
    Dune::DynamicVector<size_t> ret(numDofs(entity), 0);
    globalIndices(factor_index, entity, ret);
    return ret;
  }

  size_t mapToGlobal(const size_t factor_index, const EntityType& entity,
                     const size_t& UNUSED_UNLESS_DEBUG(localIndex)) const
  {
    assert(localIndex == 0);
    assert(factor_index < numDofs(entity));
    return (dimRange * (backend_.index(entity))) + factor_index;
  }

private:
  using BaseType::backend_;
}; // class ProductFiniteVolume< ..., rangeDim, 1 >

} // namespace Mapper
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_MAPPER_DEFAULT_PRODUCTFV_HH
<|endoftext|>


<commit_before>#include <config.h>

#include "error_calc.hh"

#include <assert.h>
#include <boost/filesystem/fstream.hpp>
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <utility>

#include <dune/gdt/assembler/system.hh>
#include <dune/gdt/discretefunction/default.hh>
#include <dune/gdt/products/l2.hh>
#include <dune/gdt/products/h1.hh>

#include <dune/multiscale/common/traits.hh>
#include <dune/multiscale/common/grid_creation.hh>
#include <dune/multiscale/problems/base.hh>
#include <dune/multiscale/msfem/localsolution_proxy.hh>
#include <dune/multiscale/msfem/proxygridview.hh>
#include <dune/multiscale/msfem/fem_solver.hh>
#include <dune/multiscale/problems/selector.hh>
#include <dune/multiscale/tools/misc/outputparameter.hh>

#include <dune/stuff/common/filesystem.hh>
#include <dune/stuff/common/configuration.hh>
#include <dune/stuff/discretefunction/projection/heterogenous.hh>

using namespace Dune::Multiscale;

void solution_output(const CommonTraits::DiscreteFunctionType& msfem_solution) {
  using namespace Dune;

  Dune::Multiscale::OutputParameters outputparam;
  outputparam.set_prefix("msfem_solution_");
  msfem_solution.visualize(outputparam.fullpath(msfem_solution.name()));
}

void data_output(const CommonTraits::GridViewType& gridPart) {
  using namespace Dune;
  Dune::Multiscale::OutputParameters outputparam;

  if (Problem::getModelData()->hasExactSolution()) {
    const auto& u = Dune::Multiscale::Problem::getExactSolution();
    outputparam.set_prefix("exact_solution");
    u->visualize(gridPart, outputparam.fullpath(u->name()));
  }
}

Dune::Multiscale::ErrorCalculator::ErrorCalculator(const std::unique_ptr<LocalsolutionProxy>& msfem_solution,
                                                   CommonTraits::ConstDiscreteFunctionType* fem_solution)
  : msfem_solution_(msfem_solution)
  , fem_solution_(fem_solution)
{
  assert(fem_solution_);
}

ErrorCalculator::ErrorCalculator(const std::unique_ptr<LocalsolutionProxy> &msfem_solution)
  : msfem_solution_(msfem_solution)
  , fem_solution_(nullptr)
{
  assert(msfem_solution_);
  if (DSC_CONFIG_GET("msfem.fem_comparison", false)) {
    fem_solver_ = DSC::make_unique<Elliptic_FEM_Solver>();
    fem_solution_ = &fem_solver_->solve();
  }
}

std::map<std::string, double> Dune::Multiscale::ErrorCalculator::print(std::ostream& out) {
  using namespace Dune::GDT::Products;
  out << std::endl << "The L2 errors:" << std::endl << std::endl;

  const size_t over_integrate = 0; // <- would let the product use a higher quadrature order than needed

  typedef Stuff::Functions::Difference<Problem::ExactSolutionType, CommonTraits::ConstDiscreteFunctionType>
  DifferenceType;
  /// TODO only call assemble once
  const auto fine_grid = make_grids().second;
  CommonTraits::GridProviderType fine_grid_provider(*fine_grid);
  const CommonTraits::GdtSpaceType fine_space =
      CommonTraits::SpaceProviderType::create(fine_grid_provider, CommonTraits::st_gdt_grid_level);

  GDT::SystemAssembler<CommonTraits::SpaceType> system_assembler(fine_space);
  const auto& grid_view = fine_space.grid_view();

  std::map<std::string, double> csv;

  CommonTraits::DiscreteFunctionType fine_msfem_solution(fine_space, "MsFEM_Solution");
  if (msfem_solution_) {
    DS::MsFEMProjection::project(*msfem_solution_, fine_msfem_solution, msfem_solution_->search());
    if (DSC_CONFIG_GET("global.vtk_output", false)) {
      DSC_LOG_INFO_0 << "Solution output for MsFEM Solution." << std::endl;
      data_output(*fine_space.grid_view());
      solution_output(fine_msfem_solution);
    }
  }

  //! ----------------- compute L2- and H1- errors -------------------
  if (Problem::getModelData()->hasExactSolution()) {
    const auto& u = *DMP::getExactSolution();

    if (msfem_solution_) {
      const DifferenceType difference(u, fine_msfem_solution);
      L2Localizable<CommonTraits::GridViewType, DifferenceType> l2_error_product(*grid_view, difference,
                                                                                over_integrate);
      system_assembler.add(l2_error_product);
      H1SemiLocalizable<CommonTraits::GridViewType, DifferenceType> h1_semi_error_product(*grid_view, difference,
                                                                                over_integrate);
      system_assembler.add(h1_semi_error_product);
      system_assembler.tbb_assemble();

      const auto msfem_error = std::sqrt(l2_error_product.apply2());
      out << "|| u_msfem - u_exact ||_L2 =  " << msfem_error << std::endl;
      const auto h1_msfem_error = std::sqrt(h1_semi_error_product.apply2());
      out << "|| u_msfem - u_exact ||_H1s =  " << h1_msfem_error << std::endl << std::endl;

      csv["msfem_exact_L2"] = msfem_error;
      csv["msfem_exact_H1s"] = h1_msfem_error;
    }

    if (fem_solution_) {
      const DifferenceType difference(u, *fem_solution_);
      L2Localizable<CommonTraits::GridViewType, DifferenceType> l2_error_product(*grid_view, difference,
                                                                                over_integrate);
      system_assembler.add(l2_error_product);
      H1SemiLocalizable<CommonTraits::GridViewType, DifferenceType> h1_semi_error_product(*grid_view, difference,
                                                                                over_integrate);
      system_assembler.add(h1_semi_error_product);
      system_assembler.tbb_assemble();

      const auto fem_error = std::sqrt(l2_error_product.apply2());
      out << "|| u_fem - u_exact ||_L2 =  " << fem_error << std::endl;
      const auto h1_fem_error = std::sqrt(h1_semi_error_product.apply2());
      out << "|| u_fem - u_exact ||_H1s =  " << h1_fem_error << std::endl << std::endl;

      csv["fem_exact_L2"] = fem_error;
      csv["fem_exact_H1s"] = h1_fem_error;
    }
  }

  if (msfem_solution_ && fem_solution_) {

    typedef Stuff::Functions::Difference<CommonTraits::ConstDiscreteFunctionType,
                                         CommonTraits::ConstDiscreteFunctionType> DiscreteDifferenceType;
    const DiscreteDifferenceType difference(fine_msfem_solution, *fem_solution_);

    L2Localizable<CommonTraits::GridViewType, DiscreteDifferenceType> l2_error_product(*grid_view, difference,
                                                                                over_integrate);
    system_assembler.add(l2_error_product);
    L2Localizable<CommonTraits::GridViewType, CommonTraits::ConstDiscreteFunctionType> l2_msfem(
        *grid_view, fine_msfem_solution, over_integrate);
    system_assembler.add(l2_msfem);
    H1SemiLocalizable<CommonTraits::GridViewType, DiscreteDifferenceType> h1_semi_error_product(*grid_view, difference,
                                                                                over_integrate);
    system_assembler.add(h1_semi_error_product);
    system_assembler.tbb_assemble();

    const auto approx_msfem_error = std::sqrt(l2_error_product.apply2());
    const auto no = std::sqrt(l2_msfem.apply2());
    if (std::abs(no) > 1e-12)
      out << "|| u_msfem - u_fem ||_L2 / || u_msfem ||_L2 =  " << approx_msfem_error / no << std::endl;
    else
      out << "|| u_msfem - u_fem ||_L2 =  " << approx_msfem_error << std::endl;

    const auto h1_approx_msfem_error = std::sqrt(h1_semi_error_product.apply2());
    out << "|| u_msfem - u_fem ||_H1s =  " << h1_approx_msfem_error << std::endl << std::endl;

    csv["msfem_fem_L2"] = approx_msfem_error;
    csv["msfem_fem_H1s"] = h1_approx_msfem_error;
  }

  std::unique_ptr<boost::filesystem::ofstream> csvfile(
      DSC::make_ofstream(std::string(DSC_CONFIG_GET("global.datadir", "data/")) + std::string("/errors.csv")));
  const std::string sep(",");
  for (const auto& key_val : csv) {
    *csvfile << key_val.first << sep;
  }
  *csvfile << std::endl;
  for (const auto& key_val : csv) {
    *csvfile << key_val.second << sep;
  }
  *csvfile << std::endl;

  return csv;
}
<commit_msg>makes error clac usable w. and w/o fem solution again<commit_after>#include <config.h>

#include "error_calc.hh"

#include <assert.h>
#include <boost/filesystem/fstream.hpp>
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <utility>

#include <dune/gdt/assembler/system.hh>
#include <dune/gdt/discretefunction/default.hh>
#include <dune/gdt/products/l2.hh>
#include <dune/gdt/products/h1.hh>

#include <dune/multiscale/common/traits.hh>
#include <dune/multiscale/common/grid_creation.hh>
#include <dune/multiscale/problems/base.hh>
#include <dune/multiscale/msfem/localsolution_proxy.hh>
#include <dune/multiscale/msfem/proxygridview.hh>
#include <dune/multiscale/msfem/fem_solver.hh>
#include <dune/multiscale/problems/selector.hh>
#include <dune/multiscale/tools/misc/outputparameter.hh>

#include <dune/stuff/common/filesystem.hh>
#include <dune/stuff/common/configuration.hh>
#include <dune/stuff/discretefunction/projection/heterogenous.hh>

using namespace Dune::Multiscale;

void solution_output(const CommonTraits::DiscreteFunctionType& msfem_solution) {
  using namespace Dune;

  Dune::Multiscale::OutputParameters outputparam;
  outputparam.set_prefix("msfem_solution_");
  msfem_solution.visualize(outputparam.fullpath(msfem_solution.name()));
}

void data_output(const CommonTraits::GridViewType& gridPart) {
  using namespace Dune;
  Dune::Multiscale::OutputParameters outputparam;

  if (Problem::getModelData()->hasExactSolution()) {
    const auto& u = Dune::Multiscale::Problem::getExactSolution();
    outputparam.set_prefix("exact_solution");
    u->visualize(gridPart, outputparam.fullpath(u->name()));
  }
}

Dune::Multiscale::ErrorCalculator::ErrorCalculator(const std::unique_ptr<LocalsolutionProxy>& msfem_solution,
                                                   CommonTraits::ConstDiscreteFunctionType* fem_solution)
  : msfem_solution_(msfem_solution)
  , fem_solution_(fem_solution)
{
  assert(fem_solution_);
}

ErrorCalculator::ErrorCalculator(const std::unique_ptr<LocalsolutionProxy> &msfem_solution)
  : msfem_solution_(msfem_solution)
  , fem_solution_(nullptr)
{
  assert(msfem_solution_);
  if (DSC_CONFIG_GET("msfem.fem_comparison", false)) {
    fem_solver_ = DSC::make_unique<Elliptic_FEM_Solver>();
    fem_solution_ = &fem_solver_->solve();
  }
}

std::map<std::string, double> Dune::Multiscale::ErrorCalculator::print(std::ostream& out) {
  using namespace Dune::GDT::Products;
  out << std::endl << "The L2 errors:" << std::endl << std::endl;

  const size_t over_integrate = 0; // <- would let the product use a higher quadrature order than needed

  typedef Stuff::Functions::Difference<Problem::ExactSolutionType, CommonTraits::ConstDiscreteFunctionType>
  DifferenceType;
  /// TODO only call assemble once
  const auto fine_grid = make_grids().second;
  CommonTraits::GridProviderType fine_grid_provider(*fine_grid);
  const auto fine_space_ptr = //fem_solution_->space();
      CommonTraits::SpaceProviderType::create(fine_grid_provider, CommonTraits::st_gdt_grid_level);
  const auto& fine_space = fem_solution_ ? fem_solution_->space() : *fine_space_ptr;
  GDT::SystemAssembler<CommonTraits::SpaceType> system_assembler(fine_space);
  const auto& grid_view = fine_space.grid_view();

  std::map<std::string, double> csv;

  CommonTraits::DiscreteFunctionType fine_msfem_solution(fine_space, "MsFEM_Solution");
  if (msfem_solution_) {
    DS::MsFEMProjection::project(*msfem_solution_, fine_msfem_solution, msfem_solution_->search());
    if (DSC_CONFIG_GET("global.vtk_output", false)) {
      DSC_LOG_INFO_0 << "Solution output for MsFEM Solution." << std::endl;
      data_output(*fine_space.grid_view());
      solution_output(fine_msfem_solution);
    }
  }

  //! ----------------- compute L2- and H1- errors -------------------
  if (Problem::getModelData()->hasExactSolution()) {
    const auto& u = *DMP::getExactSolution();

    if (msfem_solution_) {
      const DifferenceType difference(u, fine_msfem_solution);
      L2Localizable<CommonTraits::GridViewType, DifferenceType> l2_error_product(*grid_view, difference,
                                                                                over_integrate);
      system_assembler.add(l2_error_product);
      H1SemiLocalizable<CommonTraits::GridViewType, DifferenceType> h1_semi_error_product(*grid_view, difference,
                                                                                over_integrate);
      system_assembler.add(h1_semi_error_product);
      system_assembler.tbb_assemble();

      const auto msfem_error = std::sqrt(l2_error_product.apply2());
      out << "|| u_msfem - u_exact ||_L2 =  " << msfem_error << std::endl;
      const auto h1_msfem_error = std::sqrt(h1_semi_error_product.apply2());
      out << "|| u_msfem - u_exact ||_H1s =  " << h1_msfem_error << std::endl << std::endl;

      csv["msfem_exact_L2"] = msfem_error;
      csv["msfem_exact_H1s"] = h1_msfem_error;
    }

    if (fem_solution_) {
      const DifferenceType difference(u, *fem_solution_);
      L2Localizable<CommonTraits::GridViewType, DifferenceType> l2_error_product(*grid_view, difference,
                                                                                over_integrate);
      system_assembler.add(l2_error_product);
      H1SemiLocalizable<CommonTraits::GridViewType, DifferenceType> h1_semi_error_product(*grid_view, difference,
                                                                                over_integrate);
      system_assembler.add(h1_semi_error_product);
      system_assembler.tbb_assemble();

      const auto fem_error = std::sqrt(l2_error_product.apply2());
      out << "|| u_fem - u_exact ||_L2 =  " << fem_error << std::endl;
      const auto h1_fem_error = std::sqrt(h1_semi_error_product.apply2());
      out << "|| u_fem - u_exact ||_H1s =  " << h1_fem_error << std::endl << std::endl;

      csv["fem_exact_L2"] = fem_error;
      csv["fem_exact_H1s"] = h1_fem_error;
    }
  }

  if (msfem_solution_ && fem_solution_) {

    typedef Stuff::Functions::Difference<CommonTraits::ConstDiscreteFunctionType,
                                         CommonTraits::ConstDiscreteFunctionType> DiscreteDifferenceType;
    const DiscreteDifferenceType difference(fine_msfem_solution, *fem_solution_);

    L2Localizable<CommonTraits::GridViewType, DiscreteDifferenceType> l2_error_product(*grid_view, difference,
                                                                                over_integrate);
    system_assembler.add(l2_error_product);
    L2Localizable<CommonTraits::GridViewType, CommonTraits::ConstDiscreteFunctionType> l2_msfem(
        *grid_view, fine_msfem_solution, over_integrate);
    system_assembler.add(l2_msfem);
    H1SemiLocalizable<CommonTraits::GridViewType, DiscreteDifferenceType> h1_semi_error_product(*grid_view, difference,
                                                                                over_integrate);
    system_assembler.add(h1_semi_error_product);
    system_assembler.tbb_assemble();

    const auto approx_msfem_error = std::sqrt(l2_error_product.apply2());
    const auto no = std::sqrt(l2_msfem.apply2());
    if (std::abs(no) > 1e-12)
      out << "|| u_msfem - u_fem ||_L2 / || u_msfem ||_L2 =  " << approx_msfem_error / no << std::endl;
    else
      out << "|| u_msfem - u_fem ||_L2 =  " << approx_msfem_error << std::endl;

    const auto h1_approx_msfem_error = std::sqrt(h1_semi_error_product.apply2());
    out << "|| u_msfem - u_fem ||_H1s =  " << h1_approx_msfem_error << std::endl << std::endl;

    csv["msfem_fem_L2"] = approx_msfem_error;
    csv["msfem_fem_H1s"] = h1_approx_msfem_error;
  }

  std::unique_ptr<boost::filesystem::ofstream> csvfile(
      DSC::make_ofstream(std::string(DSC_CONFIG_GET("global.datadir", "data/")) + std::string("/errors.csv")));
  const std::string sep(",");
  for (const auto& key_val : csv) {
    *csvfile << key_val.first << sep;
  }
  *csvfile << std::endl;
  for (const auto& key_val : csv) {
    *csvfile << key_val.second << sep;
  }
  *csvfile << std::endl;

  return csv;
}
<|endoftext|>


<commit_before>

#include "Object.h"

namespace Atlas
{

void	Object::walkTree(int nest, string name, const Object& list)
{
}

void	Object::dump(const Object& msg)
{
}

/** (List) insert an Object at this index */
bool    Object::insert(size_t ndx, const Object& val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.insert( ((VVec*)obj)->vv.begin()+ndx , val.obj );
	val.obj->incref();
	return true;
}

/** (List) insert an Int at this index */
bool    Object::insert(size_t ndx, int val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.insert(((VVec*)obj)->vv.begin()+ndx, new VNum(val));
	return true;
}

/** (List) insert an Long at this index */
bool    Object::insert(size_t ndx, long val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.insert( ((VVec*)obj)->vv.begin()+ndx, new VNum(val) );
	return true;
}

/** (List) insert a Float at this index */
bool    Object::insert(size_t ndx, double val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.insert(((VVec*)obj)->vv.begin()+ndx, new VNum(val));
	return true;
}

/** (List) insert a String at this index */
bool    Object::insert(size_t ndx, const string& val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.insert(((VVec*)obj)->vv.begin()+ndx, new VStr(val));
	return true;
}

/** (List) append an Object */
bool    Object::append(const Object& val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.push_back(val.obj);
	val.obj->incref();
	return true;
}

/** (List) append an Int */
bool    Object::append(int val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.push_back(new VNum(val));
	return true;
}

/** (List) append an Long */
bool    Object::append(long val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.push_back(new VNum(val));
	return true;
}

/** (List) append a Float */
bool    Object::append(double val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.push_back(new VNum(val));
	return true;
}

/** (List) append a String */
bool    Object::append(const string& val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.push_back(new VStr(val));
	return true;
}

/** (List) replace an Object at this index */
bool    Object::set(size_t ndx, const Object& src)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv[ndx] = src.obj;
	src.obj->incref();
	return true;
}

/** (List) replace an Int at this index */
bool    Object::set(size_t ndx, int val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv[ndx] = new VNum(val);
	return true;
}

/** (List) replace an Long at this index */
bool    Object::set(size_t ndx, long val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv[ndx] = new VNum(val);
	return true;
}

/** (List) replace a Float at this index */
bool    Object::set(size_t ndx, double val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv[ndx] = new VNum(val);
	return true;
}

/** (List) replace a String at this index */
bool    Object::set(size_t ndx, const string& val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv[ndx] = new VStr(val);
	return true;
}

/** (List) get an Object from this index */
bool    Object::get(size_t ndx, Object& src) const
{
	if (obj->rt != List) return false;
	src.obj->decref();
	src.obj = ((VVec*)obj)->vv[ndx];
	if (tmp == NULL) return false;
	src.obj->incref();
	return true;
}

/** (List) get an Int from this index */
bool    Object::get(size_t ndx, int& val) const
{
	if (obj->rt != List) return false;
	Variant* tmp = ((VVec*)obj)->vv[ndx];
	if (tmp == NULL) return false;
	if (tmp->rt !=Int) return false;
	val = ((VNum*)tmp)->lv;
	return true;
}

/** (List) get an Long from this index */
bool    Object::get(size_t ndx, long& val) const
{
	if (obj->rt != List) return false;
	Variant* tmp = ((VVec*)obj)->vv[ndx];
	if (tmp == NULL) return false;
	if (tmp->rt !=Int) return false;
	val = ((VNum*)tmp)->lv;
	return true;
}

/** (List) get a Float from this index */
bool    Object::get(size_t ndx, double& val) const
{
	if (obj->rt != List) return false;
	//if ((VVec*)obj->vv.size() <= ndx) return false;
	Variant* tmp = ((VVec*)obj)->vv[ndx];
	if (tmp == NULL) return false;
	if (tmp->rt != Float) return false;
	val = ((VNum*)tmp)->dv;
	return true;
}

/** (List) get a String from this index */
bool    Object::get(size_t ndx, string& val) const
{
	if (obj->rt != List) return false;
	//if ((VVec*)obj->vv.size() <= ndx) return false;
	Variant* tmp = ((VVec*)obj)->vv[ndx];
	if (tmp == NULL) return false;
	if (tmp->rt !=String) return false;
	val = ((VStr*)tmp)->st;
	return true;
}

/** (List) get an Object from this index with default */
bool	Object::get(size_t ndx, Object& val, Object& def) const
{
	val = def;
	return get(ndx,val);
}

/** (List) get an Int from this index */
bool    Object::get(size_t ndx, int& val, int def) const
{
	val = def;
	return get(ndx,val);
}

/** (List) get an Long from this index */
bool    Object::get(size_t ndx, long& val, long def) const
{
	val = def;
	return get(ndx,val);
}

/** (List) get a Float from this index */
bool    Object::get(size_t ndx, double& val, double def) const
{
	val = def;
	return get(ndx,val);
}

/** (List) get a String from this index */
bool    Object::get(size_t ndx, string& val, string& def) const
{
	val = def;
	return get(ndx,val);
}

} // end namespace atlas
<commit_msg>Atlas::Object more list handling fixes<commit_after>

#include "Object.h"

namespace Atlas
{

void	Object::walkTree(int nest, string name, const Object& list)
{
}

void	Object::dump(const Object& msg)
{
}

/** (List) insert an Object at this index */
bool    Object::insert(size_t ndx, const Object& val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.insert( ((VVec*)obj)->vv.begin()+ndx , val.obj );
	val.obj->incref();
	return true;
}

/** (List) insert an Int at this index */
bool    Object::insert(size_t ndx, int val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.insert(((VVec*)obj)->vv.begin()+ndx, new VNum(val));
	return true;
}

/** (List) insert an Long at this index */
bool    Object::insert(size_t ndx, long val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.insert( ((VVec*)obj)->vv.begin()+ndx, new VNum(val) );
	return true;
}

/** (List) insert a Float at this index */
bool    Object::insert(size_t ndx, double val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.insert(((VVec*)obj)->vv.begin()+ndx, new VNum(val));
	return true;
}

/** (List) insert a String at this index */
bool    Object::insert(size_t ndx, const string& val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.insert(((VVec*)obj)->vv.begin()+ndx, new VStr(val));
	return true;
}

/** (List) append an Object */
bool    Object::append(const Object& val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.push_back(val.obj);
	val.obj->incref();
	return true;
}

/** (List) append an Int */
bool    Object::append(int val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.push_back(new VNum(val));
	return true;
}

/** (List) append an Long */
bool    Object::append(long val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.push_back(new VNum(val));
	return true;
}

/** (List) append a Float */
bool    Object::append(double val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.push_back(new VNum(val));
	return true;
}

/** (List) append a String */
bool    Object::append(const string& val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv.push_back(new VStr(val));
	return true;
}

/** (List) replace an Object at this index */
bool    Object::set(size_t ndx, const Object& src)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv[ndx] = src.obj;
	src.obj->incref();
	return true;
}

/** (List) replace an Int at this index */
bool    Object::set(size_t ndx, int val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv[ndx] = new VNum(val);
	return true;
}

/** (List) replace an Long at this index */
bool    Object::set(size_t ndx, long val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv[ndx] = new VNum(val);
	return true;
}

/** (List) replace a Float at this index */
bool    Object::set(size_t ndx, double val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv[ndx] = new VNum(val);
	return true;
}

/** (List) replace a String at this index */
bool    Object::set(size_t ndx, const string& val)
{
	if (obj->rt != List) return false;
	((VVec*)obj)->vv[ndx] = new VStr(val);
	return true;
}

/** (List) get an Object from this index */
bool    Object::get(size_t ndx, Object& src) const
{
	if (obj->rt != List) return false;
	Variant* tmp = ((VVec*)obj)->vv[ndx];
	if (tmp == NULL) return false;
	src.obj->decref();
	src.obj = tmp;
	src.obj->incref();
	return true;
}

/** (List) get an Int from this index */
bool    Object::get(size_t ndx, int& val) const
{
	if (obj->rt != List) return false;
	Variant* tmp = ((VVec*)obj)->vv[ndx];
	if (tmp == NULL) return false;
	if (tmp->rt !=Int) return false;
	val = ((VNum*)tmp)->lv;
	return true;
}

/** (List) get an Long from this index */
bool    Object::get(size_t ndx, long& val) const
{
	if (obj->rt != List) return false;
	Variant* tmp = ((VVec*)obj)->vv[ndx];
	if (tmp == NULL) return false;
	if (tmp->rt !=Int) return false;
	val = ((VNum*)tmp)->lv;
	return true;
}

/** (List) get a Float from this index */
bool    Object::get(size_t ndx, double& val) const
{
	if (obj->rt != List) return false;
	//if ((VVec*)obj->vv.size() <= ndx) return false;
	Variant* tmp = ((VVec*)obj)->vv[ndx];
	if (tmp == NULL) return false;
	if (tmp->rt != Float) return false;
	val = ((VNum*)tmp)->dv;
	return true;
}

/** (List) get a String from this index */
bool    Object::get(size_t ndx, string& val) const
{
	if (obj->rt != List) return false;
	//if ((VVec*)obj->vv.size() <= ndx) return false;
	Variant* tmp = ((VVec*)obj)->vv[ndx];
	if (tmp == NULL) return false;
	if (tmp->rt !=String) return false;
	val = ((VStr*)tmp)->st;
	return true;
}

/** (List) get an Object from this index with default */
bool	Object::get(size_t ndx, Object& val, Object& def) const
{
	val = def;
	return get(ndx,val);
}

/** (List) get an Int from this index */
bool    Object::get(size_t ndx, int& val, int def) const
{
	val = def;
	return get(ndx,val);
}

/** (List) get an Long from this index */
bool    Object::get(size_t ndx, long& val, long def) const
{
	val = def;
	return get(ndx,val);
}

/** (List) get a Float from this index */
bool    Object::get(size_t ndx, double& val, double def) const
{
	val = def;
	return get(ndx,val);
}

/** (List) get a String from this index */
bool    Object::get(size_t ndx, string& val, string& def) const
{
	val = def;
	return get(ndx,val);
}

} // end namespace atlas
<|endoftext|>


<commit_before>#include "Halide.h"
#include "copy_2_wrapper.h"
#include "tiramisu/utils.h"
#include <cstdlib>
#include <iostream>
#include <chrono>

#define NN 10

using namespace std;
using namespace std::chrono;

int main(int, char **)
{

    // Declare vector input and initialize it with 3
    Halide::Buffer<uint8_t> input(NN);
    init_buffer(input, (uint8_t)3);
    Halide::Buffer<uint8_t> output(NN);

    // TRAMISU CODE EXECUTION STARTS:
    auto start1 = std::chrono::high_resolution_clock::now();
    copy(input.raw_buffer(), output.raw_buffer());
    auto end1 = std::chrono::high_resolution_clock::now();
    auto  duration1 =duration_cast<microseconds>(end1 - start1);
    // TRAMISU CODE EXECUTION ENDS.

    // REFERENCE Output buffer
    Halide::Buffer<uint8_t> expected(NN);
    // REFERENCE C++ CODE EXECUTION STARTS
    auto start2 = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < NN; i++)
    {
            expected(i) = input(i);
    }
    // REFERENCE C++ CODE EXECUTION ENDS.

    auto end2 = std::chrono::high_resolution_clock::now();
    auto  duration2 =duration_cast<microseconds>(end2 - start2);
    //===== printing REFERECE EXEC TIME: =====
    std::cout << "\n REF RESOLUTION TIME : " << duration2.count() << "microseconds";
    //===== printing TIRAMISU EXEC TIME: =====
    std::cout << "\n TIRAMISU RESOLUTION TIME : " << duration1.count() << "microseconds";
    printf("\n");

    compare_buffers("copy", output, expected);

    return 0;
}
<commit_msg>Delete copy_2_wrapper.cpp<commit_after><|endoftext|>


<commit_before>#include <tiramisu/tiramisu.h>

using namespace tiramisu;

#define N 1024
#define M 1024

/**
*   Implementation of SYMM Benchmark in Tiramisu :
*
*        result = alpha*A*B + beta*C
*     or result = alpha*B*A + beta*C with A is symetric
*
*     A : a symmetric N by N matrix
*     B, C : a N by M matrix
*     alpha, beta : scalars
*
*
*    The C code is as follow:
*	for (i = 0; i < N; i++){
* 	   for (j = 0; j < M; j++){
*		temp = 0;
*		for (k = 0; k < j - 1; k++){
*	   		C[k][j] += alpha * A[k][i] * B[i][j];
*	    		temp += B[k][j] * A[k][i];
*	  	}
*	   Result[i][j] = beta * C[i][j] + alpha * A[i][i] * B[i][j] + alpha * temp;
*	   }
* 	}
*
**/

int main(int argc, char **argv)
{
	tiramisu::init("symm");

	// -------------------------------------------------------
	// Layer I
	// -------------------------------------------------------

	// Constants
	constant N("N", expr((int32_t) N));
	constant M("M", expr((int32_t) M))

	// Iteration variables
	var i("i", 0, N), j("j", 0, M), k("k", 0, j);

	// Scalars
	computation alpha("{alpha[0]}", expr());
	computation beta("{beta[0]}", expr());
	constant a("a", alpha(0));
	constant b("b", beta(0));

	// Matrix
	input B("B", {"k", "j"}, {N, M}, p_float64);
	input A("A", {"i", "k"}, {N, N}, p_float64);

	input C_0("C_0", {"i", "j"}, {N, M}, p_float64);

	// Computations
	// Initialisation à 0
	computation init("init", {i,j}, expr((p_float64) 0));

	//  A * B
	computation mat_mul_a_b("mat_mul_a_b", {i,j,k}, p_float64);

	// a * temp
	computation mult_alpha("mult_alpha",  {i,j,k}, p_float64);

	// Reduction on C
	computation C_1("C_1", {i,j,k}, C_0(k-1,j) + mult_alpha(i,j,k));

	//  B * A
	computation mat_mul_b_a("mat_mul_b_a", {i,j,k}, p_float64);

	computation mat_mul_a_b_e("mat_mul_a_b_e", {i,j}, p_float64);

	computation mult_alpha_k("mult_alpha_k", {i,j}, p_float64);

	computation mult_beta("mult_beta", {i,j}, p_float64);

	computation add_all("add_all", {i,j}, p_float64);

	mat_mul_a_b.set_expression(expr(mat_mul_a_b(i, j, k-1) + A(k, i) * B(i, j)));
	mult_alpha.set_expression(expr(alpha(0) * mat_mul_a_b(i, j , j-1)));
	mat_mul_b_a.set_expression(expr(mat_mul_b_a(i, j, k-1) + B(k, j) * A(k, i)));
	mat_mul_a_b_e.set_expression(expr(A(i, i) * B(i, j)));
	mult_alpha_k.set_expression(expr(alpha(0) * mat_mul_a_b_e(i, j)));
	mult_beta.set_expression(expr(beta(0) *  C_1(i,j, j-1)));
	add_all.set_expression(expr(add_all(i,j-1) + mat_mul_a_b_e(i, j) + mult_alpha(i,j, j-1) + mult_beta(i,j)));

	// -------------------------------------------------------
	// Layer II
	// -------------------------------------------------------
	add_all.after(mult_beta, j);
	mult_beta.after(mult_alpha_k, j);
	mult_alpha_k.after(mat_mul_a_b_e, j );
	mat_mul_a_b_e.after(mat_mul_b_a, j);
	mat_mul_b_a.after(mult_alpha, k);
	mult_alpha.after(mat_mul_a_b,k);
	mat_mul_a_b.after(init, j);

	// -------------------------------------------------------
	// Layer III
	// -------------------------------------------------------

	buffer buf_A("buf_A", {N,N}, p_float64, a_input);
	buffer buf_B("buf_B", {N,M}, p_float64, a_input);
	buffer buf_C("buf_C", {N,M}, p_float64, a_input);
	buffer buf_alpha("buf_alpha", {1}, p_float64, a_input);
	buffer buf_beta("buf_beta", {1}, p_float64, a_input);

	buffer buf_result("buf_result", {N,M}, p_float64, a_output);

	//Store inputs
	A.store_in(&buf_A);
	B.store_in(&buf_B);
	C_0.store_in(&buf_C);
	alpha.store_in(&buf_alpha[0]);
	beta.store_in(&buf_beta[0]);

	init.store_in(&buf_result, {i,j});

	add_all.store_in(&buf_result, {i,j});
	C_1.store_in(&buf_result, {i,j});
	mult_beta.store_in(&buf_result, {i,j});
	mat_mul_a_b_e.store_in(&buf_result, {i,j});
	mat_mul_b_a.store_in(&buf_result, {i,j});
	mult_alpha.store_in(&buf_result, {i,j});
	mat_mul_a_b.store_in(&buf_result, {i,j});

	// -------------------------------------------------------
	// Code Generation
	// -------------------------------------------------------
	tiramisu::codegen({&buf_A, &buf_B, &buf_C, &buf_alpha, &buf_beta, &buf_result}, "generated_symm.o");

	return 0;

}
<commit_msg>Remove additional spaces<commit_after>#include <tiramisu/tiramisu.h>

using namespace tiramisu;

/**
*   Implementation of SYMM Benchmark in Tiramisu :
*
*        result = alpha*A*B + beta*C
*     or result = alpha*B*A + beta*C with A is symetric
*
*     A : a symmetric N by N matrix
*     B, C : a N by M matrix
*     alpha, beta : scalars
*
*
*    The C code is as follow:
*	for (i = 0; i < N; i++){
* 	   for (j = 0; j < M; j++){
*		temp = 0;
*		for (k = 0; k < j - 1; k++){
*	   		C[k][j] += alpha * A[k][i] * B[i][j];
*	    		temp += B[k][j] * A[k][i];
*	  	}
*	   Result[i][j] = beta * C[i][j] + alpha * A[i][i] * B[i][j] + alpha * temp;
*	   }
* 	}
*
**/

int main(int argc, char **argv)
{
	tiramisu::init("symm");

	// -------------------------------------------------------
	// Layer I
	// -------------------------------------------------------

	// Constants
	constant N("N", expr((int32_t) N));
	constant M("M", expr((int32_t) M));

	// Iteration variables
	var i("i", 0, N), j("j", 0, M), k("k", 0, j);

	// Scalars
	computation alpha("{alpha[0]}", expr());
	computation beta("{beta[0]}", expr());
	constant a("a", alpha(0));
	constant b("b", beta(0));

	// Matrix
	input B("B", {"k", "j"}, {N, M}, p_float64);
	input A("A", {"i", "k"}, {N, N}, p_float64);

	input C_0("C_0", {"i", "j"}, {N, M}, p_float64);

	// Computations
	// Initialisation à 0
	computation init("init", {i,j}, expr((p_float64) 0));

	//  A * B
	computation mat_mul_a_b("mat_mul_a_b", {i,j,k}, p_float64);

	// a * temp
	computation mult_alpha("mult_alpha",  {i,j,k}, p_float64);

	// Reduction on C
	computation C_1("C_1", {i,j,k}, C_0(k-1,j) + mult_alpha(i,j,k));

	//  B * A
	computation mat_mul_b_a("mat_mul_b_a", {i,j,k}, p_float64);

	computation mat_mul_a_b_e("mat_mul_a_b_e", {i,j}, p_float64);

	computation mult_alpha_k("mult_alpha_k", {i,j}, p_float64);

	computation mult_beta("mult_beta", {i,j}, p_float64);

	computation add_all("add_all", {i,j}, p_float64);

	mat_mul_a_b.set_expression(expr(mat_mul_a_b(i, j, k-1) + A(k, i) * B(i, j)));
	mult_alpha.set_expression(expr(alpha(0) * mat_mul_a_b(i, j , j-1)));
	mat_mul_b_a.set_expression(expr(mat_mul_b_a(i, j, k-1) + B(k, j) * A(k, i)));
	mat_mul_a_b_e.set_expression(expr(A(i, i) * B(i, j)));
	mult_alpha_k.set_expression(expr(alpha(0) * mat_mul_a_b_e(i, j)));
	mult_beta.set_expression(expr(beta(0) *  C_1(i,j, j-1)));
	add_all.set_expression(expr(add_all(i,j-1) + mat_mul_a_b_e(i, j) + mult_alpha(i,j, j-1) + mult_beta(i,j)));

	// -------------------------------------------------------
	// Layer II
	// -------------------------------------------------------
	add_all.after(mult_beta, j);
	mult_beta.after(mult_alpha_k, j);
	mult_alpha_k.after(mat_mul_a_b_e, j);
	mat_mul_a_b_e.after(mat_mul_b_a, j);
	mat_mul_b_a.after(mult_alpha, k);
	mult_alpha.after(mat_mul_a_b,k);
	mat_mul_a_b.after(init, j);

	// -------------------------------------------------------
	// Layer III
	// -------------------------------------------------------

	buffer buf_A("buf_A", {N,N}, p_float64, a_input);
	buffer buf_B("buf_B", {N,M}, p_float64, a_input);
	buffer buf_C("buf_C", {N,M}, p_float64, a_input);
	buffer buf_alpha("buf_alpha", {1}, p_float64, a_input);
	buffer buf_beta("buf_beta", {1}, p_float64, a_input);

	buffer buf_result("buf_result", {N,M}, p_float64, a_output);

	//Store inputs
	A.store_in(&buf_A);
	B.store_in(&buf_B);
	C_0.store_in(&buf_C);
	alpha.store_in(&buf_alpha[0]);
	beta.store_in(&buf_beta[0]);

	init.store_in(&buf_result, {i,j});

	add_all.store_in(&buf_result, {i,j});
	C_1.store_in(&buf_result, {i,j});
	mult_beta.store_in(&buf_result, {i,j});
	mat_mul_a_b_e.store_in(&buf_result, {i,j});
	mat_mul_b_a.store_in(&buf_result, {i,j});
	mult_alpha.store_in(&buf_result, {i,j});
	mat_mul_a_b.store_in(&buf_result, {i,j});

	// -------------------------------------------------------
	// Code Generation
	// -------------------------------------------------------
	tiramisu::codegen({&buf_A, &buf_B, &buf_C, &buf_alpha, &buf_beta, &buf_result}, "generated_symm.o");

	return 0;

}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Open Source Robotics Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
*/

#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <cstring>
#include <iostream>
#include <string>
#include "ignition/transport/config.hh"
#include "ignition/transport/NetUtils.hh"

#ifdef HAVE_IFADDRS
# include <ifaddrs.h>
#endif

using namespace ignition;

//////////////////////////////////////////////////
bool transport::isPrivateIP(const char *ip)
{
  bool b = !strncmp("192.168", ip, 7) || !strncmp("10.", ip, 3) ||
           !strncmp("169.254", ip, 7);
  return b;
}

//////////////////////////////////////////////////
int transport::hostname_to_ip(char * hostname, std::string &_ip)
{
  struct hostent *he;
  struct in_addr **addr_list;
  int i;

  if ((he = gethostbyname(hostname)) == nullptr)
  {
    // get the host info
    herror("gethostbyname");
    return 1;
  }

  addr_list = (struct in_addr **) he->h_addr_list;

  for (i = 0; addr_list[i] != nullptr; ++i)
  {
    // Return the first one;
    _ip = std::string(inet_ntoa(*addr_list[i]));
    return 0;
  }

  return 1;
}

//////////////////////////////////////////////////
std::string transport::DetermineHost()
{
  char *ip_env;
  // First, did the user set DZMQ_IP?
  ip_env = std::getenv("DZMQ_IP");

  if (ip_env)
  {
    if (strlen(ip_env) != 0)
      return ip_env;
    else
      std::cerr << "invalid DZMQ_IP (an empty string)" << std::endl;
  }

  // Second, try the hostname
  char host[1024];
  memset(host, 0, sizeof(host));
  if (gethostname(host, sizeof(host) - 1) != 0)
    std::cerr << "determineIP: gethostname failed" << std::endl;

  // We don't want localhost to be our ip
  else if (strlen(host) && strcmp("localhost", host))
  {
    std::string hostIP;
    strcat(host, ".local");
    if (hostname_to_ip(host, hostIP) == 0)
    {
      return std::string(hostIP);
    }
  }

  // Third, fall back on interface search, which will yield an IP address
#ifdef HAVE_IFADDRS_H
  struct ifaddrs *ifa = nullptr, *ifp = NULL;
  int rc;
  if ((rc = getifaddrs(&ifp)) < 0)
  {
    std::cerr << "error in getifaddrs: " << strerror(rc) << std::endl;
    exit(-1);
  }
  char preferred_ip[200] = {0};
  for (ifa = ifp; ifa; ifa = ifa->ifa_next)
  {
    char ip_[200];
    socklen_t salen;
    if (!ifa->ifa_addr)
      continue;  // evidently this interface has no ip address
    if (ifa->ifa_addr->sa_family == AF_INET)
      salen = sizeof(struct sockaddr_in);
    else if (ifa->ifa_addr->sa_family == AF_INET6)
      salen = sizeof(struct sockaddr_in6);
    else
      continue;
    if (getnameinfo(ifa->ifa_addr, salen, ip_, sizeof(ip_), nullptr, 0,
                    NI_NUMERICHOST) < 0)
    {
      std::cout << "getnameinfo couldn't get the ip of interface " <<
                   ifa->ifa_name << std::endl;
      continue;
    }
    // prefer non-private IPs over private IPs
    if (!strcmp("127.0.0.1", ip_) || strchr(ip_, ':'))
      continue;  // ignore loopback unless we have no other choice
    if (ifa->ifa_addr->sa_family == AF_INET6 && !preferred_ip[0])
      strcpy(preferred_ip, ip_);
    else if (isPrivateIP(ip_) && !preferred_ip[0])
      strcpy(preferred_ip, ip_);
    else if (!isPrivateIP(ip_) &&
             (isPrivateIP(preferred_ip) || !preferred_ip[0]))
      strcpy(preferred_ip, ip_);
  }
  freeifaddrs(ifp);
  if (!preferred_ip[0])
  {
    std::cerr <<
      "Couldn't find a preferred IP via the getifaddrs() call; "
      "I'm assuming that your IP "
      "address is 127.0.0.1.  This should work for local processes, "
      "but will almost certainly not work if you have remote processes."
      "Report to the disc-zmq development team to seek a fix." << std::endl;
    return std::string("127.0.0.1");
  }
  return std::string(preferred_ip);
#else
  // @todo Fix IP determination in the case where getifaddrs() isn't
  // available.
  std::cerr <<
    "You don't have the getifaddrs() call; I'm assuming that your IP "
    "address is 127.0.0.1.  This should work for local processes, "
    "but will almost certainly not work if you have remote processes."
    "Report to the disc-zmq development team to seek a fix." << std::endl;
  return std::string("127.0.0.1");
#endif
}
<commit_msg>Tweaking #ifdef<commit_after>/*
 * Copyright (C) 2014 Open Source Robotics Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
*/

#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <cstring>
#include <iostream>
#include <string>
#include "ignition/transport/config.hh"
#include "ignition/transport/NetUtils.hh"

#ifdef HAVE_IFADDRS
# include <ifaddrs.h>
#endif

using namespace ignition;

//////////////////////////////////////////////////
bool transport::isPrivateIP(const char *ip)
{
  bool b = !strncmp("192.168", ip, 7) || !strncmp("10.", ip, 3) ||
           !strncmp("169.254", ip, 7);
  return b;
}

//////////////////////////////////////////////////
int transport::hostname_to_ip(char * hostname, std::string &_ip)
{
  struct hostent *he;
  struct in_addr **addr_list;
  int i;

  if ((he = gethostbyname(hostname)) == nullptr)
  {
    // get the host info
    herror("gethostbyname");
    return 1;
  }

  addr_list = (struct in_addr **) he->h_addr_list;

  for (i = 0; addr_list[i] != nullptr; ++i)
  {
    // Return the first one;
    _ip = std::string(inet_ntoa(*addr_list[i]));
    return 0;
  }

  return 1;
}

//////////////////////////////////////////////////
std::string transport::DetermineHost()
{
  char *ip_env;
  // First, did the user set DZMQ_IP?
  ip_env = std::getenv("DZMQ_IP");

  if (ip_env)
  {
    if (strlen(ip_env) != 0)
      return ip_env;
    else
      std::cerr << "invalid DZMQ_IP (an empty string)" << std::endl;
  }

  // Second, try the hostname
  char host[1024];
  memset(host, 0, sizeof(host));
  if (gethostname(host, sizeof(host) - 1) != 0)
    std::cerr << "determineIP: gethostname failed" << std::endl;

  // We don't want localhost to be our ip
  else if (strlen(host) && strcmp("localhost", host))
  {
    std::string hostIP;
    strcat(host, ".local");
    if (hostname_to_ip(host, hostIP) == 0)
    {
      return std::string(hostIP);
    }
  }

  // Third, fall back on interface search, which will yield an IP address
#ifdef HAVE_IFADDRS
  struct ifaddrs *ifa = nullptr, *ifp = NULL;
  int rc;
  if ((rc = getifaddrs(&ifp)) < 0)
  {
    std::cerr << "error in getifaddrs: " << strerror(rc) << std::endl;
    exit(-1);
  }
  char preferred_ip[200] = {0};
  for (ifa = ifp; ifa; ifa = ifa->ifa_next)
  {
    char ip_[200];
    socklen_t salen;
    if (!ifa->ifa_addr)
      continue;  // evidently this interface has no ip address
    if (ifa->ifa_addr->sa_family == AF_INET)
      salen = sizeof(struct sockaddr_in);
    else if (ifa->ifa_addr->sa_family == AF_INET6)
      salen = sizeof(struct sockaddr_in6);
    else
      continue;
    if (getnameinfo(ifa->ifa_addr, salen, ip_, sizeof(ip_), nullptr, 0,
                    NI_NUMERICHOST) < 0)
    {
      std::cout << "getnameinfo couldn't get the ip of interface " <<
                   ifa->ifa_name << std::endl;
      continue;
    }
    // prefer non-private IPs over private IPs
    if (!strcmp("127.0.0.1", ip_) || strchr(ip_, ':'))
      continue;  // ignore loopback unless we have no other choice
    if (ifa->ifa_addr->sa_family == AF_INET6 && !preferred_ip[0])
      strcpy(preferred_ip, ip_);
    else if (isPrivateIP(ip_) && !preferred_ip[0])
      strcpy(preferred_ip, ip_);
    else if (!isPrivateIP(ip_) &&
             (isPrivateIP(preferred_ip) || !preferred_ip[0]))
      strcpy(preferred_ip, ip_);
  }
  freeifaddrs(ifp);
  if (!preferred_ip[0])
  {
    std::cerr <<
      "Couldn't find a preferred IP via the getifaddrs() call; "
      "I'm assuming that your IP "
      "address is 127.0.0.1.  This should work for local processes, "
      "but will almost certainly not work if you have remote processes."
      "Report to the disc-zmq development team to seek a fix." << std::endl;
    return std::string("127.0.0.1");
  }
  return std::string(preferred_ip);
#else
  // @todo Fix IP determination in the case where getifaddrs() isn't
  // available.
  std::cerr <<
    "You don't have the getifaddrs() call; I'm assuming that your IP "
    "address is 127.0.0.1.  This should work for local processes, "
    "but will almost certainly not work if you have remote processes."
    "Report to the disc-zmq development team to seek a fix." << std::endl;
  return std::string("127.0.0.1");
#endif
}
<|endoftext|>


<commit_before>/**
 * @author : xiaozhuai
 * @date   : 17/1/3
 */

#include "../include/Request.h"

namespace CXXUrl {

Request::Request() :
        followLocation(true),
        contentOutput(NULL),
        headerOutput(NULL),
        maxRedirs(-1),
        form(NULL),
        referer(""),
        header(NULL) {

    userAgent = string("") + "CXXUrl/" + CXX_URL_VERSION + " " + curl_version();
}

Request::~Request() {

}

size_t Request::writeContent(char *buffer, size_t size, size_t count, void *stream) {
    ((ostream *) stream)->write(buffer, size * count);
//    printf("data recieved: %d,%s\n", size*count, buffer);
    return size * count;
}

size_t Request::writeHeader(char *buffer, size_t size, size_t count, void *stream) {
    ((ostream *) stream)->write(buffer, size * count);
    return size * count;
}

void Request::setContentOutput(ostream *stream) {
    contentOutput = stream;
}

void Request::setHeaderOutput(ostream *stream) {
    headerOutput = stream;
}

ostream *Request::getContentOutput() {
    return contentOutput;
}

ostream *Request::getHeaderOutput() {
    return headerOutput;
}

void Request::setUrl(string url) {
    this->url = url;
}

string Request::getUrl() {
    return url;
}

void Request::setFollowLocation(bool followLocation) {
    this->followLocation = followLocation;
}

bool Request::getFollowLocation() {
    return followLocation;
}

void Request::setMaxRedirs(int maxRedirs) {
    this->maxRedirs = maxRedirs;
}

int Request::getMaxRedirs() {
    return maxRedirs;
}

void Request::setForm(Form *form) {
    this->form = form;
}

Form *Request::getForm() {
    return form;
}

void Request::setUserAgent(string userAgent) {
    this->userAgent = userAgent;
}

string Request::getUserAgent() {
    return userAgent;
}

void Request::setReferer(string referer) {
    this->referer = referer;
}

string Request::getReferer() {
    return referer;
}

void Request::setHeader(Header *header) {
    this->header = header;
}

Header* Request::getHeader() {
    return header;
}

CURLcode Request::get() {
    return exec(GET);
}

CURLcode Request::post() {
    return exec(POST);
}

CURLcode Request::exec(METHOD_TYPE method) {
    curl = curl_easy_init();

    SET_CURL_OPT(CURLOPT_URL, url.c_str());
//    SET_CURL_OPT(CURLOPT_VERBOSE, 1);

    if (method == POST) {
        SET_CURL_OPT(CURLOPT_POST, 1);
        if (form == NULL)
            SET_CURL_OPT(CURLOPT_POSTFIELDS, "");
        else {
            switch (form->type){
                case Form::SIMPLE: {
                    SimpleForm *simpleForm = (SimpleForm *) form;
                    SET_CURL_OPT(CURLOPT_POSTFIELDS, simpleForm->getData());
                    SET_CURL_OPT(CURLOPT_POSTFIELDSIZE, simpleForm->length());
                    break;
                }
                case Form::MULTIPART: {
                    MultipartForm *multipartForm = (MultipartForm *) form;
                    SET_CURL_OPT(CURLOPT_HTTPPOST, multipartForm->getData());
                    break;
                }
                case Form::RAW: {
                    RawForm *rawForm = (RawForm *) form;
                    SET_CURL_OPT(CURLOPT_POSTFIELDS, rawForm->getData());
                    SET_CURL_OPT(CURLOPT_POSTFIELDSIZE, rawForm->length());
                    break;
                }
                default:
                    cerr << "form type unknown" << endl;
                    break;
            }
        }
    }

    SET_CURL_OPT(CURLOPT_FOLLOWLOCATION, followLocation);
    SET_CURL_OPT(CURLOPT_USERAGENT, userAgent.c_str());

    if(referer!=""){
        SET_CURL_OPT(CURLOPT_REFERER, referer.c_str());
    }

    if(header!=NULL){
        SET_CURL_OPT(CURLOPT_HTTPHEADER, header->getHeaders());
    }

    if (maxRedirs != -1)
        SET_CURL_OPT(CURLOPT_MAXREDIRS, maxRedirs);

    if (contentOutput != NULL) {
        SET_CURL_OPT(CURLOPT_WRITEFUNCTION, writeContent);
        SET_CURL_OPT(CURLOPT_WRITEDATA, contentOutput);
    }
    if (headerOutput != NULL) {
        SET_CURL_OPT(CURLOPT_HEADERFUNCTION, writeHeader);
        SET_CURL_OPT(CURLOPT_HEADERDATA, headerOutput);
    }

    CURLcode res;
    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    return res;
}

}<commit_msg>method choose<commit_after>/**
 * @author : xiaozhuai
 * @date   : 17/1/3
 */

#include "../include/Request.h"

namespace CXXUrl {

Request::Request() :
        followLocation(true),
        contentOutput(NULL),
        headerOutput(NULL),
        maxRedirs(-1),
        form(NULL),
        referer(""),
        header(NULL) {

    userAgent = string("") + "CXXUrl/" + CXX_URL_VERSION + " " + curl_version();
}

Request::~Request() {

}

size_t Request::writeContent(char *buffer, size_t size, size_t count, void *stream) {
    ((ostream *) stream)->write(buffer, size * count);
//    printf("data recieved: %d,%s\n", size*count, buffer);
    return size * count;
}

size_t Request::writeHeader(char *buffer, size_t size, size_t count, void *stream) {
    ((ostream *) stream)->write(buffer, size * count);
    return size * count;
}

void Request::setContentOutput(ostream *stream) {
    contentOutput = stream;
}

void Request::setHeaderOutput(ostream *stream) {
    headerOutput = stream;
}

ostream *Request::getContentOutput() {
    return contentOutput;
}

ostream *Request::getHeaderOutput() {
    return headerOutput;
}

void Request::setUrl(string url) {
    this->url = url;
}

string Request::getUrl() {
    return url;
}

void Request::setFollowLocation(bool followLocation) {
    this->followLocation = followLocation;
}

bool Request::getFollowLocation() {
    return followLocation;
}

void Request::setMaxRedirs(int maxRedirs) {
    this->maxRedirs = maxRedirs;
}

int Request::getMaxRedirs() {
    return maxRedirs;
}

void Request::setForm(Form *form) {
    this->form = form;
}

Form *Request::getForm() {
    return form;
}

void Request::setUserAgent(string userAgent) {
    this->userAgent = userAgent;
}

string Request::getUserAgent() {
    return userAgent;
}

void Request::setReferer(string referer) {
    this->referer = referer;
}

string Request::getReferer() {
    return referer;
}

void Request::setHeader(Header *header) {
    this->header = header;
}

Header* Request::getHeader() {
    return header;
}

CURLcode Request::get() {
    return exec(GET);
}

CURLcode Request::post() {
    return exec(POST);
}

CURLcode Request::exec(METHOD_TYPE method) {
    curl = curl_easy_init();

    SET_CURL_OPT(CURLOPT_URL, url.c_str());
//    SET_CURL_OPT(CURLOPT_VERBOSE, 1);

    switch (method){
        case GET: {
            SET_CURL_OPT(CURLOPT_HTTPGET, 1);
            break;
        }
        case POST: {
            SET_CURL_OPT(CURLOPT_POST, 1);
            if (form == NULL) {
                SET_CURL_OPT(CURLOPT_POSTFIELDS, "");
                SET_CURL_OPT(CURLOPT_POSTFIELDSIZE, 0);
            } else {
                switch (form->type){
                    case Form::SIMPLE: {
                        SimpleForm *simpleForm = (SimpleForm *) form;
                        SET_CURL_OPT(CURLOPT_POSTFIELDS, simpleForm->getData());
                        SET_CURL_OPT(CURLOPT_POSTFIELDSIZE, simpleForm->length());
                        break;
                    }
                    case Form::MULTIPART: {
                        MultipartForm *multipartForm = (MultipartForm *) form;
                        SET_CURL_OPT(CURLOPT_HTTPPOST, multipartForm->getData());
                        break;
                    }
                    case Form::RAW: {
                        RawForm *rawForm = (RawForm *) form;
                        SET_CURL_OPT(CURLOPT_POSTFIELDS, rawForm->getData());
                        SET_CURL_OPT(CURLOPT_POSTFIELDSIZE, rawForm->length());
                        break;
                    }
                    default:
                        cerr << "form type unknown" << endl;
                        break;
                }
            }
            break;
        }
        default:
            cerr << "unknown method" << endl;
    }

    SET_CURL_OPT(CURLOPT_FOLLOWLOCATION, followLocation);
    SET_CURL_OPT(CURLOPT_USERAGENT, userAgent.c_str());

    if(referer!=""){
        SET_CURL_OPT(CURLOPT_REFERER, referer.c_str());
    }

    if(header!=NULL){
        SET_CURL_OPT(CURLOPT_HTTPHEADER, header->getHeaders());
    }

    if (maxRedirs != -1)
        SET_CURL_OPT(CURLOPT_MAXREDIRS, maxRedirs);

    if (contentOutput != NULL) {
        SET_CURL_OPT(CURLOPT_WRITEFUNCTION, writeContent);
        SET_CURL_OPT(CURLOPT_WRITEDATA, contentOutput);
    }
    if (headerOutput != NULL) {
        SET_CURL_OPT(CURLOPT_HEADERFUNCTION, writeHeader);
        SET_CURL_OPT(CURLOPT_HEADERDATA, headerOutput);
    }

    CURLcode res;
    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    return res;
}

}<|endoftext|>