diff --git a/ProcessLib/LocalAssemblerTraits.h b/ProcessLib/LocalAssemblerTraits.h new file mode 100644 index 0000000000000000000000000000000000000000..c2d8dfed11248ed024d3c34ee0b9e62e9e5049f3 --- /dev/null +++ b/ProcessLib/LocalAssemblerTraits.h @@ -0,0 +1,234 @@ +/** + * \copyright + * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + * + */ + +#ifndef PROCESSLIB_LOCALASSEMBLERTRAITS_H +#define PROCESSLIB_LOCALASSEMBLERTRAITS_H + +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 NIntPts the number of integration points 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<typename ShpPol, unsigned NIntPts, unsigned NodalDOF, unsigned Dim> +struct LocalAssemblerTraitsFixed +{ +private: + template<int N, int M> + using Matrix = typename ShpPol::template MatrixType<N, M>; + template<int N> + using Vector = typename ShpPol::template VectorType<N>; + +public: + using ShapeMatrices = typename ShpPol::ShapeMatrices; + + //! Square matrix of the given space dimensionality + using MatrixDimDim = Matrix<Dim, Dim>; + + // TODO That only works if all process variables are single component + // and use the same shape fucntions. + //! Local matrix for the given number of d.o.f.\ per node and number of + //! integration points + using LocalMatrix = Matrix<NIntPts*NodalDOF, NIntPts*NodalDOF>; + //! Local vector for the given number of d.o.f.\ per node and number of + //! integration points + using LocalVector = Vector<NIntPts*NodalDOF>; + + //! Local vector for one component of one process variable. + //! The size is the number of nodes in the element. + using Vector1Comp = typename ShapeMatrices::ShapeType; + + //! Laplace matrix for the given space dimensionality and number of d.o.f + //! per node. + using LaplaceMatrix = Matrix<Dim*NodalDOF, Dim*NodalDOF>; + + + //! Get a block \c Dim x \c Dim whose upper left corner is at \c top and \c left. + template<typename Mat> + static + typename std::enable_if<NodalDOF != 0, + decltype(std::declval<const Mat>().template block<Dim, Dim>(0u, 0u)) + >::type + blockDimDim(Mat const& mat, + unsigned top, unsigned left, unsigned nrows, unsigned ncols) + { + assert(nrows==Dim && ncols==Dim); + (void) nrows; (void) ncols; + return mat.template block<Dim, Dim>(top, left); + } + //! Get a block \c Dim x \c Dim whose upper left corner is at \c top and \c left. + template<typename Mat> + static + typename std::enable_if<NodalDOF == 0, + decltype(std::declval<const Mat>().block(0u, 0u, 0u, 0u)) + >::type + blockDimDim(Mat const& mat, + unsigned top, unsigned left, unsigned nrows, unsigned ncols) + { + 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<typename Mat> + static + typename std::enable_if<NodalDOF != 0, + decltype(std::declval<Mat>().template block<Dim, Dim>(0u, 0u)) + >::type + blockDimDim(Mat& mat, + unsigned top, unsigned left, unsigned nrows, unsigned ncols) + { + assert(nrows==Dim && ncols==Dim); + (void) nrows; (void) ncols; + return mat.template block<Dim, Dim>(top, left); + } + //! Get a block \c Dim x \c Dim whose upper left corner is at \c top and \c left. + template<typename Mat> + static + typename std::enable_if<NodalDOF == 0, + decltype(std::declval<Mat>().block(0u, 0u, 0u, 0u)) + >::type + blockDimDim(Mat& mat, + unsigned top, unsigned left, unsigned nrows, unsigned ncols) + { + assert(nrows == ncols); + return mat.block(top, left, nrows, ncols); + } + + //! Get a block \c NIntPts x \c NIntPts whose upper left corner is at \c top and \c left. + template<typename Mat> + static + typename std::enable_if<NodalDOF != 0, + decltype(std::declval<const Mat>().template block<NIntPts, NIntPts>(0u, 0u)) + >::type + blockShpShp(Mat const& mat, + unsigned top, unsigned left, unsigned nrows, unsigned ncols) + { + assert(nrows==NIntPts && ncols==NIntPts); + (void) nrows; (void) ncols; + return mat.template block<NIntPts, NIntPts>(top, left); + } + //! Get a block \c NIntPts x \c NIntPts whose upper left corner is at \c top and \c left. + template<typename Mat> + static + typename std::enable_if<NodalDOF == 0, + decltype(std::declval<const Mat>().block(0u, 0u, 0u, 0u)) + >::type + blockShpShp(Mat const& mat, + unsigned top, unsigned left, unsigned nrows, unsigned ncols) + { + assert(nrows == ncols); + return mat.block(top, left, nrows, ncols); + } + //! Get a block \c NIntPts x \c NIntPts whose upper left corner is at \c top and \c left. + template<typename Mat> + static + typename std::enable_if<NodalDOF != 0, + decltype(std::declval<Mat>().template block<NIntPts, NIntPts>(0u, 0u)) + >::type + blockShpShp(Mat& mat, + unsigned top, unsigned left, unsigned nrows, unsigned ncols) + { + assert(nrows==NIntPts && ncols==NIntPts); + (void) nrows; (void) ncols; + return mat.template block<NIntPts, NIntPts>(top, left); + } + //! Get a block \c NIntPts x \c NIntPts whose upper left corner is at \c top and \c left. + template<typename Mat> + static + typename std::enable_if<NodalDOF == 0, + decltype(std::declval<Mat>().block(0u, 0u, 0u, 0u)) + >::type + blockShpShp(Mat& mat, + unsigned top, unsigned left, unsigned nrows, unsigned ncols) + { + assert(nrows == ncols); + return mat.block(top, left, nrows, ncols); + } + + //! Get a block \c NIntPts x 1 starting at the \c top'th row. + template<typename Vec> + static + typename std::enable_if<NodalDOF != 0, + decltype(std::declval<const Vec>().template block<NIntPts, 1>(0u, 0u)) + >::type + blockShp(Vec const& vec, unsigned top, unsigned nrows) + { + assert(nrows==NIntPts); + (void) nrows; + return vec.template block<NIntPts, 1>(top, 0); + } + //! Get a block \c NIntPts x 1 starting at the \c top'th row. + template<typename Vec> + static + typename std::enable_if<NodalDOF == 0, + decltype(std::declval<const Vec>().block(0u, 0u, 0u, 0u)) + >::type + blockShp(Vec const& vec, unsigned top, unsigned nrows) + { + return vec.block(top, 0, nrows, 1); + } + //! Get a block \c NIntPts x 1 starting at the \c top'th row. + template<typename Vec> + static + typename std::enable_if<NodalDOF != 0, + decltype(std::declval<Vec>().template block<NIntPts, 1>(0u, 0u)) + >::type + blockShp(Vec& vec, unsigned top, unsigned nrows) + { + assert(nrows==NIntPts); + (void) nrows; + return vec.template block<NIntPts, 1>(top, 0); + } + //! Get a block \c NIntPts x 1 starting at the \c top'th row. + template<typename Vec> + static + typename std::enable_if<NodalDOF == 0, + decltype(std::declval<Vec>().block(0u, 0u, 0u, 0u)) + >::type + blockShp(Vec& vec, unsigned top, unsigned nrows) + { + return vec.block(top, 0, nrows, 1); + } +}; + +} // namespace detail + + +#ifndef EIGEN_DYNAMIC_SHAPE_MATRICES + +template<typename ShpPol, unsigned NIntPts, unsigned NodalDOF, unsigned Dim> +using LocalAssemblerTraits = detail::LocalAssemblerTraitsFixed<ShpPol, NIntPts, NodalDOF, Dim>; + +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<typename ShpPol, unsigned NIntPts, unsigned NodalDOF, unsigned Dim> +using LocalAssemblerTraits = detail::LocalAssemblerTraitsFixed<ShapeMatrixPolicyType<void, 0>, 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 + +} + +#endif // PROCESSLIB_LOCALASSEMBLERTRAITS_H