Smith  0.1
Smith is an implicit thermal structural mechanics simulation code.
segment_H1.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 // this specialization defines shape functions (and their gradients) that
14 // interpolate at Gauss-Lobatto nodes for the appropriate polynomial order
15 //
16 // note: mfem assumes the parent element domain is [0,1]
17 // for additional information on the finite_element concept requirements, see finite_element.hpp
19 template <int p, int c>
20 struct finite_element<mfem::Geometry::SEGMENT, H1<p, c> > {
21  static constexpr auto geometry = mfem::Geometry::SEGMENT;
22  static constexpr auto family = Family::H1;
23  static constexpr int components = c;
24  static constexpr int dim = 1;
25  static constexpr int n = (p + 1);
26  static constexpr int ndof = (p + 1);
27 
28  static constexpr int VALUE = 0, GRADIENT = 1;
29  static constexpr int SOURCE = 0, FLUX = 1;
30 
31  using dof_type = tensor<double, c, n>;
32  using dof_type_if = dof_type;
33 
34  using value_type = typename std::conditional<components == 1, double, tensor<double, components> >::type;
35  using derivative_type = value_type;
36  using qf_input_type = tuple<value_type, derivative_type>;
37 
38  using residual_type =
39  typename std::conditional<components == 1, tensor<double, ndof>, tensor<double, ndof, components> >::type;
40 
41  SMITH_HOST_DEVICE static constexpr tensor<double, ndof> shape_functions(double xi)
42  {
43  return GaussLobattoInterpolation<ndof>(xi);
44  }
45 
46  SMITH_HOST_DEVICE static constexpr tensor<double, ndof> shape_function_gradients(double xi)
47  {
48  return GaussLobattoInterpolationDerivative<ndof>(xi);
49  }
50 
61  template <bool apply_weights, int q>
62  static constexpr auto calculate_B()
63  {
64  constexpr auto points1D = GaussLegendreNodes<q, mfem::Geometry::SEGMENT>();
65  [[maybe_unused]] constexpr auto weights1D = GaussLegendreWeights<q, mfem::Geometry::SEGMENT>();
66  tensor<double, q, n> B{};
67  for (int i = 0; i < q; i++) {
68  B[i] = GaussLobattoInterpolation<n>(points1D[i]);
69  if constexpr (apply_weights) B[i] = B[i] * weights1D[i];
70  }
71  return B;
72  }
73 
84  template <bool apply_weights, int q>
85  static constexpr auto calculate_G()
86  {
87  constexpr auto points1D = GaussLegendreNodes<q, mfem::Geometry::SEGMENT>();
88  [[maybe_unused]] constexpr auto weights1D = GaussLegendreWeights<q, mfem::Geometry::SEGMENT>();
89  tensor<double, q, n> G{};
90  for (int i = 0; i < q; i++) {
91  G[i] = GaussLobattoInterpolationDerivative<n>(points1D[i]);
92  if constexpr (apply_weights) G[i] = G[i] * weights1D[i];
93  }
94  return G;
95  }
96 
97  template <typename T, int q>
98  SMITH_HOST_DEVICE static auto batch_apply_shape_fn(int jx, tensor<T, q> input, const TensorProductQuadratureRule<q>&)
99  {
100  static constexpr bool apply_weights = false;
101  static constexpr auto B = calculate_B<apply_weights, q>();
102  static constexpr auto G = calculate_G<apply_weights, q>();
103 
104  using source_t = decltype(get<0>(get<0>(T{})) + get<1>(get<0>(T{})));
105  using flux_t = decltype(get<0>(get<1>(T{})) + get<1>(get<1>(T{})));
106 
107  tensor<tuple<source_t, flux_t>, q> output;
108 
109  for (int qx = 0; qx < q; qx++) {
110  double phi_j = B(qx, jx);
111  double dphi_j_dxi = G(qx, jx);
112 
113  const auto& d00 = get<0>(get<0>(input(qx)));
114  const auto& d01 = get<1>(get<0>(input(qx)));
115  const auto& d10 = get<0>(get<1>(input(qx)));
116  const auto& d11 = get<1>(get<1>(input(qx)));
117 
118  output[qx] = {d00 * phi_j + d01 * dphi_j_dxi, d10 * phi_j + d11 * dphi_j_dxi};
119  }
120 
121  return output;
122  }
123 
124  template <int q>
125  SMITH_HOST_DEVICE static auto interpolate(const dof_type& X, const TensorProductQuadratureRule<q>&)
126  {
127  static constexpr bool apply_weights = false;
128  static constexpr auto B = calculate_B<apply_weights, q>();
129  static constexpr auto G = calculate_G<apply_weights, q>();
130 
131  tensor<double, c, q> value{};
132  tensor<double, c, q> gradient{};
133 
134  // apply the shape functions
135  for (int i = 0; i < c; i++) {
136  value(i) = dot(B, X[i]);
137  gradient(i) = dot(G, X[i]);
138  }
139 
140  // transpose the quadrature data into a tensor of tuples
141  tensor<qf_input_type, q> output;
142 
143  for (int qx = 0; qx < q; qx++) {
144  if constexpr (c == 1) {
145  get<VALUE>(output(qx)) = value(0, qx);
146  get<GRADIENT>(output(qx)) = gradient(0, qx);
147  } else {
148  for (int i = 0; i < c; i++) {
149  get<VALUE>(output(qx))[i] = value(i, qx);
150  get<GRADIENT>(output(qx))[i] = gradient(i, qx);
151  }
152  }
153  }
154 
155  return output;
156  }
157 
158  template <typename source_type, typename flux_type, int q>
159  SMITH_HOST_DEVICE static void integrate(const tensor<tuple<source_type, flux_type>, q>& qf_output,
160  const TensorProductQuadratureRule<q>&, dof_type* element_residual,
161  [[maybe_unused]] int step = 1)
162  {
163  if constexpr (is_zero<source_type>{} && is_zero<flux_type>{}) {
164  return;
165  }
166 
167  constexpr int ntrial = std::max(size(source_type{}), size(flux_type{}) / dim) / c;
168 
169  using s_buffer_type = std::conditional_t<is_zero<source_type>{}, zero, tensor<double, q> >;
170  using f_buffer_type = std::conditional_t<is_zero<flux_type>{}, zero, tensor<double, q> >;
171 
172  static constexpr bool apply_weights = true;
173  static constexpr auto B = calculate_B<apply_weights, q>();
174  static constexpr auto G = calculate_G<apply_weights, q>();
175 
176  for (int j = 0; j < ntrial; j++) {
177  for (int i = 0; i < c; i++) {
178  s_buffer_type source;
179  f_buffer_type flux;
180 
181  for (int qx = 0; qx < q; qx++) {
182  if constexpr (!is_zero<source_type>{}) {
183  source(qx) = reinterpret_cast<const double*>(&get<SOURCE>(qf_output[qx]))[i * ntrial + j];
184  }
185  if constexpr (!is_zero<flux_type>{}) {
186  flux(qx) = reinterpret_cast<const double*>(&get<FLUX>(qf_output[qx]))[i * ntrial + j];
187  }
188  }
189 
190  element_residual[j * step](i) += dot(source, B) + dot(flux, G);
191  }
192  }
193  }
194 };
#define SMITH_HOST_DEVICE
Macro that evaluates to __host__ __device__ when compiling with nvcc and does nothing on a host compi...
Definition: accelerator.hpp:38
constexpr SMITH_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:376
SMITH_HOST_DEVICE auto max(dual< gradient_type > a, double b)
Implementation of max for dual numbers.
Definition: dual.hpp:229
constexpr SMITH_HOST_DEVICE int size(const tensor< T, n... > &)
returns the total number of stored values in a tensor
Definition: tensor.hpp:1932
tensor(const T(&data)[n1]) -> tensor< T, n1 >
class template argument deduction guide for type tensor.
constexpr SMITH_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