// Copyright (c) 2010-2023, Lawrence Livermore National Security, LLC. Produced // at the Lawrence Livermore National Laboratory. All Rights reserved. See files // LICENSE and NOTICE for details. LLNL-CODE-806117. // // This file is part of the MFEM library. For more information and source code // availability visit https://mfem.org. // // MFEM is free software; you can redistribute it and/or modify it under the // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. #ifndef MFEM_TEMPLATE_INTEGRATION_RULES #define MFEM_TEMPLATE_INTEGRATION_RULES #include "../config/tconfig.hpp" #include "../linalg/ttensor.hpp" #include "geom.hpp" namespace mfem { // Templated integration rules, cf. intrules.?pp template class GenericIntegrationRule { public: static const Geometry::Type geom = G; static const int dim = Geometry::Constants::Dimension; static const int qpts = Q; static const int order = Order; static const bool tensor_prod = false; typedef real_t real_type; protected: TVector weights; public: GenericIntegrationRule() { const IntegrationRule &ir = GetIntRule(); MFEM_ASSERT(ir.GetNPoints() == qpts, "quadrature rule mismatch"); for (int j = 0; j < qpts; j++) { weights[j] = ir.IntPoint(j).weight; } } // Default copy constructor static const IntegrationRule &GetIntRule() { return IntRules.Get(geom, order); } // Multi-component weight assignment. qpt_layout_t must be (qpts x n1 x ...) template void AssignWeights(const qpt_layout_t &qpt_layout, qpt_data_t &qpt_data) const { MFEM_STATIC_ASSERT(qpt_layout_t::rank > 1, "invalid rank"); MFEM_STATIC_ASSERT(qpt_layout_t::dim_1 == qpts, "invalid size"); for (int j = 0; j < qpts; j++) { TAssign(qpt_layout.ind1(j), qpt_data, weights.data[j]); } } template void ApplyWeights(qpt_data_t &qpt_data) const { AssignWeights(ColumnMajorLayout2D(), qpt_data); } }; template class TProductIntegrationRule_base; template class TProductIntegrationRule_base<1,Q,real_t> { protected: TVector weights_1d; public: // Multi-component weight assignment. qpt_layout_t must be (qpts x n1 x ...) template void AssignWeights(const qpt_layout_t &qpt_layout, qpt_data_t &qpt_data) const { MFEM_STATIC_ASSERT(qpt_layout_t::rank > 1, "invalid rank"); MFEM_STATIC_ASSERT(qpt_layout_t::dim_1 == Q, "invalid size"); for (int j = 0; j < Q; j++) { TAssign(qpt_layout.ind1(j), qpt_data, weights_1d.data[j]); } } template void ApplyWeights(qpt_data_t &qpt_data) const { AssignWeights(ColumnMajorLayout2D(), qpt_data); } }; template class TProductIntegrationRule_base<2,Q,real_t> { protected: TVector weights_1d; public: // Multi-component weight assignment. qpt_layout_t must be (qpts x n1 x ...) template void AssignWeights(const qpt_layout_t &qpt_layout, qpt_data_t &qpt_data) const { MFEM_STATIC_ASSERT(qpt_layout_t::rank > 1, "invalid rank"); MFEM_STATIC_ASSERT(qpt_layout_t::dim_1 == Q*Q, "invalid size"); MFEM_FLOPS_ADD(Q*Q); for (int j2 = 0; j2 < Q; j2++) { for (int j1 = 0; j1 < Q; j1++) { TAssign( qpt_layout.ind1(TMatrix::layout.ind(j1,j2)), qpt_data, weights_1d.data[j1]*weights_1d.data[j2]); } } } template void ApplyWeights(qpt_data_t &qpt_data) const { AssignWeights(ColumnMajorLayout2D(), qpt_data); } }; template class TProductIntegrationRule_base<3,Q,real_t> { protected: TVector weights_1d; public: // Multi-component weight assignment. qpt_layout_t must be (qpts x n1 x ...) template void AssignWeights(const qpt_layout_t &qpt_layout, qpt_data_t &qpt_data) const { MFEM_STATIC_ASSERT(qpt_layout_t::rank > 1, "invalid rank"); MFEM_STATIC_ASSERT(qpt_layout_t::dim_1 == Q*Q*Q, "invalid size"); MFEM_FLOPS_ADD(2*Q*Q*Q); for (int j3 = 0; j3 < Q; j3++) { for (int j2 = 0; j2 < Q; j2++) { for (int j1 = 0; j1 < Q; j1++) { TAssign( qpt_layout.ind1(TTensor3::layout.ind(j1,j2,j3)), qpt_data, weights_1d.data[j1]*weights_1d.data[j2]*weights_1d.data[j3]); } } } } template void ApplyWeights(qpt_data_t &qpt_data) const { AssignWeights(ColumnMajorLayout2D(), qpt_data); } }; template class TProductIntegrationRule : public TProductIntegrationRule_base { public: static const Geometry::Type geom = ((Dim == 1) ? Geometry::SEGMENT : ((Dim == 2) ? Geometry::SQUARE : Geometry::CUBE)); static const int dim = Dim; static const int qpts_1d = Q; static const int qpts = (Dim == 1) ? Q : ((Dim == 2) ? (Q*Q) : (Q*Q*Q)); static const int order = Order; static const bool tensor_prod = true; typedef real_t real_type; protected: using TProductIntegrationRule_base::weights_1d; public: // default constructor, default copy constructor }; template class GaussIntegrationRule : public TProductIntegrationRule { public: typedef TProductIntegrationRule base_class; using base_class::geom; using base_class::order; using base_class::qpts_1d; protected: using base_class::weights_1d; public: GaussIntegrationRule() { const IntegrationRule &ir_1d = Get1DIntRule(); MFEM_ASSERT(ir_1d.GetNPoints() == qpts_1d, "quadrature rule mismatch"); for (int j = 0; j < qpts_1d; j++) { weights_1d.data[j] = ir_1d.IntPoint(j).weight; } } static const IntegrationRule &Get1DIntRule() { return IntRules.Get(Geometry::SEGMENT, order); } static const IntegrationRule &GetIntRule() { return IntRules.Get(geom, order); } }; template class TIntegrationRule; template class TIntegrationRule : public GaussIntegrationRule<1, Order/2+1, real_t> { }; template class TIntegrationRule : public GaussIntegrationRule<2, Order/2+1, real_t> { }; template class TIntegrationRule : public GaussIntegrationRule<3, Order/2+1, real_t> { }; // Triangle integration rules (based on intrules.cpp) // These specializations define the number of quadrature points for each rule as // a compile-time constant. // TODO: add higher order rules template class TIntegrationRule : public GenericIntegrationRule { }; template class TIntegrationRule : public GenericIntegrationRule { }; template class TIntegrationRule : public GenericIntegrationRule { }; template class TIntegrationRule : public GenericIntegrationRule { }; template class TIntegrationRule : public GenericIntegrationRule { }; template class TIntegrationRule : public GenericIntegrationRule { }; template class TIntegrationRule : public GenericIntegrationRule { }; template class TIntegrationRule : public GenericIntegrationRule { }; // Tetrahedron integration rules (based on intrules.cpp) // These specializations define the number of quadrature points for each rule as // a compile-time constant. // TODO: add higher order rules template class TIntegrationRule : public GenericIntegrationRule { }; template class TIntegrationRule : public GenericIntegrationRule { }; template class TIntegrationRule : public GenericIntegrationRule { }; template class TIntegrationRule : public GenericIntegrationRule { }; template class TIntegrationRule : public GenericIntegrationRule { }; template class TIntegrationRule : public GenericIntegrationRule { }; template class TIntegrationRule : public GenericIntegrationRule { }; template class TIntegrationRule : public GenericIntegrationRule { }; } // namespace mfem #endif // MFEM_TEMPLATE_INTEGRATION_RULES