hyper.deal
Loading...
Searching...
No Matches
evaluation_kernels.h
1#ifndef HYPERDEAL_NDIM_MATRIXFREE_EVALUTION_KERNELS
2#define HYPERDEAL_NDIM_MATRIXFREE_EVALUTION_KERNELS
3
4#include <hyper.deal/base/config.h>
5
6#include <deal.II/matrix_free/evaluation_flags.h>
7#include <deal.II/matrix_free/shape_info.h>
8
9namespace hyperdeal
10{
11 namespace internal
12 {
13 template <int dim_x,
14 int dim_v,
15 int n_rows,
16 int n_columns,
17 typename Number,
18 typename Number2 = Number>
20 {
21 static constexpr int dim = dim_x + dim_v;
22 static constexpr unsigned int n_rows_of_product =
23 dealii::Utilities::pow(n_rows, dim);
24 static constexpr unsigned int n_columns_of_product =
25 dealii::Utilities::pow(n_columns, dim);
26
28 : shape_values(nullptr)
29 , shape_gradients(nullptr)
30 , shape_hessians(nullptr)
31 {}
32
34 const dealii::AlignedVector<Number2> &shape_values,
35 const dealii::AlignedVector<Number2> &shape_gradients,
36 const dealii::AlignedVector<Number2> &shape_hessians,
37 const unsigned int dummy1 = 0,
38 const unsigned int dummy2 = 0)
39 : shape_values(shape_values.begin())
40 , shape_gradients(shape_gradients.begin())
41 , shape_hessians(shape_hessians.begin())
42 {
43 // We can enter this function either for the apply() path that has
44 // n_rows * n_columns entries or for the apply_face() path that only has
45 // n_rows * 3 entries in the array. Since we cannot decide about the use
46 // we must allow for both here.
47 Assert(shape_values.size() == 0 ||
48 shape_values.size() == n_rows * n_columns ||
49 shape_values.size() == 3 * n_rows,
50 dealii::ExcDimensionMismatch(shape_values.size(),
51 n_rows * n_columns));
52 Assert(shape_gradients.size() == 0 ||
53 shape_gradients.size() == n_rows * n_columns,
54 dealii::ExcDimensionMismatch(shape_gradients.size(),
55 n_rows * n_columns));
56 Assert(shape_hessians.size() == 0 ||
57 shape_hessians.size() == n_rows * n_columns,
58 dealii::ExcDimensionMismatch(shape_hessians.size(),
59 n_rows * n_columns));
60 (void)dummy1;
61 (void)dummy2;
62 }
63
64 template <int face_direction,
65 bool contract_onto_face,
66 bool add,
67 int max_derivative>
68 void
69 apply_face_1D(const Number *DEAL_II_RESTRICT in,
70 Number *DEAL_II_RESTRICT out,
71 const unsigned int in_index,
72 const unsigned int out_index) const
73 {
74 constexpr int in_stride =
75 dealii::Utilities::pow(n_rows, face_direction);
76 constexpr int out_stride = dealii::Utilities::pow(n_rows, dim - 1);
77
78 const Number2 *DEAL_II_RESTRICT shape_values = this->shape_values;
79
80 if (contract_onto_face == true)
81 {
82 Number res0 = shape_values[0] * in[in_index + 0];
83 Number res1, res2;
84 if (max_derivative > 0)
85 res1 = shape_values[n_rows] * in[in_index + 0];
86 if (max_derivative > 1)
87 res2 = shape_values[2 * n_rows] * in[in_index + 0];
88 for (int ind = 1; ind < n_rows; ++ind)
89 {
90 res0 += shape_values[ind] * in[in_index + in_stride * ind];
91 if (max_derivative > 0)
92 res1 +=
93 shape_values[ind + n_rows] * in[in_index + in_stride * ind];
94 if (max_derivative > 1)
95 res2 += shape_values[ind + 2 * n_rows] *
96 in[in_index + in_stride * ind];
97 }
98 if (add)
99 {
100 out[out_index + 0] += res0;
101 if (max_derivative > 0)
102 out[out_index + out_stride] += res1;
103 if (max_derivative > 1)
104 out[out_index + 2 * out_stride] += res2;
105 }
106 else
107 {
108 out[out_index + 0] = res0;
109 if (max_derivative > 0)
110 out[out_index + out_stride] = res1;
111 if (max_derivative > 1)
112 out[out_index + 2 * out_stride] = res2;
113 }
114 }
115 else
116 {
117 for (int col = 0; col < n_rows; ++col)
118 {
119 if (add)
120 out[in_index + col * in_stride] +=
121 shape_values[col] * in[out_index + 0];
122 else
123 out[in_index + col * in_stride] =
124 shape_values[col] * in[out_index + 0];
125 if (max_derivative > 0)
126 out[in_index + col * in_stride] +=
127 shape_values[col + n_rows] * in[out_index + out_stride];
128 if (max_derivative > 1)
129 out[in_index + col * in_stride] +=
130 shape_values[col + 2 * n_rows] *
131 in[out_index + 2 * out_stride];
132 }
133 }
134 }
135
136 template <int face_direction,
137 bool contract_onto_face,
138 bool add,
139 int max_derivative>
140 void
141 apply_face(const Number *DEAL_II_RESTRICT in,
142 Number *DEAL_II_RESTRICT out) const
143 {
144 static_assert(max_derivative >= 0 && max_derivative < 3,
145 "Only derivative orders 0-2 implemented");
146 Assert(shape_values != nullptr,
147 dealii::ExcMessage(
148 "The given array shape_values must not be the null pointer."));
149
150 AssertIndexRange(face_direction, dim);
151
152 using namespace dealii::Utilities;
153
154 if ((dim_x == 3) && (face_direction == 1)) // swap x face
155 {
156 for (int i3 = 0; i3 < pow(n_rows, dim_v); ++i3)
157 for (int i2 = 0; i2 < n_rows; ++i2)
158 for (int i1 = 0; i1 < n_rows; ++i1)
159 {
160 const unsigned in_index =
161 i1 + i2 * pow(n_rows, 2) + i3 * pow(n_rows, 3);
162
163 // swap i1 and i2
164 const unsigned out_index =
165 i2 + i1 * n_rows + i3 * pow(n_rows, 2);
166
167 apply_face_1D<face_direction,
168 contract_onto_face,
169 add,
170 max_derivative>(in, out, in_index, out_index);
171 }
172 }
173 else if ((dim_v == 3) && (face_direction == (1 + dim_x))) // swap v face
174 {
175 for (int i3 = 0; i3 < n_rows; ++i3)
176 for (int i2 = 0; i2 < n_rows; ++i2)
177 for (int i1 = 0; i1 < pow(n_rows, dim_x); ++i1)
178 {
179 const unsigned in_index = i1 + i2 * pow(n_rows, dim_x) +
180 i3 * pow(n_rows, dim_x + 2);
181
182 // swap i2 and i3
183 const unsigned out_index = i1 + i3 * pow(n_rows, dim_x) +
184 i2 * pow(n_rows, dim_x + 1);
185
186 apply_face_1D<face_direction,
187 contract_onto_face,
188 add,
189 max_derivative>(in, out, in_index, out_index);
190 }
191 }
192 else // lex
193 {
194 constexpr int n_blocks1 = pow(n_rows, face_direction);
195 constexpr int n_blocks2 =
196 pow(n_rows, std::max(dim - face_direction - 1, 0));
197
198 for (int i2 = 0; i2 < n_blocks2; ++i2)
199 for (int i1 = 0; i1 < n_blocks1; ++i1)
200 {
201 const unsigned in_index =
202 i1 + i2 * pow(n_rows, face_direction + 1);
203 const unsigned out_index =
204 i1 + i2 * pow(n_rows, face_direction);
205
206 apply_face_1D<face_direction,
207 contract_onto_face,
208 add,
209 max_derivative>(in, out, in_index, out_index);
210 }
211 }
212 }
213
214 private:
215 const Number2 *shape_values;
216 const Number2 *shape_gradients;
217 const Number2 *shape_hessians;
218 };
219
220 template <int dim_x, int dim_v, int fe_degree, typename Number>
222 {
223 static const int dim = dim_x + dim_v;
227 template <bool do_evaluate, bool add_into_output, typename Number2>
228 static void
230 const unsigned int n_components,
231 const dealii::EvaluationFlags::EvaluationFlags flags,
232 const dealii::internal::MatrixFreeFunctions::ShapeInfo<Number>
233 & shape_info,
234 const Number2 * input,
235 Number2 * output,
236 const unsigned int face_no)
237 {
238 Assert(static_cast<unsigned int>(fe_degree + 1) ==
239 shape_info.data.front().n_q_points_1d ||
240 fe_degree == -1,
241 dealii::ExcInternalError());
242
243 interpolate_generic<do_evaluate, add_into_output>(
244 n_components,
245 input,
246 output,
247 flags,
248 face_no,
249 shape_info.data.front().quadrature.size(),
250 shape_info.data.front().quadrature_data_on_face,
251 shape_info.n_q_points,
252 shape_info.n_q_points_face);
253 }
254
255 private:
256 template <bool do_evaluate,
257 bool add_into_output,
258 int face_direction = 0,
259 typename Number2>
260 static void
261 interpolate_generic(
262 const unsigned int n_components,
263 const Number2 * input,
264 Number2 * output,
265 const dealii::EvaluationFlags::EvaluationFlags flag,
266 const unsigned int face_no,
267 const unsigned int n_points_1d,
268 const std::array<dealii::AlignedVector<Number>, 2> &shape_data,
269 const unsigned int dofs_per_component_on_cell,
270 const unsigned int dofs_per_component_on_face)
271 {
272 if (face_direction == face_no / 2)
273 {
275 dim_v,
276 fe_degree + 1,
277 0,
278 Number2,
279 Number>
280 evalf(shape_data[face_no % 2],
281 dealii::AlignedVector<Number>(),
282 dealii::AlignedVector<Number>(),
283 n_points_1d,
284 0);
285
286 const unsigned int in_stride = do_evaluate ?
287 dofs_per_component_on_cell :
288 dofs_per_component_on_face;
289 const unsigned int out_stride = do_evaluate ?
290 dofs_per_component_on_face :
291 dofs_per_component_on_cell;
292
293 for (unsigned int c = 0; c < n_components; ++c)
294 {
295 if (flag & dealii::EvaluationFlags::hessians)
296 evalf.template apply_face<face_direction,
297 do_evaluate,
298 add_into_output,
299 2>(input, output);
300 else if (flag & dealii::EvaluationFlags::gradients)
301 evalf.template apply_face<face_direction,
302 do_evaluate,
303 add_into_output,
304 1>(input, output);
305 else
306 evalf.template apply_face<face_direction,
307 do_evaluate,
308 add_into_output,
309 0>(input, output);
310 input += in_stride;
311 output += out_stride;
312 }
313 }
314 else if (face_direction < dim)
315 {
316 interpolate_generic<do_evaluate,
317 add_into_output,
318 std::min(face_direction + 1, dim - 1)>(
319 n_components,
320 input,
321 output,
322 flag,
323 face_no,
324 n_points_1d,
325 shape_data,
326 dofs_per_component_on_cell,
327 dofs_per_component_on_face);
328 }
329 }
330 };
331
332 } // namespace internal
333} // namespace hyperdeal
334
335#endif
Definition evaluation_kernels.h:20
Definition evaluation_kernels.h:222
static void interpolate_quadrature(const unsigned int n_components, const dealii::EvaluationFlags::EvaluationFlags flags, const dealii::internal::MatrixFreeFunctions::ShapeInfo< Number > &shape_info, const Number2 *input, Number2 *output, const unsigned int face_no)
Definition evaluation_kernels.h:229