#pragma once #include #include namespace AMDiS { /// A mutable view on the subspace of a DOFVector, \relates DiscreteFunction template class DOFVectorView : public DiscreteFunction { using Self = DOFVectorView; using Super = DiscreteFunction; using GlobalBasis = GB; using TreePath = TP; public: /// Constructor forwards to the treePath constructor, with empty TreePath DOFVectorView(DOFVector& dofVector) : DOFVectorView{dofVector, Dune::TypeTree::hybridTreePath()} {} /// Constructor. Stores a pointer to the mutable `dofvector`. DOFVectorView(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 = makeDOFVectorView(prob.solutionVector(),0); * v.interpolate_noalias([](auto const& x) { return x[0]; }); * ``` **/ template void interpolate_noalias(Expr&& expr) { auto const& basis = this->basis(); auto const& treePath = this->treePath(); auto&& gridFct = makeGridFunction(std::forward(expr), basis.gridView()); Dune::Functions::interpolate(basis, treePath, coefficients(), std::forward(gridFct)); } /// \brief Interpolation of GridFunction to DOFVector /** * **Example:** * ``` * auto v = makeDOFVectorView(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) { // create temporary copy of data DOFVector tmp(coefficients()); Self tmpView{tmp, this->treePath()}; tmpView.interpolate_noalias(std::forward(expr)); // move data from temporary vector into stored DOFVector coefficients().vector() = std::move(tmp.vector()); } /// \brief Interpolation of GridFunction to DOFVector, alias to \ref interpolate() template DOFVectorView& operator<<(Expr&& expr) { interpolate(expr); return *this; } /// \brief interpolate `(*this) + expr` to DOFVector template DOFVectorView& operator+=(Expr&& expr) { interpolate((*this) + expr); return *this; } /// \brief interpolate `(*this) - expr` to DOFVector template DOFVectorView& 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_; }; #if DUNE_HAVE_CXX_CLASS_TEMPLATE_ARGUMENT_DEDUCTION // Deduction guide for DOFVectorView class template DOFVectorView(DOFVector& dofVector) -> DOFVectorView>; #endif /// A Generator for a mutable \ref DOFVectorView template auto makeDOFVectorView(DOFVector& dofVector, PreTreePath const& preTreePath) { auto treePath = makeTreePath(preTreePath); return DOFVectorView{dofVector, treePath}; } /// A Generator for a mutable \ref DOFVectorView template auto makeDOFVectorView(DOFVector& dofVector) { auto treePath = Dune::TypeTree::hybridTreePath(); return DOFVectorView>{dofVector, treePath}; } } // end namespace AMDiS