#pragma once #include #include #include #include namespace AMDiS { /** * \addtogroup GridFunctions * @{ **/ /// \brief A Gridfunction that returns the derivative when calling localFunction. /** * Wrapps the GridFunction so that \ref localFunction returns a LocalFunction * representing the derivative of the LocalFunction of the GridFunction. * * \tparam GridFunction The GridFunction that is wrapped. * * **Requirements:** * - `GridFunction` models \ref Concepts::GridFunction and the LocalFunction has a derivative. **/ template class DerivativeGridFunction { using GridFctRange = typename GridFunction::Range; using GridFctDomain = typename GridFunction::Domain; using RawSignature = typename Dune::Functions::SignatureTraits::RawSignature; using DerivativeTraits = Dune::Functions::DefaultDerivativeTraits; using LocalFunction = std::decay_t())))>; enum { hasDerivative = false }; public: /// The Range of the derivative of the GridFunction using Range = typename DerivativeTraits::Range; /// The domain of the GridFunction using Domain = GridFctDomain; /// The EntitySet of the GridFunction using EntitySet = typename GridFunction::EntitySet; public: /// Constructor. Stores a copy of gridFct. explicit DerivativeGridFunction(GridFunction const& gridFct) : gridFct_{gridFct} { static_assert(isValidRange(), "Derivative of GridFunction not defined"); } /// Evaluate derivative in global coordinates. NOTE: expensive Range operator()(Domain const& x) const { auto gv = entitySet().gridView(); using GridView = decltype(gv); using Grid = typename GridView::Grid; using IS = typename GridView::IndexSet; Dune::HierarchicSearch 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. friend LocalFunction localFunction(DerivativeGridFunction const& gf) { return derivative(localFunction(gf.gridFct_)); } /// Return the \ref EntitySet of the \ref GridFunction. EntitySet const& entitySet() const { return gridFct_.entitySet(); } private: GridFunction gridFct_; }; #ifndef DOXYGEN template ())), REQUIRES(not GridFct::hasDerivative)> auto derivative(GridFct const& gridFct) { static_assert(Concepts::HasDerivative, "derivative(LocalFunction) not defined!"); return DerivativeGridFunction{gridFct}; } template struct DerivativePreGridFunction { using Self = DerivativePreGridFunction; struct Creator { template static auto create(Self const& self, GridView const& gridView) { return derivative(makeGridFunction(self.expr_, gridView)); } }; Expr expr_; }; namespace Traits { template struct IsPreGridFunction> : std::true_type {}; } #endif /// \brief Generator function for DerivativeGridFunction expressions. \relates DerivativeGridFunction /** * Generates a derivative of a GridFunction. See \ref DerivativeGridFunction. * * **Examples:** * - `gradientAtQP(prob.getSolution(_0))` * - `gradientAtQP(X(0) + X(1) + prob.getSolution(_0))` **/ template auto gradientAtQP(Expr const& expr) { return DerivativePreGridFunction{expr}; } /** @} **/ } // end namespace AMDiS