Smith  0.1
Smith is an implicit thermal structural mechanics simulation code.
qoi.inl
Go to the documentation of this file.
1 // Copyright (c) Lawrence Livermore National Security, LLC and
2 // other Smith Project Developers. See the top-level LICENSE file for
3 // details.
4 //
5 // SPDX-License-Identifier: (BSD-3-Clause)
6 
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;
20 
21  using dof_type = double;
22  using dof_type_if = double;
23  using residual_type = double;
24 
25  SMITH_HOST_DEVICE static constexpr double shape_functions(double /* xi */) { return 1.0; }
26 
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)
30  {
31  return; // integrating zeros is a no-op
32  }
33 
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)
37  {
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];
43  }
44  }
45 
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++) {
51  int k = qy * q + qx;
52  element_total[0] += qf_output[k] * wts[qx] * wts[qy];
53  }
54  }
55  }
56 
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];
65  }
66  }
67  }
68  }
69 
70  if constexpr (geometry == mfem::Geometry::TRIANGLE || geometry == mfem::Geometry::TETRAHEDRON) {
71  static constexpr auto wts = GaussLegendreWeights<q, geometry>();
72  for (int k = 0; k < leading_dimension(wts); k++) {
73  element_total[0] += qf_output[k] * wts[k];
74  }
75  }
76  }
77 
78  // this overload is used for boundary integrals, since they pad the
79  // output to be a tuple with a hardcoded `zero` flux term
80  template <typename source_type, int Q, int q>
81  SMITH_HOST_DEVICE static void integrate(const tensor<smith::tuple<source_type, zero>, Q>& qf_output,
82  const TensorProductQuadratureRule<q>&, dof_type* element_total,
83  [[maybe_unused]] int step = 1)
84  {
85  if constexpr (is_zero<source_type>{}) {
86  return;
87  }
88 
89  constexpr int ntrial = size(source_type{});
90 
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];
97  }
98  }
99 
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++) {
105  int k = qy * q + qx;
106  element_total[j * step] += reinterpret_cast<const double*>(&get<0>(qf_output[k]))[j] * wts[qx] * wts[qy];
107  }
108  }
109  }
110 
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];
120  }
121  }
122  }
123  }
124 
125  if constexpr (geometry == mfem::Geometry::TRIANGLE || geometry == mfem::Geometry::TETRAHEDRON) {
126  static constexpr auto wts = GaussLegendreWeights<q, geometry>();
127  for (int k = 0; k < leading_dimension(wts); k++) {
128  element_total[j * step] += reinterpret_cast<const double*>(&get<0>(qf_output[k]))[j] * wts[k];
129  }
130  }
131  }
132  }
133 };
#define SMITH_HOST_DEVICE
Macro that evaluates to __host__ __device__ when compiling with nvcc or amdclang and does nothing on ...
Definition: accelerator.hpp:37
constexpr SMITH_HOST_DEVICE int leading_dimension(tensor< T, m, n... >)
a function for querying the first dimension of a tensor
Definition: tensor.hpp:1977
constexpr SMITH_HOST_DEVICE int size(const tensor< T, n... > &)
returns the total number of stored values in a tensor
Definition: tensor.hpp:1939
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 ...
Definition: tuple.hpp:28