#pragma once #include #include #include #include #include #include #include #include #include #include #include namespace AMDiS { /// \class DiscreteFunction /// \brief A view on a subspace of a \ref DOFVector /** * \ingroup GridFunctions * * \tparam Coeff Const or mutable coefficient type of the DOFVector * \tparam GB Thy type of the global basis * \tparam TreePath A realization of \ref Dune::TypeTree::HybridTreePath * * **Requirements:** * - GB models \ref Concepts::GlobalBasis **/ template > class DiscreteFunction; // deduction guide template DiscreteFunction(Coeff&, GB const&, TreePath = {}) -> DiscreteFunction>; /// A Generator for a mutable \ref DiscreteFunction template ().localView())> > auto makeDiscreteFunction(Coeff& coefficients, GB const& basis, Path const& path = {}) { return DiscreteFunction>{coefficients, basis, path}; } /// A mutable view on the subspace of a DOFVector, \relates DiscreteFunction template class DiscreteFunction : public DiscreteFunction { using Self = DiscreteFunction; using Super = DiscreteFunction; using Coefficients = Coeff; using GlobalBasis = GB; using ValueType = typename Coeff::value_type; public: /// Constructor. Stores a pointer to the mutable dofvector. template DiscreteFunction(Coefficients& dofVector, GlobalBasis const& basis, Path const& path = {}) : Super(dofVector, basis, path) , mutableCoeff_(&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 Coefficients& coefficients() { return *mutableCoeff_; } /// Return the const DOFVector using Super::coefficients; template auto child(Path const& path = {}) { auto tp = cat(this->treePath_, makeTreePath(path)); return makeDiscreteFunction(*mutableCoeff_, this->basis(), tp); } using Super::child; protected: Coefficients* mutableCoeff_; }; /// A Const DiscreteFunction template class DiscreteFunction { private: using Coefficients = std::remove_const_t; using GlobalBasis = GB; using ValueType = typename Coefficients::value_type; 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. template DiscreteFunction(Coefficients const& coefficients, GlobalBasis const& basis, Path const& path = {}) : coefficients_(&coefficients) , basis_(&basis) , treePath_(makeTreePath(path)) , entitySet_(basis_->gridView()) , nodeToRangeEntry_(Dune::Functions::makeDefaultNodeToRangeMap(*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 GlobalBasis const& basis() const { return *basis_; } /// \brief Return treePath associated with this discrete function TreePath const& treePath() const { return treePath_; } /// \brief Return const coefficient vector Coefficients const& coefficients() const { return *coefficients_; } template auto child(Path const& path = {}) const { auto tp = cat(this->treePath_, makeTreePath(path)); return makeDiscreteFunction(*coefficients_, *basis_, tp); } protected: Coefficients const* coefficients_; GlobalBasis const* basis_; TreePath treePath_; EntitySet entitySet_; NodeToRangeEntry nodeToRangeEntry_; }; } // end namespace AMDiS #include "DiscreteLocalFunction.inc.hpp" #include "DiscreteFunction.inc.hpp"