13 template <mfem::Geometry::Type g>
14 struct finite_element<g, QOI> {
15 static constexpr
auto geometry = g;
16 static constexpr
auto family = Family::QOI;
17 static constexpr
int components = 1;
18 static constexpr
int dim = 1;
19 static constexpr
int ndof = 1;
21 using dof_type = double;
22 using dof_type_if = double;
23 using residual_type = double;
25 SMITH_HOST_DEVICE static constexpr
double shape_functions(
double ) {
return 1.0; }
27 template <
int Q,
int q>
28 SMITH_HOST_DEVICE static void integrate(
const tensor<zero, Q>&,
const TensorProductQuadratureRule<q>&, dof_type*,
29 [[maybe_unused]]
int step = 1)
34 template <
int Q,
int q>
35 SMITH_HOST_DEVICE static void integrate(
const tensor<double, Q>& qf_output,
const TensorProductQuadratureRule<q>&,
36 dof_type* element_total, [[maybe_unused]]
int step = 1)
38 if constexpr (geometry == mfem::Geometry::SEGMENT) {
39 static_assert(Q == q);
40 static constexpr
auto wts = GaussLegendreWeights<q, mfem::Geometry::SEGMENT>();
41 for (
int k = 0; k < q; k++) {
42 element_total[0] += qf_output[k] * wts[k];
46 if constexpr (geometry == mfem::Geometry::SQUARE) {
47 static_assert(Q == q * q);
48 static constexpr
auto wts = GaussLegendreWeights<q, mfem::Geometry::SEGMENT>();
49 for (
int qy = 0; qy < q; qy++) {
50 for (
int qx = 0; qx < q; qx++) {
52 element_total[0] += qf_output[k] * wts[qx] * wts[qy];
57 if constexpr (geometry == mfem::Geometry::CUBE) {
58 static_assert(Q == q * q * q);
59 static constexpr
auto wts = GaussLegendreWeights<q, mfem::Geometry::SEGMENT>();
60 for (
int qz = 0; qz < q; qz++) {
61 for (
int qy = 0; qy < q; qy++) {
62 for (
int qx = 0; qx < q; qx++) {
63 int k = (qz * q + qy) * q + qx;
64 element_total[0] += qf_output[k] * wts[qx] * wts[qy] * wts[qz];
70 if constexpr (geometry == mfem::Geometry::TRIANGLE || geometry == mfem::Geometry::TETRAHEDRON) {
71 static constexpr
auto wts = GaussLegendreWeights<q, geometry>();
73 element_total[0] += qf_output[k] * wts[k];
80 template <
typename source_type,
int Q,
int q>
82 const TensorProductQuadratureRule<q>&, dof_type* element_total,
83 [[maybe_unused]]
int step = 1)
85 if constexpr (is_zero<source_type>{}) {
89 constexpr
int ntrial =
size(source_type{});
91 for (
int j = 0; j < ntrial; j++) {
92 if constexpr (geometry == mfem::Geometry::SEGMENT) {
93 static_assert(Q == q);
94 static constexpr
auto wts = GaussLegendreWeights<q, mfem::Geometry::SEGMENT>();
95 for (
int k = 0; k < q; k++) {
96 element_total[j * step] +=
reinterpret_cast<const double*
>(&get<0>(qf_output[k]))[j] * wts[k];
100 if constexpr (geometry == mfem::Geometry::SQUARE) {
101 static_assert(Q == q * q);
102 static constexpr
auto wts = GaussLegendreWeights<q, mfem::Geometry::SEGMENT>();
103 for (
int qy = 0; qy < q; qy++) {
104 for (
int qx = 0; qx < q; qx++) {
106 element_total[j * step] +=
reinterpret_cast<const double*
>(&get<0>(qf_output[k]))[j] * wts[qx] * wts[qy];
111 if constexpr (geometry == mfem::Geometry::CUBE) {
112 static_assert(Q == q * q * q);
113 static constexpr
auto wts = GaussLegendreWeights<q, mfem::Geometry::SEGMENT>();
114 for (
int qz = 0; qz < q; qz++) {
115 for (
int qy = 0; qy < q; qy++) {
116 for (
int qx = 0; qx < q; qx++) {
117 int k = (qz * q + qy) * q + qx;
118 element_total[j * step] +=
119 reinterpret_cast<const double*
>(&get<0>(qf_output[k]))[j] * wts[qx] * wts[qy] * wts[qz];
125 if constexpr (geometry == mfem::Geometry::TRIANGLE || geometry == mfem::Geometry::TETRAHEDRON) {
126 static constexpr
auto wts = GaussLegendreWeights<q, geometry>();
128 element_total[j * step] +=
reinterpret_cast<const double*
>(&get<0>(qf_output[k]))[j] * wts[k];
#define SMITH_HOST_DEVICE
Macro that evaluates to __host__ __device__ when compiling with nvcc and does nothing on a host compi...
constexpr SMITH_HOST_DEVICE int leading_dimension(tensor< T, m, n... >)
a function for querying the first dimension of a tensor
constexpr SMITH_HOST_DEVICE int size(const tensor< T, n... > &)
returns the total number of stored values in a tensor
tensor(const T(&data)[n1]) -> tensor< T, n1 >
class template argument deduction guide for type tensor.
This is a class that mimics most of std::tuple's interface, except that it is usable in CUDA kernels ...