313 lines
10 KiB
C++
313 lines
10 KiB
C++
// Copyright (c) 2010-2020, 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 <Geometry::Type G, int Q, int Order, typename real_t>
|
|
class GenericIntegrationRule
|
|
{
|
|
public:
|
|
static const Geometry::Type geom = G;
|
|
static const int dim = Geometry::Constants<geom>::Dimension;
|
|
static const int qpts = Q;
|
|
static const int order = Order;
|
|
|
|
static const bool tensor_prod = false;
|
|
|
|
typedef real_t real_type;
|
|
|
|
protected:
|
|
TVector<qpts,real_t> 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 <AssignOp::Type Op, typename qpt_layout_t, typename qpt_data_t>
|
|
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<Op>(qpt_layout.ind1(j), qpt_data, weights.data[j]);
|
|
}
|
|
}
|
|
|
|
template <typename qpt_data_t>
|
|
void ApplyWeights(qpt_data_t &qpt_data) const
|
|
{
|
|
AssignWeights<AssignOp::Mult>(ColumnMajorLayout2D<qpts,1>(), qpt_data);
|
|
}
|
|
};
|
|
|
|
template <int Dim, int Q, typename real_t>
|
|
class TProductIntegrationRule_base;
|
|
|
|
template <int Q, typename real_t>
|
|
class TProductIntegrationRule_base<1,Q,real_t>
|
|
{
|
|
protected:
|
|
TVector<Q,real_t> weights_1d;
|
|
|
|
public:
|
|
// Multi-component weight assignment. qpt_layout_t must be (qpts x n1 x ...)
|
|
template <AssignOp::Type Op, typename qpt_layout_t, typename qpt_data_t>
|
|
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<Op>(qpt_layout.ind1(j), qpt_data, weights_1d.data[j]);
|
|
}
|
|
}
|
|
|
|
template <typename qpt_data_t>
|
|
void ApplyWeights(qpt_data_t &qpt_data) const
|
|
{
|
|
AssignWeights<AssignOp::Mult>(ColumnMajorLayout2D<Q,1>(), qpt_data);
|
|
}
|
|
};
|
|
|
|
template <int Q, typename real_t>
|
|
class TProductIntegrationRule_base<2,Q,real_t>
|
|
{
|
|
protected:
|
|
TVector<Q,real_t> weights_1d;
|
|
|
|
public:
|
|
// Multi-component weight assignment. qpt_layout_t must be (qpts x n1 x ...)
|
|
template <AssignOp::Type Op, typename qpt_layout_t, typename qpt_data_t>
|
|
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<Op>(
|
|
qpt_layout.ind1(TMatrix<Q,Q>::layout.ind(j1,j2)), qpt_data,
|
|
weights_1d.data[j1]*weights_1d.data[j2]);
|
|
}
|
|
}
|
|
}
|
|
|
|
template <typename qpt_data_t>
|
|
void ApplyWeights(qpt_data_t &qpt_data) const
|
|
{
|
|
AssignWeights<AssignOp::Mult>(ColumnMajorLayout2D<Q*Q,1>(), qpt_data);
|
|
}
|
|
};
|
|
|
|
template <int Q, typename real_t>
|
|
class TProductIntegrationRule_base<3,Q,real_t>
|
|
{
|
|
protected:
|
|
TVector<Q,real_t> weights_1d;
|
|
|
|
public:
|
|
// Multi-component weight assignment. qpt_layout_t must be (qpts x n1 x ...)
|
|
template <AssignOp::Type Op, typename qpt_layout_t, typename qpt_data_t>
|
|
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<Op>(
|
|
qpt_layout.ind1(TTensor3<Q,Q,Q>::layout.ind(j1,j2,j3)),
|
|
qpt_data,
|
|
weights_1d.data[j1]*weights_1d.data[j2]*weights_1d.data[j3]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
template <typename qpt_data_t>
|
|
void ApplyWeights(qpt_data_t &qpt_data) const
|
|
{
|
|
AssignWeights<AssignOp::Mult>(ColumnMajorLayout2D<Q*Q*Q,1>(), qpt_data);
|
|
}
|
|
};
|
|
|
|
template <int Dim, int Q, int Order, typename real_t>
|
|
class TProductIntegrationRule
|
|
: public TProductIntegrationRule_base<Dim,Q,real_t>
|
|
{
|
|
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<Dim,Q,real_t>::weights_1d;
|
|
|
|
public:
|
|
// default constructor, default copy constructor
|
|
};
|
|
|
|
template <int Dim, int Q, typename real_t>
|
|
class GaussIntegrationRule
|
|
: public TProductIntegrationRule<Dim, Q, 2*Q-1, real_t>
|
|
{
|
|
public:
|
|
typedef TProductIntegrationRule<Dim,Q,2*Q-1,real_t> 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 <Geometry::Type G, int Order, typename real_t = double>
|
|
class TIntegrationRule;
|
|
|
|
template <int Order, typename real_t>
|
|
class TIntegrationRule<Geometry::SEGMENT, Order, real_t>
|
|
: public GaussIntegrationRule<1, Order/2+1, real_t> { };
|
|
|
|
template <int Order, typename real_t>
|
|
class TIntegrationRule<Geometry::SQUARE, Order, real_t>
|
|
: public GaussIntegrationRule<2, Order/2+1, real_t> { };
|
|
|
|
template <int Order, typename real_t>
|
|
class TIntegrationRule<Geometry::CUBE, Order, real_t>
|
|
: 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 <typename real_t>
|
|
class TIntegrationRule<Geometry::TRIANGLE, 0, real_t>
|
|
: public GenericIntegrationRule<Geometry::TRIANGLE, 1, 0, real_t> { };
|
|
template <typename real_t>
|
|
class TIntegrationRule<Geometry::TRIANGLE, 1, real_t>
|
|
: public GenericIntegrationRule<Geometry::TRIANGLE, 1, 1, real_t> { };
|
|
template <typename real_t>
|
|
class TIntegrationRule<Geometry::TRIANGLE, 2, real_t>
|
|
: public GenericIntegrationRule<Geometry::TRIANGLE, 3, 2, real_t> { };
|
|
template <typename real_t>
|
|
class TIntegrationRule<Geometry::TRIANGLE, 3, real_t>
|
|
: public GenericIntegrationRule<Geometry::TRIANGLE, 4, 3, real_t> { };
|
|
template <typename real_t>
|
|
class TIntegrationRule<Geometry::TRIANGLE, 4, real_t>
|
|
: public GenericIntegrationRule<Geometry::TRIANGLE, 6, 4, real_t> { };
|
|
template <typename real_t>
|
|
class TIntegrationRule<Geometry::TRIANGLE, 5, real_t>
|
|
: public GenericIntegrationRule<Geometry::TRIANGLE, 7, 5, real_t> { };
|
|
template <typename real_t>
|
|
class TIntegrationRule<Geometry::TRIANGLE, 6, real_t>
|
|
: public GenericIntegrationRule<Geometry::TRIANGLE, 12, 6, real_t> { };
|
|
template <typename real_t>
|
|
class TIntegrationRule<Geometry::TRIANGLE, 7, real_t>
|
|
: public GenericIntegrationRule<Geometry::TRIANGLE, 12, 7, real_t> { };
|
|
|
|
// 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 <typename real_t>
|
|
class TIntegrationRule<Geometry::TETRAHEDRON, 0, real_t>
|
|
: public GenericIntegrationRule<Geometry::TETRAHEDRON, 1, 0, real_t> { };
|
|
template <typename real_t>
|
|
class TIntegrationRule<Geometry::TETRAHEDRON, 1, real_t>
|
|
: public GenericIntegrationRule<Geometry::TETRAHEDRON, 1, 1, real_t> { };
|
|
template <typename real_t>
|
|
class TIntegrationRule<Geometry::TETRAHEDRON, 2, real_t>
|
|
: public GenericIntegrationRule<Geometry::TETRAHEDRON, 4, 2, real_t> { };
|
|
template <typename real_t>
|
|
class TIntegrationRule<Geometry::TETRAHEDRON, 3, real_t>
|
|
: public GenericIntegrationRule<Geometry::TETRAHEDRON, 5, 3, real_t> { };
|
|
template <typename real_t>
|
|
class TIntegrationRule<Geometry::TETRAHEDRON, 4, real_t>
|
|
: public GenericIntegrationRule<Geometry::TETRAHEDRON, 11, 4, real_t> { };
|
|
template <typename real_t>
|
|
class TIntegrationRule<Geometry::TETRAHEDRON, 5, real_t>
|
|
: public GenericIntegrationRule<Geometry::TETRAHEDRON, 14, 5, real_t> { };
|
|
template <typename real_t>
|
|
class TIntegrationRule<Geometry::TETRAHEDRON, 6, real_t>
|
|
: public GenericIntegrationRule<Geometry::TETRAHEDRON, 24, 6, real_t> { };
|
|
template <typename real_t>
|
|
class TIntegrationRule<Geometry::TETRAHEDRON, 7, real_t>
|
|
: public GenericIntegrationRule<Geometry::TETRAHEDRON, 31, 7, real_t> { };
|
|
|
|
} // namespace mfem
|
|
|
|
#endif // MFEM_TEMPLATE_INTEGRATION_RULES
|