#ifndef MEDUSA_BITS_OPERATORS_SHAPESTORAGE_FWD_HPP_ #define MEDUSA_BITS_OPERATORS_SHAPESTORAGE_FWD_HPP_ /** * @file * Base class and interface for storing and accessing computed shapes. */ #include #include #include #include #include #include #include namespace mm { template class ExplicitOperators; template class ExplicitVectorOperators; template class ImplicitOperators; template class ImplicitVectorOperators; /** * Shape storage base class. It supports storing computed shapes for Lap, D1 and D2 operators. * Derived classes should inherit the interface via CRTP and implement missing methods. * * @ingroup operators * * @sa UniformShapeStorage, RaggedShapeStorage */ template , Der1s, Der2s>> class ShapeStorage { public: typedef vec_t vector_t; ///< Vector type used. typedef typename vec_t::scalar_t scalar_t; ///< Scalar type used. /// Bitmask telling us which shapes to create. /// Store dimension of the domain. enum { /** Dimensionality of the domain. */ dim = vec_t::dim }; typedef OpFamilies op_families_tuple; ///< Tuple of operator families /// Number of operator families in this storage. constexpr static int num_operators = std::tuple_size::value; friend Derived; ///< Be friends with derived class. private: /// Total number of nodes. int domain_size_; /// Local copy of support domains. Range support_; /// Tuple of shape containers for given operators. std::array, num_operators> shapes_; /// Returns pointer to the start of values for `node`-th node for `op`-th operator. template SINL T* access(std::vector& v, int op, int node) const { return static_cast(this)->access(v, op, node); } /// Returns pointer to the start of values for `node`-th node. template SINL T* access(std::vector& v, int node) const { return static_cast(this)->access(v, node); } /// Returns const pointer to the start of values for `node`-th node for `op`-th operator. template SINL const T* access(const std::vector& v, int op, int node) const { return static_cast(this)->access(v, op, node); } /// Returns const pointer to the start of values for `node`-th node. template SINL const T* access(const std::vector& v, int node) const { return static_cast(this)->access(v, node); } /// Constructs empty storage with size 0. Can be resized with @ref resize. ShapeStorage() : domain_size_(0) {} public: /// Resizes the storage to accommodate shapes of given sizes. void resize(const std::vector& support_sizes) { domain_size_ = support_sizes.size(); static_cast(this)->resize_(support_sizes); } /// Returns number of nodes. int size() const { return domain_size_; } /** * Returns index of `j`-th neighbour of `node`-th node, i.e.\ `support[node][j]`, * but possibly faster. */ SINL int support(int node, int j) const; /// Returns a collection of support indices for given `node`. SINL Eigen::Map> support(int node) const; /// Sets support of `node`-th node to `support`. void setSupport(int node_idx, const std::vector& support); /// Returns support size of `node`-th node. int supportSize(int node) const { return static_cast(this)->supportSize(node); } /** * Returns a vector of support sizes for all nodes, useful for matrix space preallocation. * @warning If there are ghost nodes present, their support sizes might be zero. However, * matrix rows corresponding to ghost nodes must still be preallocated. * @sa supportSizesVec */ Range supportSizes() const; /** * Returns a `dim*N` vector of `dim*support_size`, useful for matrix space preallocation * for vector equations. Same warning as for @ref supportSizes applies. * @sa supportSizes */ Range supportSizesVec() const; // GENERAL GETTERS /// Read access to complete shape storage. const std::array, num_operators>& shapes() const { return shapes_; } /// Get the weight of `j`-th stencil node of `node` for operator `op` in `op_family` (by index). template SINL scalar_t get(int op, int node, int j) const { return access(shapes_[op_family], op, node)[j]; } /// Get the weight of `j`-th stencil node of `node` for operator `op` in `op_family` (by type). template SINL scalar_t get(int op, int node, int j) const { return get::value>(op, node, j); } /// Get the `j`-th weight of shape for `node` for the only operator in `op_family` (by index). template SINL scalar_t get(int node, int j) const { return access(shapes_[op_family], node)[j]; } /// Get the `j`-th weight of shape for `node` for the only operator in `op_family` (by type). template SINL scalar_t get(int node, int j) const { return get::value>(node, j); } /// Get the shape for `node` for operator `op` in `op_family` (by index). template Eigen::Map> getShape(int op, int node) const { return {access(shapes_[op_family], op, node), supportSize(node)}; } /// Get the shape for `node` for operator `op` in `op_family` (by type). template Eigen::Map> getShape(int op, int node) const { return getShape::value>(op, node); } /// Get the shape for `node` for the only operator in `op_family` (by index). template SINL Eigen::Map> getShape(int node) const { return {access(shapes_[op_family], node), supportSize(node)}; } /// Get the shape for `node` for the only operator in `op_family` (by type). template SINL Eigen::Map> getShape(int node) const { return getShape::value>(node); } // GENERAL SETTERS /// Set the shape for `node` for operator `op` in `op_family` (by index). template SINL void setShape(int op, int node, const Eigen::Matrix& shape) { std::memcpy(access(shapes_[op_family], op, node), shape.data(), supportSize(node)*sizeof(scalar_t)); } /// Set the shape for `node` for operator `op` in `op_family` (by type). template SINL void setShape(int op, int node, const Eigen::Matrix& shape) { return setShape::value>(op, node, shape); } /// Set the shape for `node` for the only operator in `op_family` (by index). template SINL void setShape(int node, const Eigen::Matrix& shape) { std::memcpy(access(shapes_[op_family], node), shape.data(), supportSize(node)*sizeof(scalar_t)); } /// Set the shape for `node` for the only operator in `op_family` (by type). template SINL void setShape(int node, const Eigen::Matrix& shape) { return setShape::value>(node, shape); } // SPECIFIC ACCESSORS /// Return `j-th` laplace shape coefficient for `node`-th node. SINL scalar_t laplace(int node, int j) const; /// Returns the laplace shape for `node`. Eigen::Map> laplace(int node) const; /// Sets the laplace shape for `node` to `shape`. SINL void setLaplace(int node, const Eigen::Matrix& shape); /// Return `j`-th shape coefficient for derivative wrt. variable `var` in `node`. SINL scalar_t d1(int var, int node, int j) const; /// Return shape for derivative wrt. variable `var` in `node`. Eigen::Map> d1(int var, int node) const; /// Sets shape for derivative wrt. variable `var` for `node` to `shape`. SINL void setD1(int var, int node, const Eigen::Matrix& shape); /** * Return `j`-th shape coefficient for mixed derivative wrt. variables `varmin` and `varmax` in * `node`. */ SINL scalar_t d2(int varmin, int varmax, int node, int j) const; /// Return shape for mixed derivative wrt. variables `varmin` and `varmax` in `node`. Eigen::Map> d2(int varmin, int varmax, int node) const; /// Sets shape for mixed derivative wrt. variables `varmin` and `varmax` for `node` to `shape`. SINL void setD2(int varmin, int varmax, int node, const Eigen::Matrix& shape); /// Returns the approximate memory used (in bytes). size_t memoryUsed() const; /// Construct explicit operators over this storage. ExplicitOperators explicitOperators() const; /// Construct explicit vector operators over this storage. ExplicitVectorOperators explicitVectorOperators() const; /// Construct implicit operators over this storage. template ImplicitOperators implicitOperators(M& matrix, R& rhs) const; /// Construct implicit vector operators over this storage. template ImplicitVectorOperators implicitVectorOperators(M& matrix, R& rhs) const; /// Output basic info about this shape storage. template friend std::ostream& operator<<(std::ostream& os, const ShapeStorage& shapes); }; } // namespace mm #endif // MEDUSA_BITS_OPERATORS_SHAPESTORAGE_FWD_HPP_