17 #ifndef dealii_matrix_free_tensor_product_kernels_h 18 #define dealii_matrix_free_tensor_product_kernels_h 20 #include <deal.II/base/config.h> 22 #include <deal.II/base/aligned_vector.h> 23 #include <deal.II/base/utilities.h> 26 DEAL_II_NAMESPACE_OPEN
95 typename Number2 = Number>
130 static constexpr
unsigned int n_rows_of_product =
132 static constexpr
unsigned int n_columns_of_product =
140 : shape_values(nullptr)
141 , shape_gradients(nullptr)
142 , shape_hessians(nullptr)
151 const unsigned int dummy1 = 0,
152 const unsigned int dummy2 = 0)
153 : shape_values(shape_values.begin())
154 , shape_gradients(shape_gradients.begin())
155 , shape_hessians(shape_hessians.begin())
162 shape_values.
size() == n_rows * n_columns ||
163 shape_values.
size() == 3 * n_rows,
166 shape_gradients.
size() == n_rows * n_columns,
169 shape_hessians.
size() == n_rows * n_columns,
175 template <
int direction,
bool contract_over_rows,
bool add>
177 values(
const Number in[], Number out[])
const 179 apply<direction, contract_over_rows, add>(shape_values, in, out);
182 template <
int direction,
bool contract_over_rows,
bool add>
184 gradients(
const Number in[], Number out[])
const 186 apply<direction, contract_over_rows, add>(shape_gradients, in, out);
189 template <
int direction,
bool contract_over_rows,
bool add>
191 hessians(
const Number in[], Number out[])
const 193 apply<direction, contract_over_rows, add>(shape_hessians, in, out);
196 template <
int direction,
bool contract_over_rows,
bool add>
198 values_one_line(
const Number in[], Number out[])
const 201 apply<direction, contract_over_rows, add, true>(shape_values, in, out);
204 template <
int direction,
bool contract_over_rows,
bool add>
206 gradients_one_line(
const Number in[], Number out[])
const 209 apply<direction, contract_over_rows, add, true>(shape_gradients, in, out);
212 template <
int direction,
bool contract_over_rows,
bool add>
214 hessians_one_line(
const Number in[], Number out[])
const 217 apply<direction, contract_over_rows, add, true>(shape_hessians, in, out);
244 template <
int direction,
245 bool contract_over_rows,
247 bool one_line =
false>
249 apply(
const Number2 *DEAL_II_RESTRICT shape_data,
282 template <
int face_direction,
283 bool contract_onto_face,
287 apply_face(
const Number *DEAL_II_RESTRICT in,
288 Number *DEAL_II_RESTRICT out)
const;
290 const Number2 *shape_values;
291 const Number2 *shape_gradients;
292 const Number2 *shape_hessians;
302 template <
int direction,
bool contract_over_rows,
bool add,
bool one_line>
309 Number2>::apply(
const Number2 *DEAL_II_RESTRICT
314 static_assert(one_line ==
false || direction == dim - 1,
315 "Single-line evaluation only works for direction=dim-1.");
316 Assert(shape_data !=
nullptr,
318 "The given array shape_data must not be the null pointer!"));
319 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
321 ExcMessage(
"In-place operation only supported for " 322 "n_rows==n_columns or single-line interpolation"));
324 constexpr
int mm = contract_over_rows ? n_rows : n_columns,
325 nn = contract_over_rows ? n_columns : n_rows;
328 constexpr
int n_blocks1 = one_line ? 1 : stride;
329 constexpr
int n_blocks2 =
330 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
332 for (
int i2 = 0; i2 < n_blocks2; ++i2)
334 for (
int i1 = 0; i1 < n_blocks1; ++i1)
337 for (
int i = 0; i < mm; ++i)
338 x[i] = in[stride * i];
339 for (
int col = 0; col < nn; ++col)
342 if (contract_over_rows ==
true)
343 val0 = shape_data[col];
345 val0 = shape_data[col * n_columns];
346 Number res0 = val0 * x[0];
347 for (
int i = 1; i < mm; ++i)
349 if (contract_over_rows ==
true)
350 val0 = shape_data[i * n_columns + col];
352 val0 = shape_data[col * n_columns + i];
356 out[stride * col] = res0;
358 out[stride * col] += res0;
361 if (one_line ==
false)
367 if (one_line ==
false)
369 in += stride * (mm - 1);
370 out += stride * (nn - 1);
382 template <
int face_direction,
383 bool contract_onto_face,
392 Number2>::apply_face(
const Number *DEAL_II_RESTRICT in,
393 Number *DEAL_II_RESTRICT
396 static_assert(dim > 0 && dim < 4,
"Only dim=1,2,3 supported");
397 static_assert(max_derivative >= 0 && max_derivative < 3,
398 "Only derivative orders 0-2 implemented");
399 Assert(shape_values !=
nullptr,
401 "The given array shape_values must not be the null pointer."));
403 constexpr
int n_blocks1 = dim > 1 ? n_rows : 1;
404 constexpr
int n_blocks2 = dim > 2 ? n_rows : 1;
409 const Number *DEAL_II_RESTRICT shape_values = this->shape_values;
411 for (
int i2 = 0; i2 < n_blocks2; ++i2)
413 for (
int i1 = 0; i1 < n_blocks1; ++i1)
415 if (contract_onto_face ==
true)
417 Number res0 = shape_values[0] * in[0];
419 if (max_derivative > 0)
420 res1 = shape_values[n_rows] * in[0];
421 if (max_derivative > 1)
422 res2 = shape_values[2 * n_rows] * in[0];
423 for (
int ind = 1; ind < n_rows; ++ind)
425 res0 += shape_values[ind] * in[stride * ind];
426 if (max_derivative > 0)
427 res1 += shape_values[ind + n_rows] * in[stride * ind];
428 if (max_derivative > 1)
429 res2 += shape_values[ind + 2 * n_rows] * in[stride * ind];
434 if (max_derivative > 0)
435 out[out_stride] = res1;
436 if (max_derivative > 1)
437 out[2 * out_stride] = res2;
442 if (max_derivative > 0)
443 out[out_stride] += res1;
444 if (max_derivative > 1)
445 out[2 * out_stride] += res2;
450 for (
int col = 0; col < n_rows; ++col)
453 out[col * stride] = shape_values[col] * in[0];
455 out[col * stride] += shape_values[col] * in[0];
456 if (max_derivative > 0)
458 shape_values[col + n_rows] * in[out_stride];
459 if (max_derivative > 1)
461 shape_values[col + 2 * n_rows] * in[2 * out_stride];
468 switch (face_direction)
471 in += contract_onto_face ? n_rows : 1;
472 out += contract_onto_face ? 1 : n_rows;
482 if (contract_onto_face)
496 if (face_direction == 1 && dim == 3)
499 if (contract_onto_face)
501 in += n_rows * (n_rows - 1);
502 out -= n_rows * n_rows - 1;
506 out += n_rows * (n_rows - 1);
507 in -= n_rows * n_rows - 1;
528 template <
int dim,
typename Number,
typename Number2>
531 static constexpr
unsigned int n_rows_of_product =
533 static constexpr
unsigned int n_columns_of_product =
541 : shape_values(nullptr)
542 , shape_gradients(nullptr)
543 , shape_hessians(nullptr)
544 , n_rows(
numbers::invalid_unsigned_int)
545 , n_columns(
numbers::invalid_unsigned_int)
554 const unsigned int n_rows,
555 const unsigned int n_columns)
556 : shape_values(shape_values.begin())
557 , shape_gradients(shape_gradients.begin())
558 , shape_hessians(shape_hessians.begin())
560 , n_columns(n_columns)
567 shape_values.
size() == n_rows * n_columns ||
568 shape_values.
size() == n_rows * 3,
571 shape_gradients.
size() == n_rows * n_columns,
574 shape_hessians.
size() == n_rows * n_columns,
578 template <
int direction,
bool contract_over_rows,
bool add>
580 values(
const Number *in, Number *out)
const 582 apply<direction, contract_over_rows, add>(shape_values, in, out);
585 template <
int direction,
bool contract_over_rows,
bool add>
587 gradients(
const Number *in, Number *out)
const 589 apply<direction, contract_over_rows, add>(shape_gradients, in, out);
592 template <
int direction,
bool contract_over_rows,
bool add>
594 hessians(
const Number *in, Number *out)
const 596 apply<direction, contract_over_rows, add>(shape_hessians, in, out);
599 template <
int direction,
bool contract_over_rows,
bool add>
601 values_one_line(
const Number in[], Number out[])
const 604 apply<direction, contract_over_rows, add, true>(shape_values, in, out);
607 template <
int direction,
bool contract_over_rows,
bool add>
609 gradients_one_line(
const Number in[], Number out[])
const 612 apply<direction, contract_over_rows, add, true>(shape_gradients, in, out);
615 template <
int direction,
bool contract_over_rows,
bool add>
617 hessians_one_line(
const Number in[], Number out[])
const 620 apply<direction, contract_over_rows, add, true>(shape_hessians, in, out);
623 template <
int direction,
624 bool contract_over_rows,
626 bool one_line =
false>
628 apply(
const Number2 *DEAL_II_RESTRICT shape_data,
632 template <
int face_direction,
633 bool contract_onto_face,
637 apply_face(
const Number *DEAL_II_RESTRICT in,
638 Number *DEAL_II_RESTRICT out)
const;
640 const Number2 * shape_values;
641 const Number2 * shape_gradients;
642 const Number2 * shape_hessians;
643 const unsigned int n_rows;
644 const unsigned int n_columns;
649 template <
int dim,
typename Number,
typename Number2>
650 template <
int direction,
bool contract_over_rows,
bool add,
bool one_line>
652 EvaluatorTensorProduct<evaluate_general, dim, 0, 0, Number, Number2>::apply(
653 const Number2 *DEAL_II_RESTRICT shape_data,
657 static_assert(one_line ==
false || direction == dim - 1,
658 "Single-line evaluation only works for direction=dim-1.");
659 Assert(shape_data !=
nullptr,
661 "The given array shape_data must not be the null pointer!"));
662 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
664 ExcMessage(
"In-place operation only supported for " 665 "n_rows==n_columns or single-line interpolation"));
667 const int mm = contract_over_rows ? n_rows : n_columns,
668 nn = contract_over_rows ? n_columns : n_rows;
671 direction == 0 ? 1 : Utilities::fixed_power<direction>(n_columns);
672 const int n_blocks1 = one_line ? 1 : stride;
673 const int n_blocks2 = direction >= dim - 1 ?
678 for (
int i2 = 0; i2 < n_blocks2; ++i2)
680 for (
int i1 = 0; i1 < n_blocks1; ++i1)
683 for (
int i = 0; i < mm; ++i)
684 x[i] = in[stride * i];
685 for (
int col = 0; col < nn; ++col)
688 if (contract_over_rows ==
true)
689 val0 = shape_data[col];
691 val0 = shape_data[col * n_columns];
692 Number res0 = val0 * x[0];
693 for (
int i = 1; i < mm; ++i)
695 if (contract_over_rows ==
true)
696 val0 = shape_data[i * n_columns + col];
698 val0 = shape_data[col * n_columns + i];
702 out[stride * col] = res0;
704 out[stride * col] += res0;
707 if (one_line ==
false)
713 if (one_line ==
false)
715 in += stride * (mm - 1);
716 out += stride * (nn - 1);
723 template <
int dim,
typename Number,
typename Number2>
724 template <
int face_direction,
725 bool contract_onto_face,
729 EvaluatorTensorProduct<evaluate_general, dim, 0, 0, Number, Number2>::
730 apply_face(
const Number *DEAL_II_RESTRICT in,
731 Number *DEAL_II_RESTRICT out)
const 733 Assert(shape_values !=
nullptr,
735 "The given array shape_data must not be the null pointer!"));
736 static_assert(dim > 0 && dim < 4,
"Only dim=1,2,3 supported");
737 const int n_blocks1 = dim > 1 ? n_rows : 1;
738 const int n_blocks2 = dim > 2 ? n_rows : 1;
742 face_direction > 0 ? Utilities::fixed_power<face_direction>(n_rows) : 1;
743 const int out_stride =
746 for (
int i2 = 0; i2 < n_blocks2; ++i2)
748 for (
int i1 = 0; i1 < n_blocks1; ++i1)
750 if (contract_onto_face ==
true)
752 Number res0 = shape_values[0] * in[0];
754 if (max_derivative > 0)
755 res1 = shape_values[n_rows] * in[0];
756 if (max_derivative > 1)
757 res2 = shape_values[2 * n_rows] * in[0];
758 for (
unsigned int ind = 1; ind < n_rows; ++ind)
760 res0 += shape_values[ind] * in[stride * ind];
761 if (max_derivative > 0)
762 res1 += shape_values[ind + n_rows] * in[stride * ind];
763 if (max_derivative > 1)
764 res2 += shape_values[ind + 2 * n_rows] * in[stride * ind];
769 if (max_derivative > 0)
770 out[out_stride] = res1;
771 if (max_derivative > 1)
772 out[2 * out_stride] = res2;
777 if (max_derivative > 0)
778 out[out_stride] += res1;
779 if (max_derivative > 1)
780 out[2 * out_stride] += res2;
785 for (
unsigned int col = 0; col < n_rows; ++col)
788 out[col * stride] = shape_values[col] * in[0];
790 out[col * stride] += shape_values[col] * in[0];
791 if (max_derivative > 0)
793 shape_values[col + n_rows] * in[out_stride];
794 if (max_derivative > 1)
796 shape_values[col + 2 * n_rows] * in[2 * out_stride];
803 switch (face_direction)
806 in += contract_onto_face ? n_rows : 1;
807 out += contract_onto_face ? 1 : n_rows;
817 if (contract_onto_face)
831 if (face_direction == 1 && dim == 3)
834 if (contract_onto_face)
836 in += n_rows * (n_rows - 1);
837 out -= n_rows * n_rows - 1;
841 out += n_rows * (n_rows - 1);
842 in -= n_rows * n_rows - 1;
882 static constexpr
unsigned int n_rows_of_product =
884 static constexpr
unsigned int n_columns_of_product =
893 const unsigned int dummy1 = 0,
894 const unsigned int dummy2 = 0)
895 : shape_values(shape_values.begin())
896 , shape_gradients(shape_gradients.begin())
897 , shape_hessians(shape_hessians.begin())
900 shape_values.
size() == n_rows * n_columns,
903 shape_gradients.
size() == n_rows * n_columns,
906 shape_hessians.
size() == n_rows * n_columns,
912 template <
int direction,
bool contract_over_rows,
bool add>
914 values(
const Number in[], Number out[])
const;
916 template <
int direction,
bool contract_over_rows,
bool add>
918 gradients(
const Number in[], Number out[])
const;
920 template <
int direction,
bool contract_over_rows,
bool add>
922 hessians(
const Number in[], Number out[])
const;
924 const Number2 *shape_values;
925 const Number2 *shape_gradients;
926 const Number2 *shape_hessians;
954 template <
int direction,
bool contract_over_rows,
bool add>
961 Number2>::values(
const Number in[], Number out[])
const 965 constexpr
int mm = contract_over_rows ? n_rows : n_columns,
966 nn = contract_over_rows ? n_columns : n_rows;
967 constexpr
int n_cols = nn / 2;
968 constexpr
int mid = mm / 2;
971 constexpr
int n_blocks1 = stride;
972 constexpr
int n_blocks2 =
973 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
975 for (
int i2 = 0; i2 < n_blocks2; ++i2)
977 for (
int i1 = 0; i1 < n_blocks1; ++i1)
979 for (
int col = 0; col < n_cols; ++col)
982 Number in0, in1, res0, res1;
983 if (contract_over_rows ==
true)
985 val0 = shape_values[col];
986 val1 = shape_values[nn - 1 - col];
990 val0 = shape_values[col * n_columns];
991 val1 = shape_values[(col + 1) * n_columns - 1];
996 in1 = in[stride * (mm - 1)];
1001 for (
int ind = 1; ind < mid; ++ind)
1003 if (contract_over_rows ==
true)
1005 val0 = shape_values[ind * n_columns + col];
1006 val1 = shape_values[ind * n_columns + nn - 1 - col];
1010 val0 = shape_values[col * n_columns + ind];
1012 shape_values[(col + 1) * n_columns - 1 - ind];
1014 in0 = in[stride * ind];
1015 in1 = in[stride * (mm - 1 - ind)];
1023 res0 = res1 = Number();
1024 if (contract_over_rows ==
true)
1028 val0 = shape_values[mid * n_columns + col];
1029 in1 = val0 * in[stride * mid];
1036 if (mm % 2 == 1 && nn % 2 == 0)
1038 val0 = shape_values[col * n_columns + mid];
1039 in1 = val0 * in[stride * mid];
1046 out[stride * col] = res0;
1047 out[stride * (nn - 1 - col)] = res1;
1051 out[stride * col] += res0;
1052 out[stride * (nn - 1 - col)] += res1;
1055 if (contract_over_rows ==
true && nn % 2 == 1 && mm % 2 == 1)
1058 out[stride * n_cols] = in[stride * mid];
1060 out[stride * n_cols] += in[stride * mid];
1062 else if (contract_over_rows ==
true && nn % 2 == 1)
1065 Number2 val0 = shape_values[n_cols];
1068 res0 = val0 * (in[0] + in[stride * (mm - 1)]);
1069 for (
int ind = 1; ind < mid; ++ind)
1071 val0 = shape_values[ind * n_columns + n_cols];
1072 res0 += val0 * (in[stride * ind] +
1073 in[stride * (mm - 1 - ind)]);
1079 out[stride * n_cols] = res0;
1081 out[stride * n_cols] += res0;
1083 else if (contract_over_rows ==
false && nn % 2 == 1)
1088 Number2 val0 = shape_values[n_cols * n_columns];
1089 res0 = val0 * (in[0] + in[stride * (mm - 1)]);
1090 for (
int ind = 1; ind < mid; ++ind)
1092 val0 = shape_values[n_cols * n_columns + ind];
1093 Number in1 = val0 * (in[stride * ind] +
1094 in[stride * (mm - 1 - ind)]);
1098 res0 += in[stride * mid];
1103 out[stride * n_cols] = res0;
1105 out[stride * n_cols] += res0;
1111 in += stride * (mm - 1);
1112 out += stride * (nn - 1);
1142 template <
int direction,
bool contract_over_rows,
bool add>
1149 Number2>::gradients(
const Number in[],
1154 constexpr
int mm = contract_over_rows ? n_rows : n_columns,
1155 nn = contract_over_rows ? n_columns : n_rows;
1156 constexpr
int n_cols = nn / 2;
1157 constexpr
int mid = mm / 2;
1160 constexpr
int n_blocks1 = stride;
1161 constexpr
int n_blocks2 =
1162 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
1164 for (
int i2 = 0; i2 < n_blocks2; ++i2)
1166 for (
int i1 = 0; i1 < n_blocks1; ++i1)
1168 for (
int col = 0; col < n_cols; ++col)
1171 Number in0, in1, res0, res1;
1172 if (contract_over_rows ==
true)
1174 val0 = shape_gradients[col];
1175 val1 = shape_gradients[nn - 1 - col];
1179 val0 = shape_gradients[col * n_columns];
1180 val1 = shape_gradients[(nn - col - 1) * n_columns];
1185 in1 = in[stride * (mm - 1)];
1190 for (
int ind = 1; ind < mid; ++ind)
1192 if (contract_over_rows ==
true)
1194 val0 = shape_gradients[ind * n_columns + col];
1196 shape_gradients[ind * n_columns + nn - 1 - col];
1200 val0 = shape_gradients[col * n_columns + ind];
1202 shape_gradients[(nn - col - 1) * n_columns + ind];
1204 in0 = in[stride * ind];
1205 in1 = in[stride * (mm - 1 - ind)];
1213 res0 = res1 = Number();
1216 if (contract_over_rows ==
true)
1217 val0 = shape_gradients[mid * n_columns + col];
1219 val0 = shape_gradients[col * n_columns + mid];
1220 in1 = val0 * in[stride * mid];
1226 out[stride * col] = res0;
1227 out[stride * (nn - 1 - col)] = res1;
1231 out[stride * col] += res0;
1232 out[stride * (nn - 1 - col)] += res1;
1239 if (contract_over_rows ==
true)
1240 val0 = shape_gradients[n_cols];
1242 val0 = shape_gradients[n_cols * n_columns];
1243 res0 = val0 * (in[0] - in[stride * (mm - 1)]);
1244 for (
int ind = 1; ind < mid; ++ind)
1246 if (contract_over_rows ==
true)
1247 val0 = shape_gradients[ind * n_columns + n_cols];
1249 val0 = shape_gradients[n_cols * n_columns + ind];
1251 val0 * (in[stride * ind] - in[stride * (mm - 1 - ind)]);
1255 out[stride * n_cols] = res0;
1257 out[stride * n_cols] += res0;
1263 in += stride * (mm - 1);
1264 out += stride * (nn - 1);
1278 template <
int direction,
bool contract_over_rows,
bool add>
1285 Number2>::hessians(
const Number in[],
1290 constexpr
int mm = contract_over_rows ? n_rows : n_columns;
1291 constexpr
int nn = contract_over_rows ? n_columns : n_rows;
1292 constexpr
int n_cols = nn / 2;
1293 constexpr
int mid = mm / 2;
1296 constexpr
int n_blocks1 = stride;
1297 constexpr
int n_blocks2 =
1298 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
1300 for (
int i2 = 0; i2 < n_blocks2; ++i2)
1302 for (
int i1 = 0; i1 < n_blocks1; ++i1)
1304 for (
int col = 0; col < n_cols; ++col)
1307 Number in0, in1, res0, res1;
1308 if (contract_over_rows ==
true)
1310 val0 = shape_hessians[col];
1311 val1 = shape_hessians[nn - 1 - col];
1315 val0 = shape_hessians[col * n_columns];
1316 val1 = shape_hessians[(col + 1) * n_columns - 1];
1321 in1 = in[stride * (mm - 1)];
1326 for (
int ind = 1; ind < mid; ++ind)
1328 if (contract_over_rows ==
true)
1330 val0 = shape_hessians[ind * n_columns + col];
1332 shape_hessians[ind * n_columns + nn - 1 - col];
1336 val0 = shape_hessians[col * n_columns + ind];
1338 shape_hessians[(col + 1) * n_columns - 1 - ind];
1340 in0 = in[stride * ind];
1341 in1 = in[stride * (mm - 1 - ind)];
1349 res0 = res1 = Number();
1352 if (contract_over_rows ==
true)
1353 val0 = shape_hessians[mid * n_columns + col];
1355 val0 = shape_hessians[col * n_columns + mid];
1356 in1 = val0 * in[stride * mid];
1362 out[stride * col] = res0;
1363 out[stride * (nn - 1 - col)] = res1;
1367 out[stride * col] += res0;
1368 out[stride * (nn - 1 - col)] += res1;
1375 if (contract_over_rows ==
true)
1376 val0 = shape_hessians[n_cols];
1378 val0 = shape_hessians[n_cols * n_columns];
1381 res0 = val0 * (in[0] + in[stride * (mm - 1)]);
1382 for (
int ind = 1; ind < mid; ++ind)
1384 if (contract_over_rows ==
true)
1385 val0 = shape_hessians[ind * n_columns + n_cols];
1387 val0 = shape_hessians[n_cols * n_columns + ind];
1388 Number in1 = val0 * (in[stride * ind] +
1389 in[stride * (mm - 1 - ind)]);
1397 if (contract_over_rows ==
true)
1398 val0 = shape_hessians[mid * n_columns + n_cols];
1400 val0 = shape_hessians[n_cols * n_columns + mid];
1401 res0 += val0 * in[stride * mid];
1404 out[stride * n_cols] = res0;
1406 out[stride * n_cols] += res0;
1412 in += stride * (mm - 1);
1413 out += stride * (nn - 1);
1462 static constexpr
unsigned int n_rows_of_product =
1464 static constexpr
unsigned int n_columns_of_product =
1473 : shape_values(nullptr)
1474 , shape_gradients(nullptr)
1475 , shape_hessians(nullptr)
1483 : shape_values(shape_values.begin())
1484 , shape_gradients(nullptr)
1485 , shape_hessians(nullptr)
1497 const unsigned int dummy1 = 0,
1498 const unsigned int dummy2 = 0)
1499 : shape_values(shape_values.begin())
1500 , shape_gradients(shape_gradients.begin())
1501 , shape_hessians(shape_hessians.begin())
1505 if (!shape_values.
empty())
1507 if (!shape_gradients.
empty())
1509 if (!shape_hessians.
empty())
1515 template <
int direction,
bool contract_over_rows,
bool add>
1517 values(
const Number in[], Number out[])
const 1520 apply<direction, contract_over_rows, add, 0>(shape_values, in, out);
1523 template <
int direction,
bool contract_over_rows,
bool add>
1525 gradients(
const Number in[], Number out[])
const 1528 apply<direction, contract_over_rows, add, 1>(shape_gradients, in, out);
1531 template <
int direction,
bool contract_over_rows,
bool add>
1533 hessians(
const Number in[], Number out[])
const 1536 apply<direction, contract_over_rows, add, 2>(shape_hessians, in, out);
1539 template <
int direction,
bool contract_over_rows,
bool add>
1541 values_one_line(
const Number in[], Number out[])
const 1544 apply<direction, contract_over_rows, add, 0, true>(shape_values, in, out);
1547 template <
int direction,
bool contract_over_rows,
bool add>
1549 gradients_one_line(
const Number in[], Number out[])
const 1552 apply<direction, contract_over_rows, add, 1, true>(shape_gradients,
1557 template <
int direction,
bool contract_over_rows,
bool add>
1559 hessians_one_line(
const Number in[], Number out[])
const 1562 apply<direction, contract_over_rows, add, 2, true>(shape_hessians,
1595 template <
int direction,
1596 bool contract_over_rows,
1599 bool one_line =
false>
1601 apply(
const Number2 *DEAL_II_RESTRICT shape_data,
1605 const Number2 *shape_values;
1606 const Number2 *shape_gradients;
1607 const Number2 *shape_hessians;
1617 template <
int direction,
1618 bool contract_over_rows,
1628 Number2>::apply(
const Number2 *DEAL_II_RESTRICT shapes,
1632 static_assert(type < 3,
"Only three variants type=0,1,2 implemented");
1633 static_assert(one_line ==
false || direction == dim - 1,
1634 "Single-line evaluation only works for direction=dim-1.");
1635 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
1637 ExcMessage(
"In-place operation only supported for " 1638 "n_rows==n_columns or single-line interpolation"));
1644 constexpr
int nn = contract_over_rows ? n_columns : n_rows;
1645 constexpr
int mm = contract_over_rows ? n_rows : n_columns;
1646 constexpr
int n_cols = nn / 2;
1647 constexpr
int mid = mm / 2;
1650 constexpr
int n_blocks1 = one_line ? 1 : stride;
1651 constexpr
int n_blocks2 =
1652 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
1654 constexpr
int offset = (n_columns + 1) / 2;
1660 for (
int i2 = 0; i2 < n_blocks2; ++i2)
1662 for (
int i1 = 0; i1 < n_blocks1; ++i1)
1664 Number xp[mid > 0 ? mid : 1], xm[mid > 0 ? mid : 1];
1665 for (
int i = 0; i < mid; ++i)
1667 if (contract_over_rows ==
true && type == 1)
1669 xp[i] = in[stride * i] - in[stride * (mm - 1 - i)];
1670 xm[i] = in[stride * i] + in[stride * (mm - 1 - i)];
1674 xp[i] = in[stride * i] + in[stride * (mm - 1 - i)];
1675 xm[i] = in[stride * i] - in[stride * (mm - 1 - i)];
1678 Number xmid = in[stride * mid];
1679 for (
int col = 0; col < n_cols; ++col)
1684 if (contract_over_rows ==
true)
1686 r0 = shapes[col] * xp[0];
1687 r1 = shapes[(n_rows - 1) * offset + col] * xm[0];
1691 r0 = shapes[col * offset] * xp[0];
1692 r1 = shapes[(n_rows - 1 - col) * offset] * xm[0];
1694 for (
int ind = 1; ind < mid; ++ind)
1696 if (contract_over_rows ==
true)
1698 r0 += shapes[ind * offset + col] * xp[ind];
1699 r1 += shapes[(n_rows - 1 - ind) * offset + col] *
1704 r0 += shapes[col * offset + ind] * xp[ind];
1705 r1 += shapes[(n_rows - 1 - col) * offset + ind] *
1712 if (mm % 2 == 1 && contract_over_rows ==
true)
1715 r1 += shapes[mid * offset + col] * xmid;
1717 r0 += shapes[mid * offset + col] * xmid;
1719 else if (mm % 2 == 1 && (nn % 2 == 0 || type > 0))
1720 r0 += shapes[col * offset + mid] * xmid;
1724 out[stride * col] = r0 + r1;
1725 if (type == 1 && contract_over_rows ==
false)
1726 out[stride * (nn - 1 - col)] = r1 - r0;
1728 out[stride * (nn - 1 - col)] = r0 - r1;
1732 out[stride * col] += r0 + r1;
1733 if (type == 1 && contract_over_rows ==
false)
1734 out[stride * (nn - 1 - col)] += r1 - r0;
1736 out[stride * (nn - 1 - col)] += r0 - r1;
1739 if (type == 0 && contract_over_rows ==
true && nn % 2 == 1 &&
1743 out[stride * n_cols] = shapes[mid * offset + n_cols] * xmid;
1745 out[stride * n_cols] += shapes[mid * offset + n_cols] * xmid;
1747 else if (contract_over_rows ==
true && nn % 2 == 1)
1752 r0 = shapes[n_cols] * xp[0];
1753 for (
int ind = 1; ind < mid; ++ind)
1754 r0 += shapes[ind * offset + n_cols] * xp[ind];
1758 if (type != 1 && mm % 2 == 1)
1759 r0 += shapes[mid * offset + n_cols] * xmid;
1762 out[stride * n_cols] = r0;
1764 out[stride * n_cols] += r0;
1766 else if (contract_over_rows ==
false && nn % 2 == 1)
1773 r0 = shapes[n_cols * offset] * xm[0];
1774 for (
int ind = 1; ind < mid; ++ind)
1775 r0 += shapes[n_cols * offset + ind] * xm[ind];
1779 r0 = shapes[n_cols * offset] * xp[0];
1780 for (
int ind = 1; ind < mid; ++ind)
1781 r0 += shapes[n_cols * offset + ind] * xp[ind];
1787 if ((type == 0 || type == 2) && mm % 2 == 1)
1788 r0 += shapes[n_cols * offset + mid] * xmid;
1791 out[stride * n_cols] = r0;
1793 out[stride * n_cols] += r0;
1795 if (one_line ==
false)
1801 if (one_line ==
false)
1803 in += stride * (mm - 1);
1804 out += stride * (nn - 1);
1851 static constexpr
unsigned int n_rows_of_product =
1853 static constexpr
unsigned int n_columns_of_product =
1862 : shape_values(nullptr)
1863 , shape_gradients(nullptr)
1864 , shape_hessians(nullptr)
1872 : shape_values(shape_values.begin())
1873 , shape_gradients(nullptr)
1874 , shape_hessians(nullptr)
1884 const unsigned int dummy1 = 0,
1885 const unsigned int dummy2 = 0)
1886 : shape_values(shape_values.begin())
1887 , shape_gradients(shape_gradients.begin())
1888 , shape_hessians(shape_hessians.begin())
1894 template <
int direction,
bool contract_over_rows,
bool add>
1896 values(
const Number in[], Number out[])
const 1899 apply<direction, contract_over_rows, add, 0>(shape_values, in, out);
1902 template <
int direction,
bool contract_over_rows,
bool add>
1904 gradients(
const Number in[], Number out[])
const 1907 apply<direction, contract_over_rows, add, 1>(shape_gradients, in, out);
1910 template <
int direction,
bool contract_over_rows,
bool add>
1912 hessians(
const Number in[], Number out[])
const 1915 apply<direction, contract_over_rows, add, 0>(shape_hessians, in, out);
1918 template <
int direction,
bool contract_over_rows,
bool add>
1920 values_one_line(
const Number in[], Number out[])
const 1923 apply<direction, contract_over_rows, add, 0, true>(shape_values, in, out);
1926 template <
int direction,
bool contract_over_rows,
bool add>
1928 gradients_one_line(
const Number in[], Number out[])
const 1931 apply<direction, contract_over_rows, add, 1, true>(shape_gradients,
1936 template <
int direction,
bool contract_over_rows,
bool add>
1938 hessians_one_line(
const Number in[], Number out[])
const 1941 apply<direction, contract_over_rows, add, 0, true>(shape_hessians,
1973 template <
int direction,
1974 bool contract_over_rows,
1977 bool one_line =
false>
1979 apply(
const Number2 *DEAL_II_RESTRICT shape_data,
1983 const Number2 *shape_values;
1984 const Number2 *shape_gradients;
1985 const Number2 *shape_hessians;
1995 template <
int direction,
1996 bool contract_over_rows,
2006 Number2>::apply(
const Number2 *DEAL_II_RESTRICT shapes,
2010 static_assert(one_line ==
false || direction == dim - 1,
2011 "Single-line evaluation only works for direction=dim-1.");
2013 type == 0 || type == 1,
2014 "Only types 0 and 1 implemented for evaluate_symmetric_hierarchical.");
2015 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
2017 ExcMessage(
"In-place operation only supported for " 2018 "n_rows==n_columns or single-line interpolation"));
2024 constexpr
int nn = contract_over_rows ? n_columns : n_rows;
2025 constexpr
int mm = contract_over_rows ? n_rows : n_columns;
2026 constexpr
int n_cols = nn / 2;
2027 constexpr
int mid = mm / 2;
2030 constexpr
int n_blocks1 = one_line ? 1 : stride;
2031 constexpr
int n_blocks2 =
2032 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
2038 for (
int i2 = 0; i2 < n_blocks2; ++i2)
2040 for (
int i1 = 0; i1 < n_blocks1; ++i1)
2042 if (contract_over_rows)
2045 for (
unsigned int i = 0; i < mm; ++i)
2046 x[i] = in[stride * i];
2047 for (
unsigned int col = 0; col < n_cols; ++col)
2052 r0 = shapes[col] * x[0];
2053 r1 = shapes[col + n_columns] * x[1];
2054 for (
unsigned int ind = 1; ind < mid; ++ind)
2057 shapes[col + 2 * ind * n_columns] * x[2 * ind];
2058 r1 += shapes[col + (2 * ind + 1) * n_columns] *
2065 r0 += shapes[col + (mm - 1) * n_columns] * x[mm - 1];
2068 out[stride * col] = r0 + r1;
2070 out[stride * (nn - 1 - col)] = r1 - r0;
2072 out[stride * (nn - 1 - col)] = r0 - r1;
2076 out[stride * col] += r0 + r1;
2078 out[stride * (nn - 1 - col)] += r1 - r0;
2080 out[stride * (nn - 1 - col)] += r0 - r1;
2086 const unsigned int shift = type == 1 ? 1 : 0;
2089 r0 = shapes[n_cols + shift * n_columns] * x[shift];
2090 for (
unsigned int ind = 1; ind < mid; ++ind)
2091 r0 += shapes[n_cols + (2 * ind + shift) * n_columns] *
2096 if (type != 1 && mm % 2 == 1)
2097 r0 += shapes[n_cols + (mm - 1) * n_columns] * x[mm - 1];
2099 out[stride * n_cols] = r0;
2101 out[stride * n_cols] += r0;
2106 Number xp[mid + 1], xm[mid > 0 ? mid : 1];
2107 for (
int i = 0; i < mid; ++i)
2110 xp[i] = in[stride * i] + in[stride * (mm - 1 - i)];
2111 xm[i] = in[stride * i] - in[stride * (mm - 1 - i)];
2115 xp[i] = in[stride * i] - in[stride * (mm - 1 - i)];
2116 xm[i] = in[stride * i] + in[stride * (mm - 1 - i)];
2119 xp[mid] = in[stride * mid];
2120 for (
unsigned int col = 0; col < n_cols; ++col)
2125 r0 = shapes[2 * col * n_columns] * xp[0];
2126 r1 = shapes[(2 * col + 1) * n_columns] * xm[0];
2127 for (
unsigned int ind = 1; ind < mid; ++ind)
2129 r0 += shapes[2 * col * n_columns + ind] * xp[ind];
2131 shapes[(2 * col + 1) * n_columns + ind] * xm[ind];
2140 shapes[(2 * col + 1) * n_columns + mid] * xp[mid];
2142 r0 += shapes[2 * col * n_columns + mid] * xp[mid];
2146 out[stride * (2 * col)] = r0;
2147 out[stride * (2 * col + 1)] = r1;
2151 out[stride * (2 * col)] += r0;
2152 out[stride * (2 * col + 1)] += r1;
2160 r0 = shapes[(nn - 1) * n_columns] * xp[0];
2161 for (
unsigned int ind = 1; ind < mid; ++ind)
2162 r0 += shapes[(nn - 1) * n_columns + ind] * xp[ind];
2166 if (mm % 2 == 1 && type == 0)
2167 r0 += shapes[(nn - 1) * n_columns + mid] * xp[mid];
2169 out[stride * (nn - 1)] = r0;
2171 out[stride * (nn - 1)] += r0;
2174 if (one_line ==
false)
2180 if (one_line ==
false)
2182 in += stride * (mm - 1);
2183 out += stride * (nn - 1);
2191 DEAL_II_NAMESPACE_CLOSE
static const unsigned int invalid_unsigned_int
#define AssertDimension(dim1, dim2)
EvaluatorTensorProduct(const AlignedVector< Number2 > &shape_values, const AlignedVector< Number2 > &shape_gradients, const AlignedVector< Number2 > &shape_hessians, const unsigned int dummy1=0, const unsigned int dummy2=0)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcNotInitialized()
EvaluatorTensorProduct(const AlignedVector< Number > &shape_values)
static ::ExceptionBase & ExcMessage(std::string arg1)
EvaluatorTensorProduct(const AlignedVector< Number2 > &shape_values, const AlignedVector< Number2 > &shape_gradients, const AlignedVector< Number2 > &shape_hessians, const unsigned int dummy1=0, const unsigned int dummy2=0)
#define Assert(cond, exc)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
constexpr unsigned int pow(const unsigned int base, const int iexp)
EvaluatorTensorProduct(const AlignedVector< Number2 > &shape_values, const AlignedVector< Number2 > &shape_gradients, const AlignedVector< Number2 > &shape_hessians, const unsigned int n_rows, const unsigned int n_columns)
EvaluatorTensorProduct(const AlignedVector< Number2 > &shape_values, const AlignedVector< Number2 > &shape_gradients, const AlignedVector< Number2 > &shape_hessians, const unsigned int dummy1=0, const unsigned int dummy2=0)
EvaluatorTensorProduct(const AlignedVector< Number2 > &shape_values)
EvaluatorTensorProduct(const AlignedVector< Number2 > &shape_values, const AlignedVector< Number2 > &shape_gradients, const AlignedVector< Number2 > &shape_hessians, const unsigned int dummy1=0, const unsigned int dummy2=0)
static ::ExceptionBase & ExcNotImplemented()