Serac  0.1
Serac is an implicit thermal strucural mechanics simulation code.
geometric_factors.cpp
1 #include "serac/numerics/functional/geometric_factors.hpp"
3 
4 namespace serac {
5 
16 template <int Q, mfem::Geometry::Type geom, typename function_space>
17 void compute_geometric_factors(mfem::Vector& positions_q, mfem::Vector& jacobians_q, const mfem::Vector& positions_e,
18  const std::vector<int>& elements)
19 {
20  static constexpr TensorProductQuadratureRule<Q> rule{};
21 
22  constexpr int spatial_dim = function_space::components;
23  constexpr int geometry_dim = dimension_of(geom);
24  constexpr int qpts_per_elem = num_quadrature_points(geom, Q);
25 
26  using element_type = finite_element<geom, function_space>;
27  using position_type = tensor<double, spatial_dim, qpts_per_elem>;
29 
30  auto X_q = reinterpret_cast<position_type*>(positions_q.ReadWrite());
31  auto J_q = reinterpret_cast<jacobian_type*>(jacobians_q.ReadWrite());
32  auto X = reinterpret_cast<const typename element_type::dof_type*>(positions_e.Read());
33 
34  std::size_t num_elements = elements.size();
35 
36  // for each element in the domain
37  for (uint32_t e = 0; e < num_elements; e++) {
38  // load the positions for the nodes in this element
39  auto X_e = X[elements[e]];
40 
41  // calculate the values and derivatives (w.r.t. xi) of X at each quadrature point
42  auto quadrature_values = element_type::interpolate(X_e, rule);
43 
44  // mfem wants to store this data in a different layout, so we have to transpose it
45  for (int q = 0; q < qpts_per_elem; q++) {
46  auto [value, gradient] = quadrature_values[q];
47  for (int i = 0; i < spatial_dim; i++) {
48  X_q[e](i, q) = value[i];
49  if constexpr (std::is_same_v<decltype(value), decltype(gradient)>) {
50  J_q[e](0, i, q) = gradient[i];
51  }
52  if constexpr (!std::is_same_v<decltype(value), decltype(gradient)>) {
53  for (int j = 0; j < geometry_dim; j++) {
54  J_q[e](j, i, q) = gradient(i, j);
55  }
56  }
57  }
58  }
59  }
60 }
61 
62 GeometricFactors::GeometricFactors(const Domain& d, int q, mfem::Geometry::Type g)
63 {
64  auto* nodes = d.mesh_.GetNodes();
65  auto* fes = nodes->FESpace();
66 
67  auto restriction = serac::ElementRestriction(fes, g);
68  mfem::Vector X_e(int(restriction.ESize()));
69  restriction.Gather(*nodes, X_e);
70 
71  // assumes all elements are the same order
72  int p = fes->GetElementOrder(0);
73 
74  int spatial_dim = d.mesh_.SpaceDimension();
75  int geometry_dim = dimension_of(g);
76  int qpts_per_elem = num_quadrature_points(g, q);
77 
78  if (g == mfem::Geometry::TRIANGLE) elements = d.tri_ids_;
79  if (g == mfem::Geometry::SQUARE) elements = d.quad_ids_;
80  if (g == mfem::Geometry::TETRAHEDRON) elements = d.tet_ids_;
81  if (g == mfem::Geometry::CUBE) elements = d.hex_ids_;
82 
83  num_elements = elements.size();
84 
85  X = mfem::Vector(int(num_elements) * qpts_per_elem * spatial_dim);
86  J = mfem::Vector(int(num_elements) * qpts_per_elem * spatial_dim * geometry_dim);
87 
88 #define DISPATCH_KERNEL(GEOM, P, Q) \
89  if (g == mfem::Geometry::GEOM && p == P && q == Q) { \
90  compute_geometric_factors<Q, mfem::Geometry::GEOM, H1<P, dimension_of(mfem::Geometry::GEOM)> >(X, J, X_e, \
91  elements); \
92  return; \
93  }
94 
95  DISPATCH_KERNEL(TRIANGLE, 1, 1);
96  DISPATCH_KERNEL(TRIANGLE, 1, 2);
97  DISPATCH_KERNEL(TRIANGLE, 1, 3);
98  DISPATCH_KERNEL(TRIANGLE, 1, 4);
99 
100  DISPATCH_KERNEL(SQUARE, 1, 1);
101  DISPATCH_KERNEL(SQUARE, 1, 2);
102  DISPATCH_KERNEL(SQUARE, 1, 3);
103  DISPATCH_KERNEL(SQUARE, 1, 4);
104 
105  DISPATCH_KERNEL(SQUARE, 2, 1);
106  DISPATCH_KERNEL(SQUARE, 2, 2);
107  DISPATCH_KERNEL(SQUARE, 2, 3);
108  DISPATCH_KERNEL(SQUARE, 2, 4);
109 
110  DISPATCH_KERNEL(SQUARE, 3, 1);
111  DISPATCH_KERNEL(SQUARE, 3, 2);
112  DISPATCH_KERNEL(SQUARE, 3, 3);
113  DISPATCH_KERNEL(SQUARE, 3, 4);
114 
115  DISPATCH_KERNEL(TETRAHEDRON, 1, 1);
116  DISPATCH_KERNEL(TETRAHEDRON, 1, 2);
117  DISPATCH_KERNEL(TETRAHEDRON, 1, 3);
118  DISPATCH_KERNEL(TETRAHEDRON, 1, 4);
119 
120  DISPATCH_KERNEL(CUBE, 1, 1);
121  DISPATCH_KERNEL(CUBE, 1, 2);
122  DISPATCH_KERNEL(CUBE, 1, 3);
123  DISPATCH_KERNEL(CUBE, 1, 4);
124 
125  DISPATCH_KERNEL(CUBE, 2, 1);
126  DISPATCH_KERNEL(CUBE, 2, 2);
127  DISPATCH_KERNEL(CUBE, 2, 3);
128  DISPATCH_KERNEL(CUBE, 2, 4);
129 
130  DISPATCH_KERNEL(CUBE, 3, 1);
131  DISPATCH_KERNEL(CUBE, 3, 2);
132  DISPATCH_KERNEL(CUBE, 3, 3);
133  DISPATCH_KERNEL(CUBE, 3, 4);
134 
135 #undef DISPATCH_KERNEL
136 
137  std::cout << "should never be reached " << std::endl;
138 }
139 
140 GeometricFactors::GeometricFactors(const Domain& d, int q, mfem::Geometry::Type g, FaceType type)
141 {
142  auto* nodes = d.mesh_.GetNodes();
143  auto* fes = nodes->FESpace();
144 
145  auto restriction = serac::ElementRestriction(fes, g, type);
146  mfem::Vector X_e(int(restriction.ESize()));
147  restriction.Gather(*nodes, X_e);
148 
149  // assumes all elements are the same order
150  int p = fes->GetElementOrder(0);
151 
152  int spatial_dim = d.mesh_.SpaceDimension();
153  int geometry_dim = dimension_of(g);
154  int qpts_per_elem = num_quadrature_points(g, q);
155 
156  // NB: we only want the number of elements with the specified
157  // geometry, which is not the same as mesh->GetNE() in general
158  elements = d.get(g);
159 
160  num_elements = std::size_t(elements.size());
161 
162  X = mfem::Vector(int(num_elements) * qpts_per_elem * spatial_dim);
163  J = mfem::Vector(int(num_elements) * qpts_per_elem * spatial_dim * geometry_dim);
164 
165 #define DISPATCH_KERNEL(GEOM, P, Q) \
166  if (g == mfem::Geometry::GEOM && p == P && q == Q) { \
167  compute_geometric_factors<Q, mfem::Geometry::GEOM, H1<P, dimension_of(mfem::Geometry::GEOM) + 1> >(X, J, X_e, \
168  elements); \
169  return; \
170  }
171 
172  DISPATCH_KERNEL(SEGMENT, 1, 1);
173  DISPATCH_KERNEL(SEGMENT, 1, 2);
174  DISPATCH_KERNEL(SEGMENT, 1, 3);
175  DISPATCH_KERNEL(SEGMENT, 1, 4);
176 
177  DISPATCH_KERNEL(SEGMENT, 2, 1);
178  DISPATCH_KERNEL(SEGMENT, 2, 2);
179  DISPATCH_KERNEL(SEGMENT, 2, 3);
180  DISPATCH_KERNEL(SEGMENT, 2, 4);
181 
182  DISPATCH_KERNEL(SEGMENT, 3, 1);
183  DISPATCH_KERNEL(SEGMENT, 3, 2);
184  DISPATCH_KERNEL(SEGMENT, 3, 3);
185  DISPATCH_KERNEL(SEGMENT, 3, 4);
186 
187  DISPATCH_KERNEL(TRIANGLE, 1, 1);
188  DISPATCH_KERNEL(TRIANGLE, 1, 2);
189  DISPATCH_KERNEL(TRIANGLE, 1, 3);
190  DISPATCH_KERNEL(TRIANGLE, 1, 4);
191 
192  DISPATCH_KERNEL(TRIANGLE, 2, 1);
193  DISPATCH_KERNEL(TRIANGLE, 2, 2);
194  DISPATCH_KERNEL(TRIANGLE, 2, 3);
195  DISPATCH_KERNEL(TRIANGLE, 2, 4);
196 
197  DISPATCH_KERNEL(TRIANGLE, 3, 1);
198  DISPATCH_KERNEL(TRIANGLE, 3, 2);
199  DISPATCH_KERNEL(TRIANGLE, 3, 3);
200  DISPATCH_KERNEL(TRIANGLE, 3, 4);
201 
202  DISPATCH_KERNEL(SQUARE, 1, 1);
203  DISPATCH_KERNEL(SQUARE, 1, 2);
204  DISPATCH_KERNEL(SQUARE, 1, 3);
205  DISPATCH_KERNEL(SQUARE, 1, 4);
206 
207  DISPATCH_KERNEL(SQUARE, 2, 1);
208  DISPATCH_KERNEL(SQUARE, 2, 2);
209  DISPATCH_KERNEL(SQUARE, 2, 3);
210  DISPATCH_KERNEL(SQUARE, 2, 4);
211 
212  DISPATCH_KERNEL(SQUARE, 3, 1);
213  DISPATCH_KERNEL(SQUARE, 3, 2);
214  DISPATCH_KERNEL(SQUARE, 3, 3);
215  DISPATCH_KERNEL(SQUARE, 3, 4);
216 
217 #undef DISPATCH_KERNEL
218 
219  std::cout << "should never be reached" << std::endl;
220 }
221 
222 } // namespace serac
This file contains helper traits and enumerations for classifying finite elements.
Accelerator functionality.
Definition: serac.cpp:38
constexpr int num_quadrature_points(mfem::Geometry::Type g, int Q)
return the number of quadrature points in a Gauss-Legendre rule with parameter "Q"
Definition: geometry.hpp:25
void compute_geometric_factors(mfem::Vector &positions_q, mfem::Vector &jacobians_q, const mfem::Vector &positions_e, const std::vector< int > &elements)
a kernel to compute the positions and jacobians at each quadrature point (mfem calls this "geometric ...
constexpr SERAC_HOST_DEVICE auto type(const tuple< T... > &values)
a function intended to be used for extracting the ith type from a tuple.
Definition: tuple.hpp:274
constexpr int dimension_of(mfem::Geometry::Type g)
Returns the dimension of an element geometry.
Definition: geometry.hpp:49
a class for representing a geometric region that can be used for integration
Definition: domain.hpp:21
const mfem::Mesh & mesh_
the underyling mesh for this domain
Definition: domain.hpp:32
const std::vector< int > & get(mfem::Geometry::Type geom) const
get elements by geometry type
Definition: domain.hpp:115
std::size_t num_elements
the number of elements in the domain
std::vector< int > elements
list of element indices that are part of the associated domain
mfem::Vector J
Jacobians of the element transformations at all quadrature points.
mfem::Vector X
Mapped (physical) coordinates of all quadrature points.
GeometricFactors()
default ctor, leaving this object uninitialized
a convenience class for generating information about tensor product integration rules from the underl...
Template prototype for finite element implementations.
Arbitrary-rank tensor class.
Definition: tensor.hpp:29