#pragma once #include #include #include #include #include #include #include #include #include #include #include namespace AMDiS { template class DOFVector; /// \class DiscreteFunction /// \brief A view on a subspace of a \ref DOFVector /** * \ingroup GridFunctions * * \tparam GB Type of the global basis * \tparam VT Coefficient type of the DOFVector * \tparam TP A realization of \ref Dune::TypeTree::HybridTreePath * \tparam is_const Specifies whether a const or mutable view is implemented. * * **Requirements:** * - GB models \ref Dune::Functions::Concept::GlobalBasis **/ template class DiscreteFunction; #if DUNE_HAVE_CXX_CLASS_TEMPLATE_ARGUMENT_DEDUCTION // Deduction guide for DiscreteFunction class template DiscreteFunction(DOFVector const& dofVector) -> DiscreteFunction, true>; template DiscreteFunction(DOFVector& dofVector) -> DiscreteFunction, false>; #endif /// A Generator for a const \ref DiscreteFunction template > auto makeDiscreteFunction(DOFVector const& dofVector, PreTreePath const& preTreePath = {}) { auto treePath = makeTreePath(preTreePath); return DiscreteFunction{dofVector, treePath}; } /// A Generator for a mutable \ref DiscreteFunction template > auto makeDiscreteFunction(DOFVector& dofVector, PreTreePath const& preTreePath = {}) { auto treePath = makeTreePath(preTreePath); return DiscreteFunction{dofVector, treePath}; } /// A Const DiscreteFunction template class DiscreteFunction { private: using GlobalBasis = GB; using TreePath = TP; using Tree = typename GlobalBasis::LocalView::Tree; using SubTree = typename Dune::TypeTree::ChildForTreePath; using NodeToRangeEntry = Dune::Functions::DefaultNodeToRangeMap; using GridView = typename GlobalBasis::GridView; public: /// Set of entities the DiscreteFunction is defined on using EntitySet = Dune::Functions::GridViewEntitySet; /// Global coordinates of the EntitySet using Domain = typename EntitySet::GlobalCoordinate; /// Range type of this DiscreteFunction using Range = RangeType_t; /// \brief This GridFunction has no derivative function, it can be created /// by \ref DiscreteGridFunction. enum { hasDerivative = false }; public: /// A LocalFunction representing the derivative of the DOFVector on a bound element template class DerivativeLocalFunctionBase; class GradientLocalFunction; class PartialLocalFunction; class DivergenceLocalFunction; /// A LocalFunction representing the value the DOFVector on a bound element class LocalFunction; public: /// Constructor. Stores a pointer to the dofVector and a copy of the treePath. DiscreteFunction(DOFVector const& dofVector, TP const& treePath = {}) : dofVector_(&dofVector) , treePath_(treePath) , entitySet_(dofVector.basis()->gridView()) , nodeToRangeEntry_(Dune::Functions::makeDefaultNodeToRangeMap(*dofVector.basis(), treePath)) {} /// \brief 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 LocalFunction makeLocalFunction() const { return LocalFunction{*this}; } /// \brief Return a \ref Dune::Functions::GridViewEntitySet EntitySet const& entitySet() const { return entitySet_; } /// \brief Return global basis bound to the DOFVector std::shared_ptr basis() const { return dofVector_->basis(); } /// \brief Return treePath associated with this discrete function TreePath const& treePath() const { return treePath_; } /// \brief Return const coefficient vector DOFVector const& coefficients() const { return *dofVector_; } protected: DOFVector const* dofVector_; TreePath treePath_; EntitySet entitySet_; NodeToRangeEntry nodeToRangeEntry_; }; /// A mutable view on the subspace of a DOFVector, \relates DiscreteFunction template class DiscreteFunction : public DiscreteFunction { using Self = DiscreteFunction; using Super = DiscreteFunction; using GlobalBasis = GB; using TreePath = TP; public: /// Constructor. Stores a pointer to the mutable `dofvector`. DiscreteFunction(DOFVector& dofVector, TP const& treePath = {}) : Super(dofVector, treePath) , mutableDofVector_(&dofVector) {} public: /// \brief Interpolation of GridFunction to DOFVector, assuming that there is no /// reference to this DOFVector in the expression. /** * **Example:** * ``` * auto v = makeDiscreteFunction(prob.solutionVector(),0); * v.interpolate_noalias([](auto const& x) { return x[0]; }); * ``` **/ template void interpolate_noalias(Expr&& expr, Tag strategy = {}); /// \brief Interpolation of GridFunction to DOFVector /** * **Example:** * ``` * auto v = makeDiscreteFunction(prob.solutionVector(),0); * v.interpolate(v + [](auto const& x) { return x[0]; }); * ``` * Allows to have a reference to the DOFVector in the expression, e.g. as * \ref DiscreteFunction or \ref gradientAtQP() of a DiscreteFunction. **/ template void interpolate(Expr&& expr, Tag strategy = {}); /// \brief Interpolation of GridFunction to DOFVector, alias to \ref interpolate() template Self& operator<<(Expr&& expr) { interpolate(FWD(expr)); return *this; } /// \brief interpolate `(*this) + expr` to DOFVector template Self& operator+=(Expr&& expr) { interpolate((*this) + expr); return *this; } /// \brief interpolate `(*this) - expr` to DOFVector template Self& operator-=(Expr&& expr) { interpolate((*this) - expr); return *this; } /// Return the mutable DOFVector DOFVector& coefficients() { return *mutableDofVector_; } /// Return the const DOFVector using Super::coefficients; protected: DOFVector* mutableDofVector_; }; } // end namespace AMDiS #include "DiscreteLocalFunction.inc.hpp" #include "DiscreteFunction.inc.hpp"