16#ifndef dealii_matrix_free_evaluation_kernels_h
17#define dealii_matrix_free_evaluation_kernels_h
36 template <MatrixFreeFunctions::ElementType element,
bool is_
long>
40 template <
bool is_
long>
58 template <
bool is_
long>
77 template <
bool is_
long>
127 evaluate(
const unsigned int n_components,
129 const Number *values_dofs_actual,
133 integrate(
const unsigned int n_components,
135 Number *values_dofs_actual,
137 const bool add_into_values_array);
142 *univariate_shape_data)
165 template <
int dim,
int fe_degree,
int n_q_po
ints_1d,
typename Number>
173 evaluate(
const unsigned int n_components,
175 const Number *values_dofs_actual,
179 integrate(
const unsigned int n_components,
181 Number *values_dofs_actual,
183 const bool add_into_values_array);
195 const unsigned int n_components,
197 const Number *values_dofs_actual,
203 std::array<const MatrixFreeFunctions::UnivariateShapeData<Number2> *, 3>
204 univariate_shape_data;
208 univariate_shape_data.fill(&shape_data.front());
210 if (shape_data.size() == dim)
211 for (
int i = 1; i < dim; ++i)
212 univariate_shape_data[i] = &shape_data[i];
214 Eval eval0 = create_evaluator_tensor_product(univariate_shape_data[0]);
215 Eval eval1 = create_evaluator_tensor_product(univariate_shape_data[1]);
216 Eval eval2 = create_evaluator_tensor_product(univariate_shape_data[2]);
218 const unsigned int temp_size =
221 (Eval::n_rows_of_product > Eval::n_columns_of_product ?
222 Eval::n_rows_of_product :
223 Eval::n_columns_of_product);
228 temp2 = temp1 +
std::max(Utilities::fixed_power<dim>(
229 shape_data.front().fe_degree + 1),
230 Utilities::fixed_power<dim>(
231 shape_data.front().n_q_points_1d));
235 temp2 = temp1 + temp_size;
238 const std::size_t n_q_points = temp_size == 0 ?
240 Eval::n_columns_of_product;
241 const std::size_t dofs_per_comp =
245 const Number *values_dofs = values_dofs_actual;
248 const std::size_t n_dofs_per_comp =
250 Number *values_dofs_tmp =
251 temp1 + 2 * (
std::max(n_dofs_per_comp, n_q_points));
253 fe_degree != -1 ? fe_degree : shape_data.front().fe_degree;
254 for (
unsigned int c = 0; c < n_components; ++c)
255 for (
int i = 0, count_p = 0, count_q = 0;
256 i < (dim > 2 ? degree + 1 : 1);
259 for (
int j = 0; j < (dim > 1 ? degree + 1 - i : 1); ++j)
261 for (
int k = 0; k < degree + 1 - j - i;
262 ++k, ++count_p, ++count_q)
263 values_dofs_tmp[c * dofs_per_comp + count_q] =
264 values_dofs_actual[c * n_dofs_per_comp + count_p];
265 for (
int k = degree + 1 - j - i; k < degree + 1;
267 values_dofs_tmp[c * dofs_per_comp + count_q] = Number();
269 for (
int j = degree + 1 - i; j < degree + 1; ++j)
270 for (
int k = 0; k < degree + 1; ++k, ++count_q)
271 values_dofs_tmp[c * dofs_per_comp + count_q] = Number();
273 values_dofs = values_dofs_tmp;
282 for (
unsigned int c = 0; c < n_components; ++c)
285 eval0.template values<0, true, false>(values_dofs, values_quad);
287 eval0.template gradients<0, true, false>(values_dofs,
291 values_dofs += dofs_per_comp;
292 values_quad += n_q_points;
293 gradients_quad += n_q_points;
298 for (
unsigned int c = 0; c < n_components; ++c)
303 eval0.template gradients<0, true, false>(values_dofs, temp1);
304 eval1.template values<1, true, false, 2>(temp1,
309 eval0.template values<0, true, false>(values_dofs, temp1);
311 eval1.template gradients<1, true, false, 2>(temp1,
316 eval1.template values<1, true, false>(temp1, values_quad);
319 values_dofs += dofs_per_comp;
320 values_quad += n_q_points;
321 gradients_quad += 2 * n_q_points;
326 for (
unsigned int c = 0; c < n_components; ++c)
331 eval0.template gradients<0, true, false>(values_dofs, temp1);
332 eval1.template values<1, true, false>(temp1, temp2);
333 eval2.template values<2, true, false, 3>(temp2,
338 eval0.template values<0, true, false>(values_dofs, temp1);
341 eval1.template gradients<1, true, false>(temp1, temp2);
342 eval2.template values<2, true, false, 3>(temp2,
348 eval1.template values<1, true, false>(temp1, temp2);
350 eval2.template gradients<2, true, false, 3>(temp2,
356 eval2.template values<2, true, false>(temp2, values_quad);
359 values_dofs += dofs_per_comp;
360 values_quad += n_q_points;
361 gradients_quad += 3 * n_q_points;
374 values_quad -= n_components * n_q_points;
375 values_dofs -= n_components * dofs_per_comp;
376 for (std::size_t c = 0; c < n_components; ++c)
377 for (std::size_t q = 0; q < n_q_points; ++q)
378 values_quad[c * n_q_points + q] +=
379 values_dofs[(c + 1) * dofs_per_comp - 1];
392 const unsigned int n_components,
394 Number *values_dofs_actual,
396 const bool add_into_values_array)
398 std::array<const MatrixFreeFunctions::UnivariateShapeData<Number2> *, 3>
399 univariate_shape_data;
402 univariate_shape_data.fill(&shape_data.front());
404 if (shape_data.size() == dim)
405 for (
int i = 1; i < dim; ++i)
406 univariate_shape_data[i] = &shape_data[i];
408 Eval eval0 = create_evaluator_tensor_product(univariate_shape_data[0]);
409 Eval eval1 = create_evaluator_tensor_product(univariate_shape_data[1]);
410 Eval eval2 = create_evaluator_tensor_product(univariate_shape_data[2]);
412 const unsigned int temp_size =
415 (Eval::n_rows_of_product > Eval::n_columns_of_product ?
416 Eval::n_rows_of_product :
417 Eval::n_columns_of_product);
422 temp2 = temp1 +
std::max(Utilities::fixed_power<dim>(
423 shape_data.front().fe_degree + 1),
424 Utilities::fixed_power<dim>(
425 shape_data.front().n_q_points_1d));
429 temp2 = temp1 + temp_size;
432 const std::size_t n_q_points = temp_size == 0 ?
434 Eval::n_columns_of_product;
435 const unsigned int dofs_per_comp =
437 Utilities::fixed_power<dim>(shape_data.front().fe_degree + 1) :
440 Number *values_dofs =
442 temp1 + 2 * (std::max<std::size_t>(
453 for (
unsigned int c = 0; c < n_components; ++c)
457 if (add_into_values_array ==
false)
458 eval0.template values<0, false, false>(values_quad,
461 eval0.template values<0, false, true>(values_quad,
467 add_into_values_array ==
true)
468 eval0.template gradients<0, false, true>(gradients_quad,
471 eval0.template gradients<0, false, false>(gradients_quad,
476 values_dofs += dofs_per_comp;
477 values_quad += n_q_points;
478 gradients_quad += n_q_points;
483 for (
unsigned int c = 0; c < n_components; ++c)
488 eval1.template values<1, false, false>(values_quad, temp1);
489 if (add_into_values_array ==
false)
490 eval0.template values<0, false, false>(temp1, values_dofs);
492 eval0.template values<0, false, true>(temp1, values_dofs);
496 eval1.template gradients<1, false, false, 2>(gradients_quad +
500 eval1.template values<1, false, true>(values_quad, temp1);
501 if (add_into_values_array ==
false)
502 eval0.template values<0, false, false>(temp1, values_dofs);
504 eval0.template values<0, false, true>(temp1, values_dofs);
505 eval1.template values<1, false, false, 2>(gradients_quad,
507 eval0.template gradients<0, false, true>(temp1, values_dofs);
511 values_dofs += dofs_per_comp;
512 values_quad += n_q_points;
513 gradients_quad += 2 * n_q_points;
518 for (
unsigned int c = 0; c < n_components; ++c)
523 eval2.template values<2, false, false>(values_quad, temp1);
524 eval1.template values<1, false, false>(temp1, temp2);
525 if (add_into_values_array ==
false)
526 eval0.template values<0, false, false>(temp2, values_dofs);
528 eval0.template values<0, false, true>(temp2, values_dofs);
532 eval2.template gradients<2, false, false, 3>(gradients_quad +
536 eval2.template values<2, false, true>(values_quad, temp1);
537 eval1.template values<1, false, false>(temp1, temp2);
538 eval2.template values<2, false, false, 3>(gradients_quad + 1,
540 eval1.template gradients<1, false, true>(temp1, temp2);
541 if (add_into_values_array ==
false)
542 eval0.template values<0, false, false>(temp2, values_dofs);
544 eval0.template values<0, false, true>(temp2, values_dofs);
545 eval2.template values<2, false, false, 3>(gradients_quad,
547 eval1.template values<1, false, false>(temp1, temp2);
548 eval0.template gradients<0, false, true>(temp2, values_dofs);
552 values_dofs += dofs_per_comp;
553 values_quad += n_q_points;
554 gradients_quad += 3 * n_q_points;
565 values_dofs -= n_components * dofs_per_comp - dofs_per_comp + 1;
566 values_quad -= n_components * n_q_points;
568 for (
unsigned int c = 0; c < n_components; ++c)
570 values_dofs[0] = values_quad[0];
571 for (
unsigned int q = 1; q < n_q_points; ++q)
572 values_dofs[0] += values_quad[q];
573 values_dofs += dofs_per_comp;
574 values_quad += n_q_points;
578 for (
unsigned int c = 0; c < n_components; ++c)
579 values_dofs[c * dofs_per_comp] = Number();
580 values_dofs += n_components * dofs_per_comp;
586 const std::size_t n_dofs_per_comp =
588 values_dofs -= dofs_per_comp * n_components;
590 fe_degree != -1 ? fe_degree : shape_data.front().fe_degree;
591 for (
unsigned int c = 0; c < n_components; ++c)
592 for (
int i = 0, count_p = 0, count_q = 0;
593 i < (dim > 2 ? degree + 1 : 1);
596 for (
int j = 0; j < (dim > 1 ? degree + 1 - i : 1); ++j)
598 for (
int k = 0; k < degree + 1 - j - i;
599 ++k, ++count_p, ++count_q)
600 values_dofs_actual[c * n_dofs_per_comp + count_p] =
601 values_dofs[c * dofs_per_comp + count_q];
604 count_q += i * (degree + 1);
611 template <
int dim,
int fe_degree,
int n_q_po
ints_1d,
typename Number>
618 Number>::evaluate(
const unsigned int n_components,
620 const Number *values_dofs_actual,
625 const std::size_t n_dofs =
636 const auto *
const shape_values = shape_data.front().shape_values.data();
638 const auto *in = values_dofs_actual;
640 for (
unsigned int c = 0; c < n_components; c += 3)
642 if (c + 1 == n_components)
651 shape_values, in, out, n_dofs, n_q_points, 1, 1);
652 else if (c + 2 == n_components)
661 shape_values, in, out, n_dofs, n_q_points, 1, 1);
671 shape_values, in, out, n_dofs, n_q_points, 1, 1);
673 out += 3 * n_q_points;
680 const auto *
const shape_gradients =
681 shape_data.front().shape_gradients.data();
683 const auto *in = values_dofs_actual;
685 for (
unsigned int c = 0; c < n_components; c += 3)
687 if (c + 1 == n_components)
696 shape_gradients, in, out, n_dofs, n_q_points * dim, 1, 1);
697 else if (c + 2 == n_components)
706 shape_gradients, in, out, n_dofs, n_q_points * dim, 1, 1);
716 shape_gradients, in, out, n_dofs, n_q_points * dim, 1, 1);
718 out += 3 * n_q_points * dim;
726 template <
int dim,
int fe_degree,
int n_q_po
ints_1d,
typename Number>
733 Number>::integrate(
const unsigned int n_components,
735 Number *values_dofs_actual,
737 const bool add_into_values_array)
742 const std::size_t n_dofs =
753 const auto *
const shape_values = shape_data.front().shape_values.data();
755 auto *out = values_dofs_actual;
757 for (
unsigned int c = 0; c < n_components; c += 3)
759 if (add_into_values_array ==
false)
761 if (c + 1 == n_components)
770 shape_values, in, out, n_dofs, n_q_points, 1, 1);
771 else if (c + 2 == n_components)
780 shape_values, in, out, n_dofs, n_q_points, 1, 1);
790 shape_values, in, out, n_dofs, n_q_points, 1, 1);
794 if (c + 1 == n_components)
803 shape_values, in, out, n_dofs, n_q_points, 1, 1);
804 else if (c + 2 == n_components)
813 shape_values, in, out, n_dofs, n_q_points, 1, 1);
823 shape_values, in, out, n_dofs, n_q_points, 1, 1);
826 in += 3 * n_q_points;
832 const auto *
const shape_gradients =
833 shape_data.front().shape_gradients.data();
835 auto *out = values_dofs_actual;
837 for (
unsigned int c = 0; c < n_components; c += 3)
839 if (add_into_values_array ==
false &&
842 if (c + 1 == n_components)
851 shape_gradients, in, out, n_dofs, n_q_points * dim, 1, 1);
852 else if (c + 2 == n_components)
861 shape_gradients, in, out, n_dofs, n_q_points * dim, 1, 1);
871 shape_gradients, in, out, n_dofs, n_q_points * dim, 1, 1);
875 if (c + 1 == n_components)
884 shape_gradients, in, out, n_dofs, n_q_points * dim, 1, 1);
885 else if (c + 2 == n_components)
894 shape_gradients, in, out, n_dofs, n_q_points * dim, 1, 1);
904 shape_gradients, in, out, n_dofs, n_q_points * dim, 1, 1);
907 in += 3 * n_q_points * dim;
930 static_assert(basis_size_1 == 0 || basis_size_1 <= basis_size_2,
931 "The second dimension must not be smaller than the first");
955 template <
typename Number,
typename Number2>
962 const Number *values_in,
964 const unsigned int basis_size_1_variable =
966 const unsigned int basis_size_2_variable =
970 basis_size_1 != 0 || basis_size_1_variable <= basis_size_2_variable,
971 ExcMessage(
"The second dimension must not be smaller than the first"));
979 constexpr int next_dim = (dim == 1 || (dim == 2 && basis_size_1 > 0 &&
980 basis_size_1 == basis_size_2)) ?
987 (basis_size_1 == 0 ? 0 : basis_size_2),
990 eval_val(transformation_matrix,
993 basis_size_1_variable,
994 basis_size_2_variable);
995 const unsigned int np_1 =
996 basis_size_1 > 0 ? basis_size_1 : basis_size_1_variable;
997 const unsigned int np_2 =
998 basis_size_1 > 0 ? basis_size_2 : basis_size_2_variable;
1000 ExcMessage(
"Cannot transform with 0-point basis"));
1002 ExcMessage(
"Cannot transform with 0-point basis"));
1006 values_in = values_in + n_components * Utilities::fixed_power<dim>(np_1);
1008 values_out + n_components * Utilities::fixed_power<dim>(np_2);
1009 for (
unsigned int c = n_components; c != 0; --c)
1011 values_in -= Utilities::fixed_power<dim>(np_1);
1012 values_out -= Utilities::fixed_power<dim>(np_2);
1014 for (
unsigned int q = np_1; q != 0; --q)
1021 transformation_matrix,
1023 (q - 1) * Utilities::fixed_power<next_dim>(np_1),
1025 (q - 1) * Utilities::fixed_power<next_dim>(np_2),
1026 basis_size_1_variable,
1027 basis_size_2_variable);
1032 if (basis_size_1 > 0 && basis_size_2 == basis_size_1 && dim == 2)
1034 eval_val.template values<0, true, false>(values_in, values_out);
1035 eval_val.template values<1, true, false>(values_out, values_out);
1038 eval_val.template values<dim - 1,
true,
false>(values_in,
1041 eval_val.template values<dim - 1,
true,
false>(values_out,
1076 template <
typename Number,
typename Number2>
1083 const bool add_into_result,
1086 const unsigned int basis_size_1_variable =
1088 const unsigned int basis_size_2_variable =
1092 basis_size_1 != 0 || basis_size_1_variable <= basis_size_2_variable,
1093 ExcMessage(
"The second dimension must not be smaller than the first"));
1094 Assert(add_into_result ==
false || values_in != values_out,
1096 "Input and output cannot alias with each other when "
1097 "adding the result of the basis change to existing data"));
1103 constexpr int next_dim =
1105 ((basis_size_1 == 0 || basis_size_2 > basis_size_1) && dim > 1)) ?
1111 (basis_size_1 == 0 ? 0 : basis_size_2),
1114 eval_val(transformation_matrix,
1115 transformation_matrix,
1116 transformation_matrix,
1117 basis_size_1_variable,
1118 basis_size_2_variable);
1119 const unsigned int np_1 =
1120 basis_size_1 > 0 ? basis_size_1 : basis_size_1_variable;
1121 const unsigned int np_2 =
1122 basis_size_1 > 0 ? basis_size_2 : basis_size_2_variable;
1124 ExcMessage(
"Cannot transform with 0-point basis"));
1126 ExcMessage(
"Cannot transform with 0-point basis"));
1128 for (
unsigned int c = 0; c < n_components; ++c)
1130 if (basis_size_1 > 0 && basis_size_2 == basis_size_1 && dim == 2)
1133 eval_val.template values<1, false, false>(values_in, values_in);
1135 eval_val.template hessians<1, false, false>(values_in,
1138 if (add_into_result)
1141 eval_val.template values<0, false, true>(values_in,
1144 eval_val.template hessians<0, false, true>(values_in,
1150 eval_val.template values<0, false, false>(values_in,
1153 eval_val.template hessians<0, false, false>(values_in,
1159 if (dim == 1 && add_into_result)
1162 eval_val.template values<0, false, true>(values_in,
1165 eval_val.template hessians<0, false, true>(values_in,
1171 eval_val.template values<0, false, false>(values_in,
1174 eval_val.template hessians<0, false, false>(values_in,
1180 eval_val.template values<dim - 1,
false,
false>(values_in,
1183 eval_val.template hessians<dim - 1,
false,
false>(
1184 values_in, values_in);
1188 for (
unsigned int q = 0; q < np_1; ++q)
1195 transformation_matrix,
1198 q * Utilities::fixed_power<next_dim>(np_2),
1200 q * Utilities::fixed_power<next_dim>(np_1),
1201 basis_size_1_variable,
1202 basis_size_2_variable);
1204 values_in += Utilities::fixed_power<dim>(np_2);
1205 values_out += Utilities::fixed_power<dim>(np_1);
1229 template <
typename Number,
typename Number2>
1234 const Number *values_in,
1235 Number *scratch_data,
1238 constexpr int next_dim = dim > 1 ? dim - 1 : dim;
1239 Number *my_scratch =
1240 basis_size_1 != basis_size_2 ? scratch_data : values_out;
1242 const unsigned int size_per_component =
Utilities::pow(basis_size_2, dim);
1243 Assert(coefficients.
size() == size_per_component ||
1244 coefficients.
size() == n_components * size_per_component,
1246 const unsigned int stride =
1247 coefficients.
size() == size_per_component ? 0 : 1;
1249 for (
unsigned int q = basis_size_1; q != 0; --q)
1256 transformation_matrix,
1269 eval_val(transformation_matrix);
1270 const unsigned int n_inner_blocks =
1271 (dim > 1 && basis_size_2 < 10) ? basis_size_2 : 1;
1272 const unsigned int n_blocks =
Utilities::pow(basis_size_2, dim - 1);
1273 for (
unsigned int ii = 0; ii < n_blocks; ii += n_inner_blocks)
1274 for (
unsigned int c = 0; c < n_components; ++c)
1276 for (
unsigned int i = ii; i < ii + n_inner_blocks; ++i)
1277 eval_val.template values_one_line<dim - 1, true, false>(
1278 my_scratch + i, my_scratch + i);
1279 for (
unsigned int q = 0; q < basis_size_2; ++q)
1280 for (
unsigned int i = ii; i < ii + n_inner_blocks; ++i)
1281 my_scratch[i + q * n_blocks + c * size_per_component] *=
1282 coefficients[i + q * n_blocks +
1283 c * stride * size_per_component];
1284 for (
unsigned int i = ii; i < ii + n_inner_blocks; ++i)
1285 eval_val.template values_one_line<dim - 1, false, false>(
1286 my_scratch + i, my_scratch + i);
1288 for (
unsigned int q = 0; q < basis_size_1; ++q)
1295 transformation_matrix,
1311 template <
int n_po
ints_1d,
int dim,
typename Number,
typename Number2>
1315 const Number *values,
1319 (n_points_1d + 1) / 2 * n_points_1d);
1337 eval.template gradients<0, true, false>(values, gradients);
1341 eval.template gradients<2, true, false, dim>(values, gradients + 2);
1342 constexpr unsigned int loop_bound = (dim > 2 ? n_points_1d : 1);
1343 constexpr unsigned int n_points_2d = n_points_1d * n_points_1d;
1344 const Number *in = values + (loop_bound - 1) * n_points_2d;
1345 Number *out = gradients + (loop_bound - 1) * dim * n_points_2d;
1346 for (
unsigned int l = 0; l < loop_bound; ++l)
1348 eval_2d.template gradients<0, true, false, dim>(in, out);
1349 eval_2d.template gradients<1, true, false, dim>(in, out + 1);
1351 out -= dim * n_points_2d;
1365 template <
int n_po
ints_1d,
int dim,
typename Number,
typename Number2>
1370 const Number *gradients,
1371 const bool add_into_values_array)
1374 (n_points_1d + 1) / 2 * n_points_1d);
1393 if (add_into_values_array)
1394 eval.template gradients<0, false, true>(gradients, values);
1396 eval.template gradients<0, false, false>(gradients, values);
1400 constexpr unsigned int loop_bound = (dim > 2 ? n_points_1d : 1);
1401 constexpr unsigned int n_points_2d = n_points_1d * n_points_1d;
1403 const Number *in = gradients + (loop_bound - 1) * dim * n_points_2d;
1404 Number *out = values + (loop_bound - 1) * n_points_2d;
1405 for (
unsigned int l = 0; l < loop_bound; ++l)
1407 if (add_into_values_array)
1408 eval_2d.template gradients<0, false, true, dim>(in, out);
1410 eval_2d.template gradients<0, false, false, dim>(in, out);
1411 eval_2d.template gradients<1, false, true, dim>(in + 1, out);
1412 in -= dim * n_points_2d;
1417 eval.template gradients<2, false, true, dim>(gradients + 2, values);
1428 template <
int n_po
ints_1d,
int dim,
typename Number>
1442 data.n_q_points_1d *
data.n_q_points_1d);
1450 data.shape_gradients_collocation.data(),
1451 data.shape_hessians_collocation.data(),
1453 data.n_q_points_1d);
1459 for (
unsigned int comp = 0; comp < n_components; ++comp)
1462 eval.template hessians<0, true, false>(values, hessians);
1468 eval.template gradients<0, true, false>(values, scratch);
1469 eval.template gradients<1, true, false>(scratch,
1470 hessians + dim * n_points);
1472 eval.template hessians<1, true, false>(values, hessians + n_points);
1477 eval.template gradients<2, true, false>(scratch,
1478 hessians + 4 * n_points);
1480 eval.template gradients<1, true, false>(values, scratch);
1481 eval.template gradients<2, true, false>(scratch,
1482 hessians + 5 * n_points);
1484 eval.template hessians<2, true, false>(values,
1485 hessians + 2 * n_points);
1489 hessians += (dim * (dim + 1)) / 2 * n_points;
1501 template <
int n_q_po
ints_1d,
int dim,
typename Number>
1505 const bool add_into_values_array)
1513 data.n_q_points_1d *
data.n_q_points_1d);
1521 data.shape_gradients_collocation.data(),
1522 data.shape_hessians_collocation.data(),
1524 data.n_q_points_1d);
1530 for (
unsigned int comp = 0; comp < n_components; ++comp)
1533 if (add_into_values_array ==
true)
1534 eval.template hessians<0, false, true>(hessians, values);
1536 eval.template hessians<0, false, false>(hessians, values);
1540 eval.template hessians<1, false, true>(hessians + n_points, values);
1544 eval.template hessians<2, false, true>(hessians + 2 * n_points,
1547 eval.template gradients<2, false, false>(hessians + 5 * n_points,
1549 eval.template gradients<1, false, true>(scratch, values);
1552 eval.template gradients<2, false, false>(hessians + 4 * n_points,
1559 eval.template gradients<1,
false, (dim > 2)>(hessians +
1562 eval.template gradients<0, false, true>(scratch, values);
1566 hessians += (dim * (dim + 1)) / 2 * n_points;
1578 template <
int dim,
typename Number>
1581 const Number *values_dofs,
1587 using Eval =
typename Impl::Eval;
1589 Impl::create_evaluator_tensor_product(&univariate_shape_data[0]);
1590 Eval eval1 = Impl::create_evaluator_tensor_product(
1591 &univariate_shape_data[std::min<int>(1,
1592 univariate_shape_data.size() - 1)]);
1593 Eval eval2 = Impl::create_evaluator_tensor_product(
1594 &univariate_shape_data[std::min<int>(2,
1595 univariate_shape_data.size() - 1)]);
1600 tmp1 +
std::max(Utilities::fixed_power<dim>(
1601 univariate_shape_data.front().fe_degree + 1),
1602 Utilities::fixed_power<dim>(
1603 univariate_shape_data.front().n_q_points_1d));
1606 for (
unsigned int comp = 0; comp < n_components;
1608 hessians += n_points * dim * (dim + 1) / 2,
1614 eval0.template hessians<0, true, false>(values_dofs, hessians);
1618 eval0.template hessians<0, true, false>(values_dofs, tmp1);
1619 eval1.template values<1, true, false>(tmp1, hessians);
1621 eval0.template gradients<0, true, false>(values_dofs, tmp1);
1622 eval1.template gradients<1, true, false>(tmp1,
1623 hessians + 2 * n_points);
1625 eval0.template values<0, true, false>(values_dofs, tmp1);
1626 eval1.template hessians<1, true, false>(tmp1, hessians + n_points);
1630 eval0.template hessians<0, true, false>(values_dofs, tmp1);
1631 eval1.template values<1, true, false>(tmp1, tmp2);
1632 eval2.template values<2, true, false>(tmp2, hessians);
1634 eval0.template gradients<0, true, false>(values_dofs, tmp1);
1635 eval1.template gradients<1, true, false>(tmp1, tmp2);
1636 eval2.template values<2, true, false>(tmp2,
1637 hessians + 3 * n_points);
1639 eval1.template values<1, true, false>(tmp1, tmp2);
1640 eval2.template gradients<2, true, false>(tmp2,
1641 hessians + 4 * n_points);
1643 eval0.template values<0, true, false>(values_dofs, tmp1);
1644 eval1.template hessians<1, true, false>(tmp1, tmp2);
1645 eval2.template values<2, true, false>(tmp2, hessians + n_points);
1647 eval1.template gradients<1, true, false>(tmp1, tmp2);
1648 eval2.template gradients<2, true, false>(tmp2,
1649 hessians + 5 * n_points);
1651 eval1.template values<1, true, false>(tmp1, tmp2);
1652 eval2.template hessians<2, true, false>(tmp2,
1653 hessians + 2 * n_points);
1659 "Only 1d, 2d and 3d implemented for Hessian"));
1672 template <
int dim,
typename Number>
1676 Number *values_dofs,
1677 const bool add_into_values_array)
1682 using Eval =
typename Impl::Eval;
1684 Impl::create_evaluator_tensor_product(&univariate_shape_data[0]);
1685 Eval eval1 = Impl::create_evaluator_tensor_product(
1686 &univariate_shape_data[std::min<int>(1,
1687 univariate_shape_data.size() - 1)]);
1688 Eval eval2 = Impl::create_evaluator_tensor_product(
1689 &univariate_shape_data[std::min<int>(2,
1690 univariate_shape_data.size() - 1)]);
1695 tmp1 +
std::max(Utilities::fixed_power<dim>(
1696 univariate_shape_data.front().fe_degree + 1),
1697 Utilities::fixed_power<dim>(
1698 univariate_shape_data.front().n_q_points_1d));
1701 for (
unsigned int comp = 0; comp < n_components;
1703 hessians += n_points * dim * (dim + 1) / 2,
1709 if (add_into_values_array)
1710 eval0.template hessians<0, false, true>(hessians, values_dofs);
1712 eval0.template hessians<0, false, false>(hessians, values_dofs);
1716 eval1.template values<1, false, false>(hessians, tmp1);
1717 if (add_into_values_array)
1718 eval0.template hessians<0, false, true>(tmp1, values_dofs);
1720 eval0.template hessians<0, false, false>(tmp1, values_dofs);
1723 eval1.template gradients<1, false, false>(hessians + 2 * n_points,
1725 eval0.template gradients<0, false, true>(tmp1, values_dofs);
1727 eval1.template hessians<1, false, false>(hessians + n_points, tmp1);
1728 eval0.template values<0, false, true>(tmp1, values_dofs);
1732 eval2.template values<2, false, false>(hessians, tmp1);
1733 eval1.template values<1, false, false>(tmp1, tmp2);
1735 if (add_into_values_array)
1736 eval0.template hessians<0, false, true>(tmp2, values_dofs);
1738 eval0.template hessians<0, false, false>(tmp2, values_dofs);
1741 eval2.template values<2, false, false>(hessians + 3 * n_points,
1743 eval1.template gradients<1, false, false>(tmp1, tmp2);
1745 eval2.template gradients<2, false, false>(hessians + 4 * n_points,
1747 eval1.template values<1, false, true>(tmp1, tmp2);
1748 eval1.template values<0, false, true>(tmp2, values_dofs);
1751 eval2.template values<2, false, false>(hessians + n_points, tmp1);
1752 eval1.template hessians<1, false, false>(tmp1, tmp2);
1755 eval2.template gradients<2, false, false>(hessians + 5 * n_points,
1757 eval1.template gradients<1, false, true>(tmp1, tmp2);
1760 eval2.template hessians<2, false, false>(hessians + 2 * n_points,
1762 eval1.template values<1, false, true>(tmp1, tmp2);
1763 eval0.template values<0, false, true>(tmp2, values_dofs);
1769 "Only 1d, 2d and 3d implemented for Hessian"));
1787 template <
int dim,
int fe_degree,
typename Number>
1802 const Number *values_dofs,
1805 constexpr std::size_t n_points =
Utilities::pow(fe_degree + 1, dim);
1807 for (
unsigned int c = 0; c < n_components; ++c)
1810 for (
unsigned int i = 0; i < n_points; ++i)
1812 values_dofs[n_points * c + i];
1815 evaluate_gradients_collocation<fe_degree + 1, dim>(
1817 values_dofs + c * n_points,
1825 Number *values_dofs,
1827 const bool add_into_values_array)
1829 constexpr std::size_t n_points =
Utilities::pow(fe_degree + 1, dim);
1831 for (
unsigned int c = 0; c < n_components; ++c)
1835 if (add_into_values_array)
1836 for (
unsigned int i = 0; i < n_points; ++i)
1837 values_dofs[n_points * c + i] +=
1840 for (
unsigned int i = 0; i < n_points; ++i)
1841 values_dofs[n_points * c + i] =
1846 integrate_gradients_collocation<fe_degree + 1, dim>(
1848 values_dofs + c * n_points,
1850 add_into_values_array ||
1868 template <
int dim,
int fe_degree,
int n_q_po
ints_1d,
typename Number>
1874 const Number *values_dofs,
1879 Assert(n_q_points_1d > fe_degree,
1880 ExcMessage(
"You lose information when going to a collocation "
1881 "space of lower degree, so the evaluation results "
1882 "would be wrong. Thus, this class does not permit "
1883 "the chosen operation."));
1884 constexpr std::size_t n_dofs =
Utilities::pow(fe_degree + 1, dim);
1885 constexpr std::size_t n_q_points =
Utilities::pow(n_q_points_1d, dim);
1887 for (
unsigned int c = 0; c < n_components; ++c)
1893 (fe_degree >= n_q_points_1d ? n_q_points_1d : fe_degree + 1),
1894 n_q_points_1d>::do_forward(1,
1895 shape_data.shape_values_eo,
1896 values_dofs + c * n_dofs,
1901 evaluate_gradients_collocation<n_q_points_1d, dim>(
1911 Number *values_dofs,
1913 const bool add_into_values_array)
1917 Assert(n_q_points_1d > fe_degree,
1918 ExcMessage(
"You lose information when going to a collocation "
1919 "space of lower degree, so the evaluation results "
1920 "would be wrong. Thus, this class does not permit "
1921 "the chosen operation."));
1922 constexpr std::size_t n_q_points =
Utilities::pow(n_q_points_1d, dim);
1924 for (
unsigned int c = 0; c < n_components; ++c)
1928 integrate_gradients_collocation<n_q_points_1d, dim>(
1940 (fe_degree >= n_q_points_1d ? n_q_points_1d : fe_degree + 1),
1941 n_q_points_1d>::do_backward(1,
1942 shape_data.shape_values_eo,
1943 add_into_values_array,
1958 template <
int dim,
int fe_degree,
int n_q_po
ints_1d,
typename Number>
1968 template <
bool integrate>
1970 evaluate_or_integrate(
1972 Number *values_dofs_actual,
1974 const bool add_into_values_array =
false);
1979 template <
int dim,
int fe_degree,
int n_q_po
ints_1d,
typename Number>
1980 template <
bool integrate>
1987 evaluate_or_integrate(
1989 Number *values_dofs,
1993 Assert(dim == 2 || dim == 3,
1994 ExcMessage(
"Only dim = 2,3 implemented for Raviart-Thomas "
1995 "evaluation/integration"));
2009 const unsigned int dofs_per_component =
2011 const unsigned int n_points =
Utilities::pow(n_q_points_1d, dim);
2022 integrate_gradients_collocation<n_q_points_1d, dim>(shape_data[0],
2026 if constexpr (dim > 2)
2027 eval.template tangential<2, 0>(shape_data[1], values, values);
2028 eval.template tangential<1, 0>(shape_data[1], values, values);
2029 eval.template normal<0>(shape_data[0], values, values_dofs, add);
2032 gradients += n_points * dim;
2033 values_dofs += dofs_per_component;
2036 integrate_gradients_collocation<n_q_points_1d, dim>(shape_data[0],
2040 if constexpr (dim > 2)
2041 eval.template tangential<2, 1>(shape_data[1], values, values);
2042 eval.template tangential<0, 1>(shape_data[1], values, values);
2043 eval.template normal<1>(shape_data[0], values, values_dofs, add);
2045 if constexpr (dim > 2)
2048 gradients += n_points * dim;
2049 values_dofs += dofs_per_component;
2052 integrate_gradients_collocation<n_q_points_1d, dim>(shape_data[0],
2056 eval.template tangential<1, 2>(shape_data[1], values, values);
2057 eval.template tangential<0, 2>(shape_data[1], values, values);
2058 eval.template normal<0>(shape_data[0], values, values_dofs, add);
2065 eval.template normal<0>(shape_data[0], values_dofs, values);
2066 eval.template tangential<1, 0>(shape_data[1], values, values);
2067 if constexpr (dim > 2)
2068 eval.template tangential<2, 0>(shape_data[1], values, values);
2070 evaluate_gradients_collocation<n_q_points_1d, dim>(shape_data[0],
2075 gradients += n_points * dim;
2076 values_dofs += dofs_per_component;
2078 eval.template normal<1>(shape_data[0], values_dofs, values);
2079 eval.template tangential<0, 1>(shape_data[1], values, values);
2080 if constexpr (dim > 2)
2081 eval.template tangential<2, 1>(shape_data[1], values, values);
2083 evaluate_gradients_collocation<n_q_points_1d, dim>(shape_data[0],
2087 if constexpr (dim > 2)
2090 gradients += n_points * dim;
2091 values_dofs += dofs_per_component;
2093 eval.template normal<2>(shape_data[0], values_dofs, values);
2094 eval.template tangential<0, 2>(shape_data[1], values, values);
2095 eval.template tangential<1, 2>(shape_data[1], values, values);
2097 evaluate_gradients_collocation<n_q_points_1d, dim>(shape_data[0],
2121 template <
int dim,
typename Number,
bool do_
integrate>
2124 template <
int fe_degree,
int n_q_po
ints_1d,
typename OtherNumber>
2126 run(
const unsigned int n_components,
2128 OtherNumber *values_dofs,
2130 const bool sum_into_values_array_in =
false)
2134 static_assert(std::is_same_v<Number, std::remove_const_t<OtherNumber>>,
2135 "Type of Number and of OtherNumber do not match.");
2142 element_type == ElementType::tensor_general) ||
2143 element_type == ElementType::tensor_raviart_thomas,
2147 bool sum_into_values_array = sum_into_values_array_in;
2153 if constexpr (do_integrate)
2157 integrate_hessians_collocation<n_q_points_1d>(
2166 sum_into_values_array);
2167 sum_into_values_array =
true;
2172 if (fe_degree >= 0 && fe_degree + 1 == n_q_points_1d &&
2173 element_type == ElementType::tensor_symmetric_collocation)
2181 sum_into_values_array);
2185 else if (fe_degree >= 0 &&
2187 element_type <= ElementType::tensor_symmetric)
2198 sum_into_values_array);
2200 else if (fe_degree >= 0 &&
2201 element_type <= ElementType::tensor_symmetric_no_collocation)
2212 sum_into_values_array);
2214 else if (element_type == ElementType::tensor_none)
2222 sum_into_values_array);
2224 else if (element_type == ElementType::tensor_symmetric_plus_dg0)
2231 Number>>(n_components,
2235 sum_into_values_array);
2237 else if (element_type == ElementType::truncated_tensor)
2248 sum_into_values_array);
2250 else if (element_type == ElementType::tensor_raviart_thomas)
2252 if constexpr (fe_degree > 0 && n_q_points_1d > 0 && dim > 1)
2259 template evaluate_or_integrate<do_integrate>(
2261 const_cast<Number *
>(values_dofs),
2263 sum_into_values_array);
2269 "in 2d/3d and with templated degree"));
2283 sum_into_values_array);
2292 evaluate_hessians_collocation<n_q_points_1d>(n_components, fe_eval);
2301 template <
typename T>
2304 const unsigned int n_components,
2306 const Number *values_dofs,
2308 const bool sum_into_values_array,
2309 std::bool_constant<false>)
2311 (void)sum_into_values_array;
2313 T::evaluate(n_components, evaluation_flag, values_dofs, fe_eval);
2316 template <
typename T>
2319 const unsigned int n_components,
2321 Number *values_dofs,
2323 const bool sum_into_values_array,
2324 std::bool_constant<true>)
2326 T::integrate(n_components,
2330 sum_into_values_array);
2333 template <
typename T,
typename OtherNumber>
2336 const unsigned int n_components,
2338 OtherNumber *values_dofs,
2340 const bool sum_into_values_array)
2342 evaluate_or_integrate<T>(n_components,
2346 sum_into_values_array,
2347 std::bool_constant<do_integrate>());
2357 template <
int dim,
typename Number>
2363 template <
int fe_degree,
int = 0>
2365 run(
const unsigned int n_components,
2367 const Number *in_array,
2370 const unsigned int given_degree =
2371 (fe_degree > -1) ? fe_degree :
2374 const unsigned int dofs_per_component =
2394 for (
unsigned int d = 0; d < n_components; ++d)
2396 const Number *in = in_array + d * dofs_per_component;
2397 Number *out = out_array + d * dofs_per_component;
2400 evaluator.template hessians<0, true, false>(in, out);
2402 evaluator.template hessians<1, true, false>(out, out);
2404 evaluator.template hessians<2, true, false>(out, out);
2406 for (
unsigned int q = 0; q < dofs_per_component; ++q)
2408 const Number inverse_JxW_q = Number(1.) / fe_eval.
JxW(q);
2409 for (
unsigned int d = 0; d < n_components; ++d)
2410 out_array[q + d * dofs_per_component] *= inverse_JxW_q;
2412 for (
unsigned int d = 0; d < n_components; ++d)
2414 Number *out = out_array + d * dofs_per_component;
2416 evaluator.template hessians<2, false, false>(out, out);
2418 evaluator.template hessians<1, false, false>(out, out);
2419 evaluator.template hessians<0, false, false>(out, out);
2433 template <
int dim,
typename Number>
2439 template <
int fe_degree,
int = 0>
2441 run(
const unsigned int n_desired_components,
2444 const bool dyadic_coefficients,
2445 const Number *in_array,
2448 const unsigned int given_degree =
2449 (fe_degree > -1) ? fe_degree :
2452 const unsigned int dofs_per_component =
2456 inverse_coefficients.
size() % dofs_per_component == 0,
2458 "Expected diagonal to be a multiple of scalar dof per cells"));
2460 if (!dyadic_coefficients)
2462 if (inverse_coefficients.
size() != dofs_per_component)
2464 inverse_coefficients.
size());
2470 inverse_coefficients.
size());
2490 const Number *in = in_array;
2491 Number *out = out_array;
2493 const Number *inv_coefficient = inverse_coefficients.
data();
2495 const unsigned int shift_coefficient =
2496 inverse_coefficients.
size() > dofs_per_component ? dofs_per_component :
2499 const auto n_comp_outer = dyadic_coefficients ? 1 : n_desired_components;
2500 const auto n_comp_inner = dyadic_coefficients ? n_desired_components : 1;
2502 for (
unsigned int d = 0; d < n_comp_outer; ++d)
2504 for (
unsigned int di = 0; di < n_comp_inner; ++di)
2506 const Number *in_ = in + di * dofs_per_component;
2507 Number *out_ = out + di * dofs_per_component;
2508 evaluator.template hessians<0, true, false>(in_, out_);
2510 evaluator.template hessians<1, true, false>(out_, out_);
2512 evaluator.template hessians<2, true, false>(out_, out_);
2514 if (dyadic_coefficients)
2516 const auto n_coeff_components =
2517 n_desired_components * n_desired_components;
2518 if (n_desired_components == dim)
2520 for (
unsigned int q = 0; q < dofs_per_component; ++q)
2521 vmult<dim>(&inv_coefficient[q * n_coeff_components],
2524 dofs_per_component);
2528 for (
unsigned int q = 0; q < dofs_per_component; ++q)
2529 vmult<-1>(&inv_coefficient[q * n_coeff_components],
2533 n_desired_components);
2537 for (
unsigned int q = 0; q < dofs_per_component; ++q)
2538 out[q] *= inv_coefficient[q];
2540 for (
unsigned int di = 0; di < n_comp_inner; ++di)
2542 Number *out_ = out + di * dofs_per_component;
2544 evaluator.template hessians<2, false, false>(out_, out_);
2546 evaluator.template hessians<1, false, false>(out_, out_);
2547 evaluator.template hessians<0, false, false>(out_, out_);
2550 in += dofs_per_component;
2551 out += dofs_per_component;
2552 inv_coefficient += shift_coefficient;
2559 template <
int n_components>
2561 vmult(
const Number *inverse_coefficients,
2564 const unsigned int dofs_per_component,
2565 const unsigned int n_given_components = 0)
2567 const unsigned int n_desired_components =
2568 (n_components > -1) ? n_components : n_given_components;
2570 std::array<Number, dim + 2> tmp = {};
2571 Assert(n_desired_components <= dim + 2,
2573 "Number of components larger than dim+2 not supported."));
2575 for (
unsigned int d = 0; d < n_desired_components; ++d)
2576 tmp[d] = src[d * dofs_per_component];
2578 for (
unsigned int d1 = 0; d1 < n_desired_components; ++d1)
2580 const Number *inv_coeff_row =
2581 &inverse_coefficients[d1 * n_desired_components];
2582 Number sum = inv_coeff_row[0] * tmp[0];
2583 for (
unsigned int d2 = 1; d2 < n_desired_components; ++d2)
2584 sum += inv_coeff_row[d2] * tmp[d2];
2585 dst[d1 * dofs_per_component] = sum;
2598 template <
int dim,
typename Number>
2601 template <
int fe_degree,
int n_q_po
ints_1d>
2603 run(
const unsigned int n_desired_components,
2605 const Number *in_array,
2608 static const bool do_inplace =
2609 fe_degree > -1 && (fe_degree + 1 == n_q_points_1d);
2615 const auto &inverse_shape =
2620 const std::size_t dofs_per_component =
2623 const std::size_t n_q_points = do_inplace ?
2641 for (
unsigned int d = 0; d < n_desired_components; ++d)
2643 const Number *in = in_array + d * n_q_points;
2644 Number *out = out_array + d * dofs_per_component;
2647 auto *temp_2 = do_inplace ?
2649 (temp_1 +
std::max(n_q_points, dofs_per_component));
2653 evaluator.template hessians<2, false, false>(in, temp_1);
2654 evaluator.template hessians<1, false, false>(temp_1, temp_2);
2655 evaluator.template hessians<0, false, false>(temp_2, out);
2659 evaluator.template hessians<1, false, false>(in, temp_1);
2660 evaluator.template hessians<0, false, false>(temp_1, out);
2663 evaluator.template hessians<0, false, false>(in, out);
value_type * data() const noexcept
ScalarNumber shape_info_number_type
const ShapeInfoType & get_shape_info() const
Number JxW(const unsigned int q_point) const
const Number * begin_gradients() const
ArrayView< Number > get_scratch_data() const
const Number * begin_values() const
const Number * begin_hessians() const
#define DEAL_II_ALWAYS_INLINE
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
@ tensor_symmetric_no_collocation
@ tensor_symmetric_plus_dg0
std::vector< index_type > data
EvaluationFlags
The EvaluationFlags enum.
constexpr T pow(const T base, const int iexp)
void evaluate_hessians_collocation(const unsigned int n_components, FEEvaluationData< dim, Number, false > &fe_eval)
constexpr bool use_collocation_evaluation(const unsigned int fe_degree, const unsigned int n_q_points_1d)
void integrate_gradients_collocation(const MatrixFreeFunctions::UnivariateShapeData< Number2 > &shape, Number *values, const Number *gradients, const bool add_into_values_array)
void evaluate_hessians_slow(const unsigned int n_components, const Number *values_dofs, FEEvaluationData< dim, Number, false > &fe_eval)
std::enable_if_t<(variant==evaluate_general), void > apply_matrix_vector_product(const Number2 *matrix, const Number *in, Number *out)
void integrate_hessians_collocation(const unsigned int n_components, FEEvaluationData< dim, Number, false > &fe_eval, const bool add_into_values_array)
void evaluate_gradients_collocation(const MatrixFreeFunctions::UnivariateShapeData< Number2 > &shape, const Number *values, Number *gradients)
void integrate_hessians_slow(const unsigned int n_components, const FEEvaluationData< dim, Number, false > &fe_eval, Number *values_dofs, const bool add_into_values_array)
static const unsigned int invalid_unsigned_int
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
typename FEEvaluationData< dim, Number, false >::shape_info_number_type Number2
static bool run(const unsigned int n_components, const FEEvaluationData< dim, Number, false > &fe_eval, const Number *in_array, Number *out_array)
typename FEEvaluationData< dim, Number, false >::shape_info_number_type Number2
static bool run(const unsigned int n_desired_components, const FEEvaluationData< dim, Number, false > &fe_eval, const ArrayView< const Number > &inverse_coefficients, const bool dyadic_coefficients, const Number *in_array, Number *out_array)
static void vmult(const Number *inverse_coefficients, const Number *src, Number *dst, const unsigned int dofs_per_component, const unsigned int n_given_components=0)
static void do_backward(const unsigned int n_components, const AlignedVector< Number2 > &transformation_matrix, const bool add_into_result, Number *values_in, Number *values_out, const unsigned int basis_size_1_variable=numbers::invalid_unsigned_int, const unsigned int basis_size_2_variable=numbers::invalid_unsigned_int)
static void do_forward(const unsigned int n_components, const AlignedVector< Number2 > &transformation_matrix, const Number *values_in, Number *values_out, const unsigned int basis_size_1_variable=numbers::invalid_unsigned_int, const unsigned int basis_size_2_variable=numbers::invalid_unsigned_int)
static void do_mass(const unsigned int n_components, const AlignedVector< Number2 > &transformation_matrix, const AlignedVector< Number > &coefficients, const Number *values_in, Number *scratch_data, Number *values_out)
static void evaluate(const unsigned int n_components, const EvaluationFlags::EvaluationFlags evaluation_flag, const Number *values_dofs, FEEvaluationData< dim, Number, false > &fe_eval)
static void integrate(const unsigned int n_components, const EvaluationFlags::EvaluationFlags integration_flag, Number *values_dofs, FEEvaluationData< dim, Number, false > &fe_eval, const bool add_into_values_array)
typename FEEvaluationData< dim, Number, false >::shape_info_number_type Number2
static void evaluate_or_integrate(const unsigned int n_components, const EvaluationFlags::EvaluationFlags evaluation_flag, OtherNumber *values_dofs, FEEvaluationData< dim, Number, false > &fe_eval, const bool sum_into_values_array)
static void evaluate_or_integrate(const unsigned int n_components, const EvaluationFlags::EvaluationFlags evaluation_flag, Number *values_dofs, FEEvaluationData< dim, Number, false > &fe_eval, const bool sum_into_values_array, std::bool_constant< true >)
static bool run(const unsigned int n_components, const EvaluationFlags::EvaluationFlags evaluation_flag, OtherNumber *values_dofs, FEEvaluationData< dim, Number, false > &fe_eval, const bool sum_into_values_array_in=false)
static void evaluate_or_integrate(const unsigned int n_components, const EvaluationFlags::EvaluationFlags evaluation_flag, const Number *values_dofs, FEEvaluationData< dim, Number, false > &fe_eval, const bool sum_into_values_array, std::bool_constant< false >)
typename FEEvaluationData< dim, Number, false >::shape_info_number_type Number2
static const EvaluatorVariant variant
typename FEEvaluationData< dim, Number, false >::shape_info_number_type Number2
EvaluatorTensorProduct< variant, dim, fe_degree+1, n_q_points_1d, Number, Number2 > Eval
static void integrate(const unsigned int n_components, const EvaluationFlags::EvaluationFlags integration_flag, Number *values_dofs_actual, FEEvaluationData< dim, Number, false > &fe_eval, const bool add_into_values_array)
static Eval create_evaluator_tensor_product(const MatrixFreeFunctions::UnivariateShapeData< Number2 > *univariate_shape_data)
static void evaluate(const unsigned int n_components, const EvaluationFlags::EvaluationFlags evaluation_flag, const Number *values_dofs_actual, FEEvaluationData< dim, Number, false > &fe_eval)
unsigned int dofs_per_component_on_cell
std::vector< UnivariateShapeData< Number > > data
AlignedVector< Number > shape_values
AlignedVector< Number > shape_values_eo
AlignedVector< Number > shape_hessians_eo
AlignedVector< Number > shape_gradients_collocation_eo
unsigned int n_q_points_1d
AlignedVector< Number > shape_gradients_eo
AlignedVector< Number > shape_hessians
AlignedVector< Number > shape_gradients