#ifndef MEDUSA_BITS_APPROXIMATIONS_OPERATORS_FWD_HPP_ #define MEDUSA_BITS_APPROXIMATIONS_OPERATORS_FWD_HPP_ /** * @file * File defining basic differential operator families. * * @example test/approximations/operators_test.cpp */ #include #include #include #include #include "Monomials_fwd.hpp" #include namespace mm { /** * Base class for a differential operator. Also doubles as a one-element family. * @tparam Derived Derived class inheriting, used for CRTP. * @ingroup approximations * * Example of custom operator usage. Definition: * @snippet approximations/operators_test.cpp Biharmonic def * Usage: * @snippet approximations/operators_test.cpp Biharmonic usage * * See also custom_operators example in the examples suite. */ template struct Operator { typedef Derived operator_t; ///< Type of the contained operators. static constexpr int size() { return 1; } ///< Size of a single-operator family is always 1. static constexpr int index(Derived) { return 0; } ///< Index is always 0. std::string name() const { return Derived::name(); } ///< CRTP for human-readable name. static std::string type_name() { return Derived::type_name(); } ///< Human-readable type name. /** * Return an iterable of iterators represented by a family. * As this is a single operator, the family consists of itself only. */ std::array operators() const { return {*static_cast(this)}; } /** * Apply this operator to a given basis function. This function should be specialized * (overloaded) for more concrete values of `basis_t` in concrete classes inheriting form * this one. It is intended that this function is never called but only serves as a default * for demonstration purposes and better error messages. * @tparam basis_t Basis type. * @param basis The basis @f$b@f$ to apply the operator to. * @param index Which element of the basis to apply the operator to. * @param point At which aldeary shifted and translated point to apply the operator. * @param support Local support domain (already shifted and scaled). These are the values * @f$(x-c)/s@f$ in the equation below. * @param scale Local scaling factor @f$s@f$ * @return Let this operator be called @f$L@f$, the `index`-th basis function @f$b_i@f$. * The function returns @f$L b_i((x-c)/s)@f$. Not that the operator @f$L@f$ is usually * something like "derivative wrt. x" and factors of @f$s@f$ appear in the result. * @sa RBFBasis::evalOp, Monomials::evalOp, applyAt0 */ template typename basis_t::scalar_t apply( const basis_t& basis, int index, typename basis_t::vector_t point, const std::vector& support, typename basis_t::scalar_t scale) const; /** * Like @ref apply, but with point equal to 0. * @sa apply, RBFBasis::evalOpAt0, Monomials::evalOpAt0 */ template typename basis_t::scalar_t applyAt0( const basis_t& basis, int index, const std::vector& support, typename basis_t::scalar_t scale) const; }; /// Output info about given operator. template std::ostream& operator<<(std::ostream& os, const Operator& op) { return os << op.name(); } /// Represents the Laplacian operator. @ingroup approximations template struct Lap : public Operator> { /// Store dimension of the domain. enum { /** Dimensionality of the domain. */ dim = dimension }; static std::string name() { return format("Laplacian<%d>", dim); } ///< Human-readable name. static std::string type_name() { return name(); } ///< Human readable type name. }; /** * Represents a family of all first derivatives. * @ingroup approximations */ template struct Der1s { /// Store dimension of the domain. enum { /** Dimensionality of the domain. */ dim = dimension }; typedef Der1 operator_t; ///< Type of this family's members. static int size() { return dim; } ///< Size of this family is `dim`. static std::string name() { return format("Der1s<%d>", dim); } ///< Human-readable name. static std::string type_name() { return name(); } ///< Human readable type name. /// Return an iterable of iterators represented by a family. static std::array, dimension> operators(); /// Get index of operator `d` in the family. static int index(Der1 d) { return d.var; } }; /// Output info about Der1s template std::ostream& operator<<(std::ostream& os, const Der1s& op) { return os << op.name(); } /** * Represents a family of all second derivatives. * @ingroup approximations */ template struct Der2s { /// Store dimension of the domain. enum { /** Dimensionality of the domain. */ dim = dimension }; typedef Der2 operator_t; ///< Type of this family's members. static int size() { return dim * (dim + 1) / 2; } ///< Size of this family is `dim*(dim-1)/2`. static std::string name() { return format("Der2s<%d>", dim); } ///< Human-readable name. static std::string type_name() { return name(); } ///< Human readable type name. /// Return an iterable of iterators represented by a family. static std::array, dimension * (dimension + 1) / 2> operators(); /// Get index of operator `d` in the family. static int index(Der2 d) { return (d.var2 == 2 ? d.var1 + 1 : d.var1) + d.var2; } }; /// Output info about Der2s template std::ostream& operator<<(std::ostream& os, const Der2s& op) { return os << op.name(); } /// Represents a first derivative wrt. `var`. @ingroup approximations template struct Der1 : public Operator> { /// Store dimension of the domain. enum { /** Dimensionality of the domain. */ dim = dimension }; int var; ///< Index representing derived variable (x = 0, y = 1, z = 2) /// Default constructor for array preallocation purposes. Der1() : var(-1) {} /** * Initialization of specific 1st derivative operator. * @param var Index representing derived variable (x = 0, y = 1, z = 2). */ Der1(int var); /// Human readable name. std::string name() const; /// Human readable type name. static std::string type_name() { return format("Der1<%d>", dim); } }; /// Represents a second derivative wrt. `var1` and `var2`. @ingroup approximations template struct Der2 : public Operator> { /// Store dimension of the domain. enum { /** Dimensionality of the domain. */ dim = dimension }; int var1, ///< Lower index representing derived variable (x = 0, y = 1, z = 2, ...) var2; ///< Higher index representing derived variable (x = 0, y = 1, z = 2, ...) /// Default constructor for array preallocation purposes. Der2() : var1(-1), var2(-1) {} /** * Initialization of specific 2nd derivative operator. * @param var1 First variable with respect to which the derivative is taken. * variable (x = 0, y = 1, z = 2, ...). * @param var2 Second variable with respect to which the derivative is taken. * (Should have higher index and the first variable.) * variable (x = 0, y = 1, z = 2, ...). */ Der2(int var1, int var2); /** * Initialization of specific 2nd derivative operator. * @param var Index representing two times derived variable (x = 0, y = 1, z = 2, ...). */ Der2(int var) : Der2(var, var) {} /// Human readable name. std::string name() const; /// Human readable type name. static std::string type_name() { return format("Der2<%d>", dim); } }; /** * Represents a general derivative @f$\frac{\partial^{|\alpha|}}{\partial x^\alpha}@f$. * @ingroup approximations */ template struct Derivative : public Operator> { /// Store dimension of the domain. enum { /** Dimensionality of the domain. */ dim = dimension }; std::array orders; ///< Values @f$\alpha@f$. /// Parameter `orders` represent the derivative orders @f$\alpha@f$. Derivative(const std::array& orders) : orders(orders) {} /// Human readable name. std::string name() { return format("Derivative<%d> wrt. %s", dim, orders); } /// Human readable type name. static std::string type_name() { return format("Derivative<%d>", dim); } }; } // namespace mm #endif // MEDUSA_BITS_APPROXIMATIONS_OPERATORS_FWD_HPP_