Serac  0.1
Serac is an implicit thermal strucural mechanics simulation code.
finite_element.hpp
Go to the documentation of this file.
1 // Copyright (c) 2019-2024, Lawrence Livermore National Security, LLC and
2 // other Serac Project Developers. See the top-level LICENSE file for
3 // details.
4 //
5 // SPDX-License-Identifier: (BSD-3-Clause)
6 
13 #pragma once
14 
15 #include "tuple.hpp"
16 #include "tensor.hpp"
17 #include "geometry.hpp"
18 #include "polynomials.hpp"
19 
20 namespace serac {
21 
28 template <int q>
32 
34  SERAC_HOST_DEVICE double weight(int ix, int iy) const { return weights1D[ix] * weights1D[iy]; }
35 
37  SERAC_HOST_DEVICE double weight(int ix, int iy, int iz) const
38  {
39  return weights1D[ix] * weights1D[iy] * weights1D[iz];
40  }
41 };
42 
43 template <auto val>
45 };
46 
54 template <mfem::Geometry::Type g, int q>
56 
58 template <int q>
59 struct batched_jacobian<mfem::Geometry::CUBE, q> {
62 };
63 
65 template <int q>
66 struct batched_jacobian<mfem::Geometry::SQUARE, q> {
69 };
70 
72 template <int q>
73 struct batched_jacobian<mfem::Geometry::TRIANGLE, q> {
75  using type = tensor<double, 2, 2, q*(q + 1) / 2>;
76 };
77 
79 template <int q>
80 struct batched_jacobian<mfem::Geometry::TETRAHEDRON, q> {
82  using type = tensor<double, 3, 3, (q * (q + 1) * (q + 2)) / 6>;
83 };
84 
92 template <mfem::Geometry::Type g, int q>
94 
96 template <int q>
97 struct batched_position<mfem::Geometry::CUBE, q> {
100 };
101 
103 template <int q>
104 struct batched_position<mfem::Geometry::SQUARE, q> {
107 };
108 
110 template <int q>
111 struct batched_position<mfem::Geometry::TRIANGLE, q> {
113  using type = tensor<double, 2, q*(q + 1) / 2>;
114 };
115 
117 template <int q>
118 struct batched_position<mfem::Geometry::TETRAHEDRON, q> {
120  using type = tensor<double, 3, (q * (q + 1) * (q + 2)) / 6>;
121 };
122 
124 template <int q>
125 struct batched_position<mfem::Geometry::SEGMENT, q> {
128 };
129 
140 template <mfem::Geometry::Type g>
142 {
143  if (g == mfem::Geometry::CUBE) {
144  switch (q) {
145  case 1:
146  return 64;
147  case 2:
148  return 16;
149  case 3:
150  return 4;
151  default:
152  return 1;
153  }
154  }
155 
156  if (g == mfem::Geometry::SQUARE) {
157  switch (q) {
158  case 1:
159  return 128;
160  case 2:
161  return 32;
162  case 3:
163  return 16;
164  case 4:
165  return 8;
166  default:
167  return 1;
168  }
169  }
170 }
171 
181 enum class Family
182 {
183  QOI,
184  H1,
185  HCURL,
186  HDIV,
187  L2
188 };
189 
195 template <int p, int c = 1>
196 struct H1 {
197  static constexpr int order = p;
198  static constexpr int components = c;
199  static constexpr Family family = Family::H1;
200 };
201 
207 template <int p, int c = 1>
208 struct Hcurl {
209  static constexpr int order = p;
210  static constexpr int components = c;
211  static constexpr Family family = Family::HCURL;
212 };
213 
219 template <int p, int c = 1>
220 struct L2 {
221  static constexpr int order = p;
222  static constexpr int components = c;
223  static constexpr Family family = Family::L2;
224 };
225 
229 struct QOI {
230  static constexpr int order = 0;
231  static constexpr int components = 1;
232  static constexpr Family family = Family::QOI;
233 };
234 
246 template <Family f, typename T, int q, int dim>
248 {
249  [[maybe_unused]] constexpr int VALUE = 0;
250  [[maybe_unused]] constexpr int DERIVATIVE = 1;
251 
252  for (int k = 0; k < q; k++) {
254  for (int row = 0; row < dim; row++) {
255  for (int col = 0; col < dim; col++) {
256  J[row][col] = jacobians(col, row, k);
257  }
258  }
259 
260  if constexpr (f == Family::H1 || f == Family::L2) {
261  // note: no transformation necessary for the values of H1-field
262  get<DERIVATIVE>(qf_input[k]) = dot(get<DERIVATIVE>(qf_input[k]), inv(J));
263  }
264 
265  if constexpr (f == Family::HCURL) {
266  get<VALUE>(qf_input[k]) = dot(get<VALUE>(qf_input[k]), inv(J));
267  get<DERIVATIVE>(qf_input[k]) = get<DERIVATIVE>(qf_input[k]) / det(J);
268  if constexpr (dim == 3) {
269  get<DERIVATIVE>(qf_input[k]) = dot(get<DERIVATIVE>(qf_input[k]), transpose(J));
270  }
271  }
272  }
273 }
274 
287 template <Family f, typename T, int q, int dim>
289 {
290  [[maybe_unused]] constexpr int SOURCE = 0;
291  [[maybe_unused]] constexpr int FLUX = 1;
292 
293  for (int k = 0; k < q; k++) {
295  for (int row = 0; row < dim; row++) {
296  for (int col = 0; col < dim; col++) {
297  J_T[row][col] = jacobians(row, col, k);
298  }
299  }
300 
301  auto dv = det(J_T);
302 
303  if constexpr (f == Family::H1 || f == Family::L2) {
304  get<SOURCE>(qf_output[k]) = get<SOURCE>(qf_output[k]) * dv;
305  get<FLUX>(qf_output[k]) = dot(get<FLUX>(qf_output[k]), inv(J_T)) * dv;
306  }
307 
308  // note: the flux term here is usually divided by detJ, but
309  // physical_to_parent also multiplies every quadrature-point value by det(J)
310  // so that part cancels out
311  if constexpr (f == Family::HCURL) {
312  get<SOURCE>(qf_output[k]) = dot(get<SOURCE>(qf_output[k]), inv(J_T)) * dv;
313  if constexpr (dim == 3) {
314  get<FLUX>(qf_output[k]) = dot(get<FLUX>(qf_output[k]), transpose(J_T));
315  }
316  }
317 
318  if constexpr (f == Family::QOI) {
319  qf_output[k] = qf_output[k] * dv;
320  }
321  }
322 }
323 
349 template <mfem::Geometry::Type g, typename family>
351 
352 #include "detail/segment_H1.inl"
353 #include "detail/segment_Hcurl.inl"
354 #include "detail/segment_L2.inl"
355 
356 #include "detail/triangle_H1.inl"
357 #include "detail/triangle_L2.inl"
358 
362 
363 #include "detail/tetrahedron_H1.inl"
364 #include "detail/tetrahedron_L2.inl"
365 
366 #include "detail/hexahedron_H1.inl"
368 #include "detail/hexahedron_L2.inl"
369 
370 #include "detail/qoi.inl"
371 
372 } // namespace serac
#define SERAC_HOST_DEVICE
Macro that evaluates to __host__ __device__ when compiling with nvcc and does nothing on a host compi...
Definition: accelerator.hpp:38
Specialization of finite_element for H1 on hexahedron geometry.
Specialization of finite_element for Hcurl on hexahedron geometry.
Specialization of finite_element for L2 on hexahedron geometry.
Accelerator functionality.
Definition: serac.cpp:38
constexpr SERAC_HOST_DEVICE auto dot(const isotropic_tensor< S, m, m > &I, const tensor< T, m, n... > &A)
dot product between an isotropic and (nonisotropic) tensor
constexpr SERAC_HOST_DEVICE int elements_per_block(int q)
this function returns information about how many elements should be processed by a single thread bloc...
SERAC_HOST_DEVICE void physical_to_parent(tensor< T, q > &qf_output, const tensor< double, dim, dim, q > &jacobians)
transform information in the physical space (i.e. sources and fluxes w.r.t {x, y, z}) back to the par...
constexpr SERAC_HOST_DEVICE auto det(const isotropic_tensor< T, m, m > &I)
compute the determinant of an isotropic tensor
constexpr SERAC_HOST_DEVICE auto inv(const isotropic_tensor< T, m, m > &I)
return the inverse of an isotropic tensor
constexpr SERAC_HOST_DEVICE auto transpose(const isotropic_tensor< T, m, m > &I)
return the transpose of an isotropic tensor
Family
Element conformity.
SERAC_HOST_DEVICE void parent_to_physical(tensor< T, q > &qf_input, const tensor< double, dim, dim, q > &jacobians)
transform information in the parent space (i.e. values and derivatives w.r.t {xi, eta,...
Definitions of 1D quadrature weights and node locations and polynomial basis functions.
Specialization of finite_element for expressing quantities of interest on any geometry.
Specialization of finite_element for H1 on quadrilateral geometry.
Specialization of finite_element for Hcurl on quadrilateral geometry.
Specialization of finite_element for L2 on quadrilateral geometry.
Specialization of finite_element for H1 on segment geometry.
Specialization of finite_element for Hcurl on segment geometry.
Specialization of finite_element for L2 on segment geometry.
H1 elements of order p.
static constexpr int order
the polynomial order of the elements
static constexpr Family family
the family of the basis functions
static constexpr int components
the number of components at each node
H(curl) elements of order p.
static constexpr int components
the number of components at each node
static constexpr int order
the polynomial order of the elements
static constexpr Family family
the family of the basis functions
Discontinuous elements of order p.
static constexpr int components
the number of components at each node
static constexpr int order
the polynomial order of the elements
static constexpr Family family
the family of the basis functions
"Quantity of Interest" elements (i.e. elements with a single shape function, 1)
static constexpr int order
the polynomial order of the elements
static constexpr Family family
the family of the basis functions
static constexpr int components
the number of components at each node
a convenience class for generating information about tensor product integration rules from the underl...
SERAC_HOST_DEVICE double weight(int ix, int iy) const
return the quadrature weight for a quadrilateral
SERAC_HOST_DEVICE double weight(int ix, int iy, int iz) const
return the quadrature weight for a hexahedron
tensor< double, q > points1D
the abscissae of the underlying 1D quadrature rule
tensor< double, q > weights1D
the weights of the underlying 1D quadrature rule
this struct is used to look up mfem's memory layout of the quadrature point jacobian matrices
this struct is used to look up mfem's memory layout of the quadrature point position vectors
Template prototype for finite element implementations.
Implementation of the tensor class used by Functional.
Specialization of finite_element for H1 on tetrahedron geometry.
Specialization of finite_element for L2 on tetrahedron geometry.
Specialization of finite_element for H1 on triangle geometry.
Specialization of finite_element for L2 on triangle geometry.
Implements a std::tuple-like object that works in CUDA kernels.