#pragma once #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())))>; 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"); } /// NOTE: no global derivative available Range operator()(Domain const& x) const { error_exit("Not implemented"); return Range(0); } /// 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 && Concepts::HasLocalFunctionDerivative)> auto derivative(GridFct const& gridFct) { return DerivativeGridFunction{gridFct}; } template struct DerivativePreGridFunction { 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}; } /** @} **/ namespace Impl { /// Generator function for \ref AnalyticGridFunction expressions from \ref AnalyticPreGridFunction. template auto makeGridFunctionImpl(DerivativePreGridFunction const& pre, GridView const& gridView, Dune::PriorityTag<3>) { return derivative(Impl::makeGridFunctionImpl(pre.expr, gridView, Dune::PriorityTag<10>{})); } } // end namespace Impl } // end namespace AMDiS