/** * \file * \copyright * Copyright (c) 2012-2022, OpenGeoSys Community (http://www.opengeosys.org) * Distributed under a Modified BSD License. * See accompanying file LICENSE.txt or * http://www.opengeosys.org/project/license * */ #pragma once #include "NumLib/Fem/ShapeMatrixPolicy.h" #include #include namespace ProcessLib { namespace detail { /*! This class makes it possible to handle Eigen's block expressions transparently, * both for fixed-size and dynamically allocated Eigen matrices. * * \tparam ShpPol the shape matrix policy used * \tparam NNodes the number of nodes for the FEM element * \tparam NodalDOF the number of d.o.f. per node. * If zero, this struct's methods will determine the size of * the generated Eigen::block's at runtime. If non-zero, the * size will be determined at compile-time. * \tparam Dim global spatial dimension */ template struct LocalAssemblerTraitsFixed { private: template using Matrix = typename ShpPol::template MatrixType; template using Vector = typename ShpPol::template VectorType; public: using ShapeMatrices = typename ShpPol::ShapeMatrices; //! Square matrix of the given space dimensionality using MatrixDimDim = Matrix; // TODO That only works if all process variables are single component // and use the same shape functions. //! Local matrix for the given number of d.o.f.\ per node and number of //! integration points using LocalMatrix = Matrix; //! Local vector for the given number of d.o.f.\ per node and number of //! integration points using LocalVector = Vector; //! Local vector for one component of one process variable. //! The size is the number of nodes in the element. using Vector1Comp = Vector; //! Laplace matrix for the given space dimensionality and number of d.o.f //! per node. using LaplaceMatrix = Matrix; //! Get a block \c Dim x \c Dim whose upper left corner is at \c top and \c //! left. template static auto blockDimDim(Mat const& mat, unsigned top, unsigned left, unsigned nrows, unsigned ncols) { if constexpr (NodalDOF != 0) { assert(nrows == Dim && ncols == Dim); (void)nrows; (void)ncols; return mat.template block(top, left); } else { assert(nrows == ncols); return mat.block(top, left, nrows, ncols); } } //! Get a block \c Dim x \c Dim whose upper left corner is at \c top and \c //! left. template static auto blockDimDim(Mat& mat, unsigned top, unsigned left, unsigned nrows, unsigned ncols) { if constexpr (NodalDOF != 0) { assert(nrows == Dim && ncols == Dim); (void)nrows; (void)ncols; return mat.template block(top, left); } else { assert(nrows == ncols); return mat.block(top, left, nrows, ncols); } } //! Get a block \c NNodes x \c NNodes whose upper left corner is at \c top //! and \c left. template static auto blockShpShp(Mat const& mat, unsigned top, unsigned left, unsigned nrows, unsigned ncols) { if constexpr (NodalDOF != 0) { assert(nrows == NNodes && ncols == NNodes); (void)nrows; (void)ncols; return mat.template block(top, left); } else { assert(nrows == ncols); return mat.block(top, left, nrows, ncols); } } //! Get a block \c NNodes x \c NNodes whose upper left corner is at \c top //! and \c left. template static auto blockShpShp(Mat& mat, unsigned top, unsigned left, unsigned nrows, unsigned ncols) { if constexpr (NodalDOF != 0) { assert(nrows == NNodes && ncols == NNodes); (void)nrows; (void)ncols; return mat.template block(top, left); } else { assert(nrows == ncols); return mat.block(top, left, nrows, ncols); } } //! Get a block \c NNodes x 1 starting at the \c top'th row. template static auto blockShp(Vec const& vec, unsigned top, unsigned nrows) { if constexpr (NodalDOF != 0) { assert(nrows == NNodes); (void)nrows; return vec.template block(top, 0); } else { return vec.block(top, 0, nrows, 1); } } //! Get a block \c NNodes x 1 starting at the \c top'th row. template static auto blockShp(Vec& vec, unsigned top, unsigned nrows) { if constexpr (NodalDOF != 0) { assert(nrows == NNodes); (void)nrows; return vec.template block(top, 0); } else { return vec.block(top, 0, nrows, 1); } } }; } // namespace detail #ifndef OGS_EIGEN_DYNAMIC_SHAPE_MATRICES template using LocalAssemblerTraits = detail::LocalAssemblerTraitsFixed; static_assert(OGS_EIGEN_DYNAMIC_SHAPE_MATRICES_FLAG == 0, "Inconsistent use of the macro OGS_EIGEN_DYNAMIC_SHAPE_MATRICES." " Maybe you forgot to include some header file."); #else template using LocalAssemblerTraits = detail::LocalAssemblerTraitsFixed, 0, 0, 0>; static_assert(OGS_EIGEN_DYNAMIC_SHAPE_MATRICES_FLAG == 1, "Inconsistent use of the macro OGS_EIGEN_DYNAMIC_SHAPE_MATRICES." " Maybe you forgot to include some header file."); #endif } // namespace ProcessLib