From a4aeae1da5363195f6d07651daad4de63fa5c52c Mon Sep 17 00:00:00 2001 From: Simon Praetorius <simon.praetorius@tu-dresden.de> Date: Mon, 22 Oct 2018 16:48:41 -0400 Subject: [PATCH] renamed DOFVectorConstView into DiscreteFunction and added some more interpolation methods --- src/amdis/FileWriter.hpp | 20 +- src/amdis/ProblemStat.hpp | 3 +- src/amdis/gridfunctions/CMakeLists.txt | 3 +- src/amdis/gridfunctions/DOFVectorView.hpp | 332 +++--------------- .../gridfunctions/DerivativeGridFunction.hpp | 18 +- src/amdis/gridfunctions/DiscreteFunction.hpp | 245 +++++++++++++ ...rView.inc.hpp => DiscreteFunction.inc.hpp} | 24 +- test/CMakeLists.txt | 4 + test/DiscreteFunctionTest.cpp | 102 ++++++ 9 files changed, 445 insertions(+), 306 deletions(-) create mode 100644 src/amdis/gridfunctions/DiscreteFunction.hpp rename src/amdis/gridfunctions/{DOFVectorView.inc.hpp => DiscreteFunction.inc.hpp} (83%) create mode 100644 test/DiscreteFunctionTest.cpp diff --git a/src/amdis/FileWriter.hpp b/src/amdis/FileWriter.hpp index ff734622..a8d95f25 100644 --- a/src/amdis/FileWriter.hpp +++ b/src/amdis/FileWriter.hpp @@ -12,7 +12,7 @@ #include <amdis/Initfile.hpp> #include <amdis/common/Size.hpp> #include <amdis/common/ValueCategory.hpp> -#include <amdis/gridfunctions/DOFVectorView.hpp> +#include <amdis/gridfunctions/DiscreteFunction.hpp> #include <amdis/io/FileWriterInterface.hpp> #include <amdis/utility/Filesystem.hpp> @@ -49,8 +49,8 @@ namespace AMDiS { private: // typedefs and static constants using GridView = typename GlobalBasis::GridView; - using Vector = DOFVectorConstView<GlobalBasis,RangeType,TreePath>; - using Range = typename Vector::Range; + using DiscreteFunction = AMDiS::DiscreteFunction<GlobalBasis,RangeType,TreePath>; + using Range = typename DiscreteFunction::Range; /// Dimension of the mesh static constexpr int dim = GridView::dimension; @@ -61,9 +61,9 @@ namespace AMDiS public: /// Constructor. FileWriter(std::string const& baseName, - Vector const& dofvector) + DiscreteFunction const& discreteFct) : FileWriterInterface(baseName) - , dofvector_(dofvector) + , discreteFct_(discreteFct) , animation_(false) { Parameters::get(baseName + "->ParaView animation", animation_); @@ -86,7 +86,7 @@ namespace AMDiS if (animation_) vtkSeqWriter_ = std::make_shared<Dune::VTKSequenceWriter<GridView>>(vtkWriter_, filename_, dir_, ""); - vtkWriter_->addVertexData(dofvector_, Dune::VTK::FieldInfo(name_, VTKFieldType<Range>, VTKFieldSize<Range>)); + vtkWriter_->addVertexData(discreteFct_, Dune::VTK::FieldInfo(name_, VTKFieldType<Range>, VTKFieldSize<Range>)); } void init(std::string const&, tag::unknown) {} @@ -105,11 +105,11 @@ namespace AMDiS protected: GridView const& gridView() const { - return dofvector_.basis().gridView(); + return discreteFct_.basis().gridView(); } private: - Vector dofvector_; + DiscreteFunction discreteFct_; std::shared_ptr<Dune::VTKWriter<GridView>> vtkWriter_; std::shared_ptr<Dune::VTKSequenceWriter<GridView>> vtkSeqWriter_; @@ -125,9 +125,9 @@ namespace AMDiS template <class GlobalBasis, class Range, class TreePath> std::shared_ptr<FileWriter<GlobalBasis,Range,TreePath>> makeFileWriterPtr(std::string baseName, - DOFVectorConstView<GlobalBasis,Range,TreePath> const& dofvector) + DiscreteFunction<GlobalBasis,Range,TreePath> const& discreteFct) { - return std::make_shared<FileWriter<GlobalBasis,Range,TreePath>>(baseName, dofvector); + return std::make_shared<FileWriter<GlobalBasis,Range,TreePath>>(baseName, discreteFct); } } // end namespace AMDiS diff --git a/src/amdis/ProblemStat.hpp b/src/amdis/ProblemStat.hpp index 74eb5c10..a965675f 100644 --- a/src/amdis/ProblemStat.hpp +++ b/src/amdis/ProblemStat.hpp @@ -32,6 +32,7 @@ #include <amdis/common/Utility.hpp> #include <amdis/GridFunctions.hpp> +#include <amdis/gridfunctions/DiscreteFunction.hpp> #include <amdis/gridfunctions/DOFVectorView.hpp> #include <amdis/io/FileWriterInterface.hpp> @@ -198,7 +199,7 @@ namespace AMDiS auto getSolution(TreePath const& path = {}) const { auto&& tp = makeTreePath(path); - return makeDOFVectorView(*solution_, tp); + return makeDiscreteFunction(*solution_, tp); } diff --git a/src/amdis/gridfunctions/CMakeLists.txt b/src/amdis/gridfunctions/CMakeLists.txt index a2b00db0..328773db 100644 --- a/src/amdis/gridfunctions/CMakeLists.txt +++ b/src/amdis/gridfunctions/CMakeLists.txt @@ -5,8 +5,9 @@ install(FILES ConstantGridFunction.hpp CoordsGridFunction.hpp DerivativeGridFunction.hpp + DiscreteFunction.hpp + DiscreteFunction.inc.hpp DOFVectorView.hpp - DOFVectorView.inc.hpp FunctorGridFunction.hpp GridFunctionConcepts.hpp Integrate.hpp diff --git a/src/amdis/gridfunctions/DOFVectorView.hpp b/src/amdis/gridfunctions/DOFVectorView.hpp index 86b52e7e..c39cf8df 100644 --- a/src/amdis/gridfunctions/DOFVectorView.hpp +++ b/src/amdis/gridfunctions/DOFVectorView.hpp @@ -1,299 +1,75 @@ #pragma once -#include <vector> - -#include <dune/common/std/optional.hh> -#include <dune/functions/common/defaultderivativetraits.hh> -#include <dune/functions/common/treedata.hh> -#include <dune/functions/functionspacebases/defaultnodetorangemap.hh> -#include <dune/functions/functionspacebases/flatvectorview.hh> -#include <dune/functions/gridfunctions/gridviewentityset.hh> -#include <dune/typetree/childextraction.hh> - #include <amdis/GridFunctions.hpp> -#include <amdis/utility/FiniteElementType.hpp> +#include <amdis/gridfunctions/DiscreteFunction.hpp> namespace AMDiS { - /** - * \addtogroup GridFunctions - * @{ - **/ - + /// A mutable view on the subspace of a DOFVector, \relates DiscreteFunction template <class GlobalBasisType, class RangeType, class TreePathType> - class DOFVectorConstView + class DOFVectorView + : public DiscreteFunction<GlobalBasisType, RangeType, TreePathType> { - public: + using Self = DOFVectorView; + using Super = DiscreteFunction<GlobalBasisType, RangeType, TreePathType>; + using GlobalBasis = GlobalBasisType; using TreePath = TreePathType; - using Tree = typename GlobalBasis::LocalView::Tree; - using SubTree = typename Dune::TypeTree::ChildForTreePath<Tree, TreePath>; - using NodeToRangeEntry = Dune::Functions::DefaultNodeToRangeMap<SubTree>; - - using GridView = typename GlobalBasis::GridView; - using EntitySet = Dune::Functions::GridViewEntitySet<GridView, 0>; - - using Domain = typename EntitySet::GlobalCoordinate; - using Range = RangeType_t<SubTree>; - static_assert(std::is_arithmetic<RangeType>::value, ""); - // Don't know how to determine Range with non-trivial RangeType - - using RawSignature = typename Dune::Functions::SignatureTraits<Range(Domain)>::RawSignature; - using DerivativeTraits = Dune::Functions::DefaultDerivativeTraits<RawSignature>; - using DerivativeRange = typename DerivativeTraits::Range; - - using LocalDomain = typename EntitySet::LocalCoordinate; - using Element = typename EntitySet::Element; - using Geometry = typename Element::Geometry; - - enum { hasDerivative = false }; - - public: // a local view on the gradients - - /// A LocalFunction representing the derivative of the DOFVector - class GradientLocalFunction - { - public: - using Domain = LocalDomain; - using Range = DerivativeRange; - - enum { hasDerivative = false }; - - private: - using LocalView = typename GlobalBasis::LocalView; - - template <class LeafNode> - using LocalBasisJacobian = typename LeafNode::FiniteElement::Traits::LocalBasisType::Traits::JacobianType; - - template <class Node> - using NodeData = typename std::vector<LocalBasisJacobian<Node>>; - - using ReferenceGradientContainer = Dune::Functions::TreeData<SubTree, NodeData, true>; - - public: - GradientLocalFunction(DOFVectorConstView const& globalFunction) - : globalFunction_(&globalFunction) - , localView_(globalFunction_->basis().localView()) - , subTree_(&Dune::TypeTree::child(localView_.tree(), globalFunction_->treePath())) - { - referenceGradientContainer_.init(*subTree_); - } - - void bind(Element const& element) - { - localView_.bind(element); - geometry_.emplace(element.geometry()); - bound_ = true; - } - - void unbind() - { - localView_.unbind(); - geometry_.reset(); - bound_ = false; - } - - /// Evaluate Gradient at bound element in local coordinates - Range operator()(Domain const& x) const; - - friend int order(GradientLocalFunction const& self) - { - assert( self.bound_ ); - return std::max(0, polynomialDegree(*self.subTree_)-1); - } - - /// Return the bound element - Element const& localContext() const - { - assert( bound_ ); - return localView_.element(); - } - - private: - DOFVectorConstView const* globalFunction_; - LocalView localView_; - - SubTree const* subTree_; - mutable ReferenceGradientContainer referenceGradientContainer_; - - Dune::Std::optional<Geometry> geometry_; - bool bound_ = false; - }; - - - public: // a local view on the values - - /// A LocalFunction, i.e., an element local view on the DOFVector - class LocalFunction - { - public: - using Domain = typename DOFVectorConstView::LocalDomain; - using Range = typename DOFVectorConstView::Range; - - enum { hasDerivative = true }; - - private: - using LocalView = typename GlobalBasis::LocalView; - - template <class LeafNode> - using LocalBasisRange = RangeType_t<LeafNode>; - // = typename LeafNode::FiniteElement::Traits::LocalBasisType::Traits::RangeType; - - template <class Node> - using NodeData = typename std::vector<LocalBasisRange<Node>>; - - using ShapeFunctionValueContainer = Dune::Functions::TreeData<SubTree, NodeData, true>; - - public: - LocalFunction(DOFVectorConstView const& globalFunction) - : globalFunction_(&globalFunction) - , localView_(globalFunction_->basis().localView()) - , subTree_(&Dune::TypeTree::child(localView_.tree(), globalFunction_->treePath())) - { - shapeFunctionValueContainer_.init(*subTree_); - } - - void bind(Element const& element) - { - localView_.bind(element); - bound_ = true; - } - - void unbind() - { - localView_.unbind(); - bound_ = false; - } - - /// Evaluate LocalFunction at bound element in local coordinates - Range operator()(Domain const& x) const; - - /// \brief Create a LocalFunction representing the gradient. \relates GradientLocalFunction - friend GradientLocalFunction derivative(LocalFunction const& localFunction) - { - static_assert(isValidRange<DerivativeTraits>(),"Derivative of DOFVector not defined."); - return GradientLocalFunction{*localFunction.globalFunction_}; - } - - friend int order(LocalFunction const& self) - { - assert( self.bound_ ); - return polynomialDegree(*self.subTree_); - } - - /// Return the bound element - Element const& localContext() const - { - assert( bound_ ); - return localView_.element(); - } - - private: - DOFVectorConstView const* globalFunction_; - LocalView localView_; - SubTree const* subTree_; - - mutable ShapeFunctionValueContainer shapeFunctionValueContainer_; - - bool bound_ = false; - }; - - public: - /// Constructor. Stores a pointer to the dofVector and a copy of the treePath. - DOFVectorConstView(DOFVector<GlobalBasis,RangeType> const& dofVector, TreePath const& treePath) - : dofVector_(&dofVector) - , treePath_(treePath) - , entitySet_(dofVector.basis().gridView()) - , nodeToRangeEntry_(Dune::Functions::makeDefaultNodeToRangeMap(dofVector.basis(), treePath)) + /// Constructor. Stores a pointer to the mutable `dofvector`. + DOFVectorView(DOFVector<GlobalBasis,RangeType>& dofVector, TreePath const& treePath) + : Super(dofVector, treePath) + , mutableDofVector_(&dofVector) {} - /// Evaluate the view on this DOFVector in global coordinates - Range operator()(Domain const& x) const + public: + /// \brief Interpolation of GridFunction to DOFVector, assuming that there is no + /// reference to this DOFVector in the expression. + template <class Expr> + void interpolate_noalias(Expr&& expr) { - error_exit("Not implemented."); - return Range(0); - } + auto const& basis = this->basis(); + auto const& treePath = this->treePath(); - /// \brief Create a local function for this view on the DOFVector. \relates LocalFunction - friend LocalFunction localFunction(DOFVectorConstView const& self) - { - return LocalFunction{self}; - } + auto&& gridFct = makeGridFunction(std::forward<Expr>(expr), basis.gridView()); - EntitySet const& entitySet() const - { - return entitySet_; + Dune::Functions::interpolate(basis, treePath, coefficients(), std::forward<decltype(gridFct)>(gridFct)); } - public: - /// Return global basis - GlobalBasis const& basis() const + /// Interpolation of GridFunction to DOFVector + template <class Expr> + void interpolate(Expr&& expr) { - return dofVector_->basis(); - } + // create temporary copy of data + DOFVector<GlobalBasis,RangeType> tmp(coefficients()); + Self tmpView{tmp, this->treePath()}; + tmpView.interpolate_noalias(std::forward<Expr>(expr)); - /// Return treePath associated with this view - TreePath const& treePath() const - { - return treePath_; + // move data from temporary vector into stored DOFVector + coefficients().vector() = std::move(tmp.vector()); } - /// Return const coefficient vector - DOFVector<GlobalBasis,RangeType> const& coefficients() const + /// \brief Interpolation of GridFunction to DOFVector, alias to \ref interpolate() + template <class Expr> + DOFVectorView& operator<<(Expr&& expr) { - return *dofVector_; + interpolate(expr); + return *this; } - protected: - DOFVector<GlobalBasis,RangeType> const* dofVector_; - TreePath const treePath_; - - EntitySet entitySet_; - NodeToRangeEntry nodeToRangeEntry_; - }; - - - // A mutable version of DOFVectorView - template <class GlobalBasisType, class RangeType, class TreePathType> - class DOFVectorMutableView - : public DOFVectorConstView<GlobalBasisType, RangeType, TreePathType> - { - using Super = DOFVectorConstView<GlobalBasisType, RangeType, TreePathType>; - - using GlobalBasis = GlobalBasisType; - using TreePath = TreePathType; - - public: - /// Constructor. Stores a pointer to the mutable `dofvector`. - DOFVectorMutableView(DOFVector<GlobalBasis,RangeType>& dofVector, TreePath const& treePath) - : Super(dofVector, treePath) - , mutableDofVector_(&dofVector) - {} - - public: - /// Interpolation of GridFunction to DOFVector template <class Expr> - DOFVectorMutableView& interpolate(Expr&& expr) + DOFVectorView& operator+=(Expr&& expr) { - auto const& basis = Super::basis(); - auto const& treePath = Super::treePath(); - - auto&& gridFct = makeGridFunction(std::forward<Expr>(expr), basis.gridView()); - - DOFVector<GlobalBasis,RangeType> tmp(*mutableDofVector_); - Dune::Functions::interpolate(basis, treePath, tmp, std::forward<decltype(gridFct)>(gridFct)); - - // move data from temporary vector into stored DOFVector - mutableDofVector_->vector() = std::move(tmp.vector()); + interpolate((*this) + expr); return *this; } template <class Expr> - DOFVectorMutableView& operator<<(Expr&& expr) + DOFVectorView& operator-=(Expr&& expr) { - return interpolate(expr); + interpolate((*this) - expr); + return *this; } @@ -307,42 +83,20 @@ namespace AMDiS DOFVector<GlobalBasis,RangeType>* mutableDofVector_; }; - /** @} **/ - -#ifndef DOXYGEN - // A Generator for a const \ref DOFVectorView. - template <class GlobalBasis, class RangeType, class TreePath> - auto makeDOFVectorView(DOFVector<GlobalBasis, RangeType> const& dofVector, TreePath const& treePath) - { - return DOFVectorConstView<GlobalBasis, RangeType, TreePath>{dofVector, treePath}; - } - - // A Generator for a mutable \ref DOFVectorView. + /// A Generator for a mutable \ref DOFVectorView template <class GlobalBasis, class RangeType, class TreePath> auto makeDOFVectorView(DOFVector<GlobalBasis, RangeType>& dofVector, TreePath const& treePath) { - return DOFVectorMutableView<GlobalBasis, RangeType, TreePath>{dofVector, treePath}; - } - - - // A Generator for a const \ref DOFVectorView. - template <class GlobalBasis, class RangeType> - auto makeDOFVectorView(DOFVector<GlobalBasis, RangeType> const& dofVector) - { - auto treePath = Dune::TypeTree::hybridTreePath(); - return DOFVectorConstView<GlobalBasis, RangeType, decltype(treePath)>{dofVector, treePath}; + return DOFVectorView<GlobalBasis, RangeType, TreePath>{dofVector, treePath}; } - // A Generator for a mutable \ref DOFVectorView. + /// A Generator for a mutable \ref DOFVectorView template <class GlobalBasis, class RangeType> auto makeDOFVectorView(DOFVector<GlobalBasis, RangeType>& dofVector) { auto treePath = Dune::TypeTree::hybridTreePath(); - return DOFVectorMutableView<GlobalBasis, RangeType, decltype(treePath)>{dofVector, treePath}; + return DOFVectorView<GlobalBasis, RangeType, decltype(treePath)>{dofVector, treePath}; } -#endif } // end namespace AMDiS - -#include "DOFVectorView.inc.hpp" diff --git a/src/amdis/gridfunctions/DerivativeGridFunction.hpp b/src/amdis/gridfunctions/DerivativeGridFunction.hpp index e4c0adc7..c9b3811d 100644 --- a/src/amdis/gridfunctions/DerivativeGridFunction.hpp +++ b/src/amdis/gridfunctions/DerivativeGridFunction.hpp @@ -3,6 +3,7 @@ #include <type_traits> #include <dune/functions/common/defaultderivativetraits.hh> +#include <dune/grid/utility/hierarchicsearch.hh> #include <amdis/gridfunctions/GridFunctionConcepts.hpp> @@ -52,11 +53,22 @@ namespace AMDiS static_assert(isValidRange<DerivativeTraits>(), "Derivative of GridFunction not defined"); } - /// NOTE: no global derivative available + /// Evaluate derivative in global coordinates. NOTE: expensive Range operator()(Domain const& x) const { - error_exit("Not implemented"); - return Range(0); + auto gv = entitySet().gridView(); + + using GridView = decltype(gv); + using Grid = typename GridView::Grid; + using IS = typename GridView::IndexSet; + + Dune::HierarchicSearch<Grid,IS> hsearch{gv.grid(), gv.indexSet()}; + + auto element = hsearch.findEntity(x); + auto geometry = element.geometry(); + auto localFct = derivative(localFunction(gridFct_)); + localFct.bind(element); + return localFct(geometry.local(x)); } /// Return the derivative-localFunction of the GridFunction. diff --git a/src/amdis/gridfunctions/DiscreteFunction.hpp b/src/amdis/gridfunctions/DiscreteFunction.hpp new file mode 100644 index 00000000..396fe04c --- /dev/null +++ b/src/amdis/gridfunctions/DiscreteFunction.hpp @@ -0,0 +1,245 @@ +#pragma once + +#include <vector> + +#include <dune/common/std/optional.hh> +#include <dune/functions/common/defaultderivativetraits.hh> +#include <dune/functions/functionspacebases/defaultnodetorangemap.hh> +#include <dune/functions/functionspacebases/flatvectorview.hh> +#include <dune/functions/gridfunctions/gridviewentityset.hh> +#include <dune/typetree/childextraction.hh> + +#include <amdis/GridFunctions.hpp> +#include <amdis/utility/FiniteElementType.hpp> + +namespace AMDiS +{ + /// \brief A view on a subspace of a \ref DOFVector + /** + * \ingroup GridFunctions + **/ + template <class GlobalBasisType, class RangeType, class TreePathType> + class DiscreteFunction + { + public: + using GlobalBasis = GlobalBasisType; + using TreePath = TreePathType; + + using Tree = typename GlobalBasis::LocalView::Tree; + using SubTree = typename Dune::TypeTree::ChildForTreePath<Tree, TreePath>; + using NodeToRangeEntry = Dune::Functions::DefaultNodeToRangeMap<SubTree>; + + using GridView = typename GlobalBasis::GridView; + using EntitySet = Dune::Functions::GridViewEntitySet<GridView, 0>; + + using Domain = typename EntitySet::GlobalCoordinate; + using Range = RangeType_t<SubTree>; + static_assert(std::is_arithmetic<RangeType>::value, ""); + // Don't know how to determine Range with non-trivial RangeType + + using RawSignature = typename Dune::Functions::SignatureTraits<Range(Domain)>::RawSignature; + using DerivativeTraits = Dune::Functions::DefaultDerivativeTraits<RawSignature>; + using DerivativeRange = typename DerivativeTraits::Range; + + using LocalDomain = typename EntitySet::LocalCoordinate; + using Element = typename EntitySet::Element; + using Geometry = typename Element::Geometry; + + enum { hasDerivative = false }; + + public: // a local view on the gradients + + /// A LocalFunction representing the derivative of the DOFVector + class GradientLocalFunction + { + public: + using Domain = LocalDomain; + using Range = DerivativeRange; + + enum { hasDerivative = false }; + + private: + using LocalView = typename GlobalBasis::LocalView; + + public: + GradientLocalFunction(DiscreteFunction const& globalFunction) + : globalFunction_(&globalFunction) + , localView_(globalFunction_->basis().localView()) + , subTree_(&child(localView_.tree(), globalFunction_->treePath())) + {} + + void bind(Element const& element) + { + localView_.bind(element); + geometry_.emplace(element.geometry()); + bound_ = true; + } + + void unbind() + { + localView_.unbind(); + geometry_.reset(); + bound_ = false; + } + + /// Evaluate Gradient at bound element in local coordinates + Range operator()(Domain const& x) const; + + friend int order(GradientLocalFunction const& self) + { + assert( self.bound_ ); + return std::max(0, polynomialDegree(*self.subTree_)-1); + } + + /// Return the bound element + Element const& localContext() const + { + assert( bound_ ); + return localView_.element(); + } + + private: + DiscreteFunction const* globalFunction_; + LocalView localView_; + + SubTree const* subTree_; + + Dune::Std::optional<Geometry> geometry_; + bool bound_ = false; + }; + + + public: // a local view on the values + + /// A LocalFunction, i.e., an element local view on the DOFVector + class LocalFunction + { + public: + using Domain = typename DiscreteFunction::LocalDomain; + using Range = typename DiscreteFunction::Range; + + enum { hasDerivative = true }; + + private: + using LocalView = typename GlobalBasis::LocalView; + + public: + LocalFunction(DiscreteFunction const& globalFunction) + : globalFunction_(&globalFunction) + , localView_(globalFunction_->basis().localView()) + , subTree_(&child(localView_.tree(), globalFunction_->treePath())) + {} + + void bind(Element const& element) + { + localView_.bind(element); + bound_ = true; + } + + void unbind() + { + localView_.unbind(); + bound_ = false; + } + + /// Evaluate LocalFunction at bound element in local coordinates + Range operator()(Domain const& x) const; + + /// \brief Create a LocalFunction representing the gradient. \relates GradientLocalFunction + friend GradientLocalFunction derivative(LocalFunction const& localFunction) + { + static_assert(isValidRange<DerivativeTraits>(), + "Derivative of DOFVector not defined."); + return GradientLocalFunction{*localFunction.globalFunction_}; + } + + friend int order(LocalFunction const& self) + { + assert( self.bound_ ); + return polynomialDegree(*self.subTree_); + } + + /// Return the bound element + Element const& localContext() const + { + assert( bound_ ); + return localView_.element(); + } + + private: + DiscreteFunction const* globalFunction_; + LocalView localView_; + SubTree const* subTree_; + + bool bound_ = false; + }; + + + public: + /// Constructor. Stores a pointer to the dofVector and a copy of the treePath. + DiscreteFunction(DOFVector<GlobalBasis,RangeType> const& dofVector, TreePath const& treePath) + : dofVector_(&dofVector) + , treePath_(treePath) + , entitySet_(dofVector.basis().gridView()) + , nodeToRangeEntry_(Dune::Functions::makeDefaultNodeToRangeMap(dofVector.basis(), treePath)) + {} + + /// Evaluate DiscreteFunction in global coordinates. NOTE: expensive + Range operator()(Domain const& x) const; + + /// \brief Create a local function for this view on the DOFVector. \relates LocalFunction + friend LocalFunction localFunction(DiscreteFunction const& self) + { + return LocalFunction{self}; + } + + EntitySet const& entitySet() const + { + return entitySet_; + } + + public: + /// Return global basis + GlobalBasis const& basis() const + { + return dofVector_->basis(); + } + + /// Return treePath associated with this view + TreePath const& treePath() const + { + return treePath_; + } + + /// Return const coefficient vector + DOFVector<GlobalBasis,RangeType> const& coefficients() const + { + return *dofVector_; + } + + protected: + DOFVector<GlobalBasis,RangeType> const* dofVector_; + TreePath const treePath_; + + EntitySet entitySet_; + NodeToRangeEntry nodeToRangeEntry_; + }; + + /// A Generator for a \ref DiscreteFunction + template <class GlobalBasis, class RangeType, class TreePath> + auto makeDiscreteFunction(DOFVector<GlobalBasis, RangeType> const& dofVector, TreePath const& treePath) + { + return DiscreteFunction<GlobalBasis, RangeType, TreePath>{dofVector, treePath}; + } + + /// A Generator for a \ref DiscreteFunction + template <class GlobalBasis, class RangeType> + auto makeDiscreteFunction(DOFVector<GlobalBasis, RangeType> const& dofVector) + { + auto treePath = Dune::TypeTree::hybridTreePath(); + return DiscreteFunction<GlobalBasis, RangeType, decltype(treePath)>{dofVector, treePath}; + } + +} // end namespace AMDiS + +#include "DiscreteFunction.inc.hpp" diff --git a/src/amdis/gridfunctions/DOFVectorView.inc.hpp b/src/amdis/gridfunctions/DiscreteFunction.inc.hpp similarity index 83% rename from src/amdis/gridfunctions/DOFVectorView.inc.hpp rename to src/amdis/gridfunctions/DiscreteFunction.inc.hpp index 939b89a0..fc6faa73 100644 --- a/src/amdis/gridfunctions/DOFVectorView.inc.hpp +++ b/src/amdis/gridfunctions/DiscreteFunction.inc.hpp @@ -3,10 +3,12 @@ #include <amdis/common/FieldMatVec.hpp> #include <amdis/LocalBasisCache.hpp> +#include <dune/grid/utility/hierarchicsearch.hh> + namespace AMDiS { template <class GB, class RT, class TP> -typename DOFVectorConstView<GB,RT,TP>::Range DOFVectorConstView<GB,RT,TP>:: +typename DiscreteFunction<GB,RT,TP>::Range DiscreteFunction<GB,RT,TP>:: LocalFunction::operator()(LocalDomain const& x) const { assert( bound_ ); @@ -50,7 +52,7 @@ LocalFunction::operator()(LocalDomain const& x) const template <class GB, class RT, class TP> -typename DOFVectorConstView<GB,RT,TP>::DerivativeRange DOFVectorConstView<GB,RT,TP>:: +typename DiscreteFunction<GB,RT,TP>::DerivativeRange DiscreteFunction<GB,RT,TP>:: GradientLocalFunction::operator()(LocalDomain const& x) const { assert( bound_ ); @@ -106,4 +108,22 @@ GradientLocalFunction::operator()(LocalDomain const& x) const return dy; } + +template <class GB, class RT, class TP> +typename DiscreteFunction<GB,RT,TP>::Range DiscreteFunction<GB,RT,TP>:: +operator()(Domain const& x) const +{ + using Grid = typename GB::GridView::Grid; + using IS = typename GB::GridView::IndexSet; + + auto const& gv = this->basis().gridView(); + Dune::HierarchicSearch<Grid,IS> hsearch{gv.grid(), gv.indexSet()}; + + auto element = hsearch.findEntity(x); + auto geometry = element.geometry(); + auto localFct = localFunction(*this); + localFct.bind(element); + return localFct(geometry.local(x)); +} + } // end namespace AMDiS diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a18847f2..363a35a6 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -11,6 +11,10 @@ dune_add_test(SOURCES ConceptsTest.cpp dune_add_test(SOURCES DOFVectorTest.cpp LINK_LIBRARIES amdis) +dune_add_test(SOURCES DiscreteFunctionTest.cpp + LINK_LIBRARIES amdis + CMD_ARGS "${CMAKE_SOURCE_DIR}/examples/init/ellipt.dat.2d") + dune_add_test(SOURCES ExpressionsTest.cpp LINK_LIBRARIES amdis CMD_ARGS "${CMAKE_SOURCE_DIR}/examples/init/ellipt.dat.2d") diff --git a/test/DiscreteFunctionTest.cpp b/test/DiscreteFunctionTest.cpp new file mode 100644 index 00000000..bd3edbf4 --- /dev/null +++ b/test/DiscreteFunctionTest.cpp @@ -0,0 +1,102 @@ +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: + +#include <iostream> + +#include <amdis/AMDiS.hpp> +#include <amdis/ProblemStat.hpp> +#include <amdis/Operators.hpp> +#include <amdis/common/Literals.hpp> +#include <amdis/common/FieldMatVec.hpp> +#include <amdis/gridfunctions/Integrate.hpp> + +#include "Tests.hpp" + +using namespace AMDiS; + +using ElliptParam = YaspGridBasis<2, 2>; +using ElliptProblem = ProblemStat<ElliptParam>; + +template <class GB, class T> +bool comp(DOFVector<GB,T> const& U, DOFVector<GB,T> const& V) +{ + if (U.size() != V.size()) + return false; + + using Int = typename DOFVector<GB,T>::size_type; + for (Int i = 0; i < U.size(); ++i) { + if (U[i] != V[i]) + return false; + } + return true; +} + +int main(int argc, char** argv) +{ + AMDiS::init(argc, argv); + + using namespace Dune::Indices; + + ElliptProblem prob("ellipt"); + prob.initialize(INIT_ALL); + + // create 3 copies of the solution vector + auto U0 = prob.getSolutionVector(); + auto U1 = prob.getSolutionVector(); + auto U2 = prob.getSolutionVector(); + + auto u0 = makeDOFVectorView(U0); + auto u1 = makeDOFVectorView(U1); + auto u2 = makeDOFVectorView(U2); + + auto expr = [](auto const& x) { return x[0] + x[1]; }; + u0.interpolate_noalias(expr); + u1.interpolate(expr); + u2 << expr; + + AMDIS_TEST( comp(U0, U1) ); + AMDIS_TEST( comp(U0, U2) ); + + auto expr2 = [](auto const& x) { return 2*x[0] - 3*x[1]; }; + + u0.interpolate_noalias(u2 + expr2); + u1.interpolate(u1 + expr2); + u2 += expr2; + + AMDIS_TEST( comp(U0, U1) ); + AMDIS_TEST( comp(U0, U2) ); + + auto expr3 = [](auto const& x) { return -0.5*x[0] - 2*x[1]; }; + + u0.interpolate_noalias(u2 - expr3); + u1.interpolate(u1 - expr3); + u2 -= expr3; + + AMDIS_TEST( comp(U0, U1) ); + AMDIS_TEST( comp(U0, U2) ); + + auto du0 = derivative(u0); + auto localFct = localFunction(u0); + auto dlocalFct = derivative(localFct); + for (auto const& e : elements(prob.gridView())) + { + localFct.bind(e); + auto geo = e.geometry(); + auto local = referenceElement(geo).position(0,0); + auto y0 = localFct(local); + auto y1 = u0(geo.global(local)); + + AMDIS_TEST(std::abs(y0 - y1) < 1.e-10); + localFct.unbind(); + + dlocalFct.bind(e); + auto g0 = dlocalFct(local); + auto g1 = du0(geo.global(local)); + + AMDIS_TEST(two_norm(g0 - g1) < 1.e-10); + dlocalFct.unbind(); + } + + AMDiS::finalize(); + return 0; +} -- GitLab