17 #ifndef dealii_matrix_free_tensor_product_kernels_h
18 #define dealii_matrix_free_tensor_product_kernels_h
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>
186 apply<direction, contract_over_rows, add>(shape_gradients, in, out);
189 template <
int direction,
bool contract_over_rows,
bool add>
193 apply<direction, contract_over_rows, add>(shape_hessians, in, out);
196 template <
int direction,
bool contract_over_rows,
bool add>
201 apply<direction, contract_over_rows, add, true>(shape_values, in, out);
204 template <
int direction,
bool contract_over_rows,
bool add>
209 apply<direction, contract_over_rows, add, true>(shape_gradients, in, out);
212 template <
int direction,
bool contract_over_rows,
bool add>
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>
282 template <
int face_direction,
283 bool contract_onto_face,
302 template <
int direction,
bool contract_over_rows,
bool add,
bool one_line>
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,
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;
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)
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>
589 apply<direction, contract_over_rows, add>(shape_gradients, in, out);
592 template <
int direction,
bool contract_over_rows,
bool add>
596 apply<direction, contract_over_rows, add>(shape_hessians, in, out);
599 template <
int direction,
bool contract_over_rows,
bool add>
604 apply<direction, contract_over_rows, add, true>(shape_values, in, out);
607 template <
int direction,
bool contract_over_rows,
bool add>
612 apply<direction, contract_over_rows, add, true>(shape_gradients, in, out);
615 template <
int direction,
bool contract_over_rows,
bool add>
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>
632 template <
int face_direction,
633 bool contract_onto_face,
649 template <
int dim,
typename Number,
typename Number2>
650 template <
int direction,
bool contract_over_rows,
bool add,
bool one_line>
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 ?
683 if (contract_over_rows && n_rows == 2)
685 const Number2 *shape_data_1 = shape_data + n_columns;
686 for (
int i2 = 0; i2 < n_blocks2; ++i2)
688 for (
int i1 = 0; i1 < n_blocks1; ++i1)
690 const Number x0 = in[0], x1 = in[stride];
691 for (
int col = 0; col < nn; ++col)
693 const Number result =
694 shape_data[col] * x0 + shape_data_1[col] * x1;
696 out[stride * col] = result;
698 out[stride * col] += result;
701 if (one_line ==
false)
707 if (one_line ==
false)
709 in += stride * (mm - 1);
710 out += stride * (nn - 1);
715 else if (contract_over_rows && n_rows == 3)
717 const Number2 *shape_data_1 = shape_data + n_columns;
718 const Number2 *shape_data_2 = shape_data + 2 * n_columns;
719 for (
int i2 = 0; i2 < n_blocks2; ++i2)
721 for (
int i1 = 0; i1 < n_blocks1; ++i1)
723 const Number x0 = in[0], x1 = in[stride], x2 = in[2 * stride];
724 for (
int col = 0; col < nn; ++col)
726 const Number result = shape_data[col] * x0 +
727 shape_data_1[col] * x1 +
728 shape_data_2[col] * x2;
730 out[stride * col] = result;
732 out[stride * col] += result;
735 if (one_line ==
false)
741 if (one_line ==
false)
743 in += stride * (mm - 1);
744 out += stride * (nn - 1);
750 for (
int i2 = 0; i2 < n_blocks2; ++i2)
752 for (
int i1 = 0; i1 < n_blocks1; ++i1)
755 for (
int i = 0; i < mm; ++i)
756 x[i] = in[stride * i];
757 for (
int col = 0; col < nn; ++col)
760 if (contract_over_rows ==
true)
761 val0 = shape_data[col];
763 val0 = shape_data[col * n_columns];
764 Number res0 = val0 * x[0];
765 for (
int i = 1; i < mm; ++i)
767 if (contract_over_rows ==
true)
768 val0 = shape_data[i * n_columns + col];
770 val0 = shape_data[col * n_columns + i];
774 out[stride * col] = res0;
776 out[stride * col] += res0;
779 if (one_line ==
false)
785 if (one_line ==
false)
787 in += stride * (mm - 1);
788 out += stride * (nn - 1);
795 template <
int dim,
typename Number,
typename Number2>
796 template <
int face_direction,
797 bool contract_onto_face,
805 Assert(shape_values !=
nullptr,
807 "The given array shape_data must not be the null pointer!"));
808 static_assert(dim > 0 && dim < 4,
"Only dim=1,2,3 supported");
809 const int n_blocks1 = dim > 1 ? n_rows : 1;
810 const int n_blocks2 = dim > 2 ? n_rows : 1;
814 face_direction > 0 ? Utilities::fixed_power<face_direction>(n_rows) : 1;
815 const int out_stride =
818 for (
int i2 = 0; i2 < n_blocks2; ++i2)
820 for (
int i1 = 0; i1 < n_blocks1; ++i1)
822 if (contract_onto_face ==
true)
824 Number res0 = shape_values[0] * in[0];
826 if (max_derivative > 0)
827 res1 = shape_values[n_rows] * in[0];
828 if (max_derivative > 1)
829 res2 = shape_values[2 * n_rows] * in[0];
830 for (
unsigned int ind = 1; ind < n_rows; ++ind)
832 res0 += shape_values[ind] * in[stride * ind];
833 if (max_derivative > 0)
834 res1 += shape_values[ind + n_rows] * in[stride * ind];
835 if (max_derivative > 1)
836 res2 += shape_values[ind + 2 * n_rows] * in[stride * ind];
841 if (max_derivative > 0)
842 out[out_stride] = res1;
843 if (max_derivative > 1)
844 out[2 * out_stride] = res2;
849 if (max_derivative > 0)
850 out[out_stride] += res1;
851 if (max_derivative > 1)
852 out[2 * out_stride] += res2;
857 for (
unsigned int col = 0; col < n_rows; ++col)
860 out[col * stride] = shape_values[col] * in[0];
862 out[col * stride] += shape_values[col] * in[0];
863 if (max_derivative > 0)
865 shape_values[col + n_rows] * in[out_stride];
866 if (max_derivative > 1)
868 shape_values[col + 2 * n_rows] * in[2 * out_stride];
875 switch (face_direction)
878 in += contract_onto_face ? n_rows : 1;
879 out += contract_onto_face ? 1 : n_rows;
889 if (contract_onto_face)
903 if (face_direction == 1 && dim == 3)
906 if (contract_onto_face)
908 in += n_rows * (n_rows - 1);
909 out -= n_rows * n_rows - 1;
913 out += n_rows * (n_rows - 1);
914 in -= n_rows * n_rows - 1;
954 static constexpr
unsigned int n_rows_of_product =
956 static constexpr
unsigned int n_columns_of_product =
965 const unsigned int dummy1 = 0,
966 const unsigned int dummy2 = 0)
967 : shape_values(shape_values.
begin())
968 , shape_gradients(shape_gradients.
begin())
969 , shape_hessians(shape_hessians.
begin())
972 shape_values.
size() == n_rows * n_columns,
975 shape_gradients.
size() == n_rows * n_columns,
978 shape_hessians.
size() == n_rows * n_columns,
984 template <
int direction,
bool contract_over_rows,
bool add>
986 values(
const Number in[], Number out[])
const;
988 template <
int direction,
bool contract_over_rows,
bool add>
990 gradients(
const Number in[], Number out[])
const;
992 template <
int direction,
bool contract_over_rows,
bool add>
994 hessians(
const Number in[], Number out[])
const;
1026 template <
int direction,
bool contract_over_rows,
bool add>
1033 Number2>::values(
const Number in[], Number out[])
const
1037 constexpr
int mm = contract_over_rows ? n_rows : n_columns,
1038 nn = contract_over_rows ? n_columns : n_rows;
1039 constexpr
int n_cols = nn / 2;
1040 constexpr
int mid = mm / 2;
1043 constexpr
int n_blocks1 = stride;
1044 constexpr
int n_blocks2 =
1045 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
1047 for (
int i2 = 0; i2 < n_blocks2; ++i2)
1049 for (
int i1 = 0; i1 < n_blocks1; ++i1)
1051 for (
int col = 0; col < n_cols; ++col)
1054 Number in0, in1, res0, res1;
1055 if (contract_over_rows ==
true)
1057 val0 = shape_values[col];
1058 val1 = shape_values[nn - 1 - col];
1062 val0 = shape_values[col * n_columns];
1063 val1 = shape_values[(col + 1) * n_columns - 1];
1068 in1 = in[stride * (mm - 1)];
1073 for (
int ind = 1; ind < mid; ++ind)
1075 if (contract_over_rows ==
true)
1077 val0 = shape_values[ind * n_columns + col];
1078 val1 = shape_values[ind * n_columns + nn - 1 - col];
1082 val0 = shape_values[col * n_columns + ind];
1084 shape_values[(col + 1) * n_columns - 1 - ind];
1086 in0 = in[stride * ind];
1087 in1 = in[stride * (mm - 1 - ind)];
1095 res0 = res1 = Number();
1096 if (contract_over_rows ==
true)
1100 val0 = shape_values[mid * n_columns + col];
1101 in1 = val0 * in[stride * mid];
1108 if (mm % 2 == 1 && nn % 2 == 0)
1110 val0 = shape_values[col * n_columns + mid];
1111 in1 = val0 * in[stride * mid];
1118 out[stride * col] = res0;
1119 out[stride * (nn - 1 - col)] = res1;
1123 out[stride * col] += res0;
1124 out[stride * (nn - 1 - col)] += res1;
1127 if (contract_over_rows ==
true && nn % 2 == 1 && mm % 2 == 1)
1130 out[stride * n_cols] = in[stride * mid];
1132 out[stride * n_cols] += in[stride * mid];
1134 else if (contract_over_rows ==
true && nn % 2 == 1)
1137 Number2 val0 = shape_values[n_cols];
1140 res0 = val0 * (in[0] + in[stride * (mm - 1)]);
1141 for (
int ind = 1; ind < mid; ++ind)
1143 val0 = shape_values[ind * n_columns + n_cols];
1144 res0 += val0 * (in[stride * ind] +
1145 in[stride * (mm - 1 - ind)]);
1151 out[stride * n_cols] = res0;
1153 out[stride * n_cols] += res0;
1155 else if (contract_over_rows ==
false && nn % 2 == 1)
1160 Number2 val0 = shape_values[n_cols * n_columns];
1161 res0 = val0 * (in[0] + in[stride * (mm - 1)]);
1162 for (
int ind = 1; ind < mid; ++ind)
1164 val0 = shape_values[n_cols * n_columns + ind];
1165 Number in1 = val0 * (in[stride * ind] +
1166 in[stride * (mm - 1 - ind)]);
1170 res0 += in[stride * mid];
1175 out[stride * n_cols] = res0;
1177 out[stride * n_cols] += res0;
1183 in += stride * (mm - 1);
1184 out += stride * (nn - 1);
1214 template <
int direction,
bool contract_over_rows,
bool add>
1221 Number2>::gradients(
const Number in[],
1226 constexpr
int mm = contract_over_rows ? n_rows : n_columns,
1227 nn = contract_over_rows ? n_columns : n_rows;
1228 constexpr
int n_cols = nn / 2;
1229 constexpr
int mid = mm / 2;
1232 constexpr
int n_blocks1 = stride;
1233 constexpr
int n_blocks2 =
1234 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
1236 for (
int i2 = 0; i2 < n_blocks2; ++i2)
1238 for (
int i1 = 0; i1 < n_blocks1; ++i1)
1240 for (
int col = 0; col < n_cols; ++col)
1243 Number in0, in1, res0, res1;
1244 if (contract_over_rows ==
true)
1246 val0 = shape_gradients[col];
1247 val1 = shape_gradients[nn - 1 - col];
1251 val0 = shape_gradients[col * n_columns];
1252 val1 = shape_gradients[(nn - col - 1) * n_columns];
1257 in1 = in[stride * (mm - 1)];
1262 for (
int ind = 1; ind < mid; ++ind)
1264 if (contract_over_rows ==
true)
1266 val0 = shape_gradients[ind * n_columns + col];
1268 shape_gradients[ind * n_columns + nn - 1 - col];
1272 val0 = shape_gradients[col * n_columns + ind];
1274 shape_gradients[(nn - col - 1) * n_columns + ind];
1276 in0 = in[stride * ind];
1277 in1 = in[stride * (mm - 1 - ind)];
1285 res0 = res1 = Number();
1288 if (contract_over_rows ==
true)
1289 val0 = shape_gradients[mid * n_columns + col];
1291 val0 = shape_gradients[col * n_columns + mid];
1292 in1 = val0 * in[stride * mid];
1298 out[stride * col] = res0;
1299 out[stride * (nn - 1 - col)] = res1;
1303 out[stride * col] += res0;
1304 out[stride * (nn - 1 - col)] += res1;
1311 if (contract_over_rows ==
true)
1312 val0 = shape_gradients[n_cols];
1314 val0 = shape_gradients[n_cols * n_columns];
1315 res0 = val0 * (in[0] - in[stride * (mm - 1)]);
1316 for (
int ind = 1; ind < mid; ++ind)
1318 if (contract_over_rows ==
true)
1319 val0 = shape_gradients[ind * n_columns + n_cols];
1321 val0 = shape_gradients[n_cols * n_columns + ind];
1323 val0 * (in[stride * ind] - in[stride * (mm - 1 - ind)]);
1327 out[stride * n_cols] = res0;
1329 out[stride * n_cols] += res0;
1335 in += stride * (mm - 1);
1336 out += stride * (nn - 1);
1350 template <
int direction,
bool contract_over_rows,
bool add>
1357 Number2>::hessians(
const Number in[],
1362 constexpr
int mm = contract_over_rows ? n_rows : n_columns;
1363 constexpr
int nn = contract_over_rows ? n_columns : n_rows;
1364 constexpr
int n_cols = nn / 2;
1365 constexpr
int mid = mm / 2;
1368 constexpr
int n_blocks1 = stride;
1369 constexpr
int n_blocks2 =
1370 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
1372 for (
int i2 = 0; i2 < n_blocks2; ++i2)
1374 for (
int i1 = 0; i1 < n_blocks1; ++i1)
1376 for (
int col = 0; col < n_cols; ++col)
1379 Number in0, in1, res0, res1;
1380 if (contract_over_rows ==
true)
1382 val0 = shape_hessians[col];
1383 val1 = shape_hessians[nn - 1 - col];
1387 val0 = shape_hessians[col * n_columns];
1388 val1 = shape_hessians[(col + 1) * n_columns - 1];
1393 in1 = in[stride * (mm - 1)];
1398 for (
int ind = 1; ind < mid; ++ind)
1400 if (contract_over_rows ==
true)
1402 val0 = shape_hessians[ind * n_columns + col];
1404 shape_hessians[ind * n_columns + nn - 1 - col];
1408 val0 = shape_hessians[col * n_columns + ind];
1410 shape_hessians[(col + 1) * n_columns - 1 - ind];
1412 in0 = in[stride * ind];
1413 in1 = in[stride * (mm - 1 - ind)];
1421 res0 = res1 = Number();
1424 if (contract_over_rows ==
true)
1425 val0 = shape_hessians[mid * n_columns + col];
1427 val0 = shape_hessians[col * n_columns + mid];
1428 in1 = val0 * in[stride * mid];
1434 out[stride * col] = res0;
1435 out[stride * (nn - 1 - col)] = res1;
1439 out[stride * col] += res0;
1440 out[stride * (nn - 1 - col)] += res1;
1447 if (contract_over_rows ==
true)
1448 val0 = shape_hessians[n_cols];
1450 val0 = shape_hessians[n_cols * n_columns];
1453 res0 = val0 * (in[0] + in[stride * (mm - 1)]);
1454 for (
int ind = 1; ind < mid; ++ind)
1456 if (contract_over_rows ==
true)
1457 val0 = shape_hessians[ind * n_columns + n_cols];
1459 val0 = shape_hessians[n_cols * n_columns + ind];
1460 Number in1 = val0 * (in[stride * ind] +
1461 in[stride * (mm - 1 - ind)]);
1469 if (contract_over_rows ==
true)
1470 val0 = shape_hessians[mid * n_columns + n_cols];
1472 val0 = shape_hessians[n_cols * n_columns + mid];
1473 res0 += val0 * in[stride * mid];
1476 out[stride * n_cols] = res0;
1478 out[stride * n_cols] += res0;
1484 in += stride * (mm - 1);
1485 out += stride * (nn - 1);
1534 static constexpr
unsigned int n_rows_of_product =
1536 static constexpr
unsigned int n_columns_of_product =
1545 : shape_values(nullptr)
1546 , shape_gradients(nullptr)
1547 , shape_hessians(nullptr)
1555 : shape_values(shape_values.
begin())
1556 , shape_gradients(nullptr)
1557 , shape_hessians(nullptr)
1569 const unsigned int dummy1 = 0,
1570 const unsigned int dummy2 = 0)
1571 : shape_values(shape_values.
begin())
1572 , shape_gradients(shape_gradients.
begin())
1573 , shape_hessians(shape_hessians.
begin())
1577 if (!shape_values.
empty())
1579 if (!shape_gradients.
empty())
1581 if (!shape_hessians.
empty())
1587 template <
int direction,
bool contract_over_rows,
bool add>
1589 values(
const Number in[], Number out[])
const
1592 apply<direction, contract_over_rows, add, 0>(shape_values, in, out);
1595 template <
int direction,
bool contract_over_rows,
bool add>
1600 apply<direction, contract_over_rows, add, 1>(shape_gradients, in, out);
1603 template <
int direction,
bool contract_over_rows,
bool add>
1608 apply<direction, contract_over_rows, add, 2>(shape_hessians, in, out);
1611 template <
int direction,
bool contract_over_rows,
bool add>
1616 apply<direction, contract_over_rows, add, 0, true>(shape_values, in, out);
1619 template <
int direction,
bool contract_over_rows,
bool add>
1624 apply<direction, contract_over_rows, add, 1, true>(shape_gradients,
1629 template <
int direction,
bool contract_over_rows,
bool add>
1634 apply<direction, contract_over_rows, add, 2, true>(shape_hessians,
1667 template <
int direction,
1668 bool contract_over_rows,
1671 bool one_line =
false>
1689 template <
int direction,
1690 bool contract_over_rows,
1704 static_assert(type < 3,
"Only three variants type=0,1,2 implemented");
1705 static_assert(one_line ==
false || direction == dim - 1,
1706 "Single-line evaluation only works for direction=dim-1.");
1707 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
1709 ExcMessage(
"In-place operation only supported for "
1710 "n_rows==n_columns or single-line interpolation"));
1716 constexpr
int nn = contract_over_rows ? n_columns : n_rows;
1717 constexpr
int mm = contract_over_rows ? n_rows : n_columns;
1718 constexpr
int n_cols = nn / 2;
1719 constexpr
int mid = mm / 2;
1722 constexpr
int n_blocks1 = one_line ? 1 : stride;
1723 constexpr
int n_blocks2 =
1724 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
1726 constexpr
int offset = (n_columns + 1) / 2;
1732 for (
int i2 = 0; i2 < n_blocks2; ++i2)
1734 for (
int i1 = 0; i1 < n_blocks1; ++i1)
1736 Number xp[mid > 0 ? mid : 1], xm[mid > 0 ? mid : 1];
1737 for (
int i = 0; i < mid; ++i)
1739 if (contract_over_rows ==
true && type == 1)
1741 xp[i] = in[stride * i] - in[stride * (mm - 1 - i)];
1742 xm[i] = in[stride * i] + in[stride * (mm - 1 - i)];
1746 xp[i] = in[stride * i] + in[stride * (mm - 1 - i)];
1747 xm[i] = in[stride * i] - in[stride * (mm - 1 - i)];
1750 Number xmid = in[stride * mid];
1751 for (
int col = 0; col < n_cols; ++col)
1756 if (contract_over_rows ==
true)
1758 r0 = shapes[col] * xp[0];
1759 r1 = shapes[(n_rows - 1) * offset + col] * xm[0];
1763 r0 = shapes[col * offset] * xp[0];
1764 r1 = shapes[(n_rows - 1 - col) * offset] * xm[0];
1766 for (
int ind = 1; ind < mid; ++ind)
1768 if (contract_over_rows ==
true)
1770 r0 += shapes[ind * offset + col] * xp[ind];
1771 r1 += shapes[(n_rows - 1 - ind) * offset + col] *
1776 r0 += shapes[col * offset + ind] * xp[ind];
1777 r1 += shapes[(n_rows - 1 - col) * offset + ind] *
1784 if (mm % 2 == 1 && contract_over_rows ==
true)
1787 r1 += shapes[mid * offset + col] * xmid;
1789 r0 += shapes[mid * offset + col] * xmid;
1791 else if (mm % 2 == 1 && (nn % 2 == 0 || type > 0 || mm == 3))
1792 r0 += shapes[col * offset + mid] * xmid;
1796 out[stride * col] = r0 + r1;
1797 if (type == 1 && contract_over_rows ==
false)
1798 out[stride * (nn - 1 - col)] = r1 - r0;
1800 out[stride * (nn - 1 - col)] = r0 - r1;
1804 out[stride * col] += r0 + r1;
1805 if (type == 1 && contract_over_rows ==
false)
1806 out[stride * (nn - 1 - col)] += r1 - r0;
1808 out[stride * (nn - 1 - col)] += r0 - r1;
1811 if (type == 0 && contract_over_rows ==
true && nn % 2 == 1 &&
1812 mm % 2 == 1 && mm > 3)
1815 out[stride * n_cols] = shapes[mid * offset + n_cols] * xmid;
1817 out[stride * n_cols] += shapes[mid * offset + n_cols] * xmid;
1819 else if (contract_over_rows ==
true && nn % 2 == 1)
1824 r0 = shapes[n_cols] * xp[0];
1825 for (
int ind = 1; ind < mid; ++ind)
1826 r0 += shapes[ind * offset + n_cols] * xp[ind];
1830 if (type != 1 && mm % 2 == 1)
1831 r0 += shapes[mid * offset + n_cols] * xmid;
1834 out[stride * n_cols] = r0;
1836 out[stride * n_cols] += r0;
1838 else if (contract_over_rows ==
false && nn % 2 == 1)
1845 r0 = shapes[n_cols * offset] * xm[0];
1846 for (
int ind = 1; ind < mid; ++ind)
1847 r0 += shapes[n_cols * offset + ind] * xm[ind];
1851 r0 = shapes[n_cols * offset] * xp[0];
1852 for (
int ind = 1; ind < mid; ++ind)
1853 r0 += shapes[n_cols * offset + ind] * xp[ind];
1859 if ((type == 0 || type == 2) && mm % 2 == 1)
1860 r0 += shapes[n_cols * offset + mid] * xmid;
1863 out[stride * n_cols] = r0;
1865 out[stride * n_cols] += r0;
1867 if (one_line ==
false)
1873 if (one_line ==
false)
1875 in += stride * (mm - 1);
1876 out += stride * (nn - 1);
1923 static constexpr
unsigned int n_rows_of_product =
1925 static constexpr
unsigned int n_columns_of_product =
1934 : shape_values(nullptr)
1935 , shape_gradients(nullptr)
1936 , shape_hessians(nullptr)
1944 : shape_values(shape_values.
begin())
1945 , shape_gradients(nullptr)
1946 , shape_hessians(nullptr)
1956 const unsigned int dummy1 = 0,
1957 const unsigned int dummy2 = 0)
1958 : shape_values(shape_values.
begin())
1959 , shape_gradients(shape_gradients.
begin())
1960 , shape_hessians(shape_hessians.
begin())
1966 template <
int direction,
bool contract_over_rows,
bool add>
1968 values(
const Number in[], Number out[])
const
1971 apply<direction, contract_over_rows, add, 0>(shape_values, in, out);
1974 template <
int direction,
bool contract_over_rows,
bool add>
1979 apply<direction, contract_over_rows, add, 1>(shape_gradients, in, out);
1982 template <
int direction,
bool contract_over_rows,
bool add>
1987 apply<direction, contract_over_rows, add, 0>(shape_hessians, in, out);
1990 template <
int direction,
bool contract_over_rows,
bool add>
1995 apply<direction, contract_over_rows, add, 0, true>(shape_values, in, out);
1998 template <
int direction,
bool contract_over_rows,
bool add>
2003 apply<direction, contract_over_rows, add, 1, true>(shape_gradients,
2008 template <
int direction,
bool contract_over_rows,
bool add>
2013 apply<direction, contract_over_rows, add, 0, true>(shape_hessians,
2045 template <
int direction,
2046 bool contract_over_rows,
2049 bool one_line =
false>
2067 template <
int direction,
2068 bool contract_over_rows,
2082 static_assert(one_line ==
false || direction == dim - 1,
2083 "Single-line evaluation only works for direction=dim-1.");
2085 type == 0 || type == 1,
2086 "Only types 0 and 1 implemented for evaluate_symmetric_hierarchical.");
2087 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
2089 ExcMessage(
"In-place operation only supported for "
2090 "n_rows==n_columns or single-line interpolation"));
2096 constexpr
int nn = contract_over_rows ? n_columns : n_rows;
2097 constexpr
int mm = contract_over_rows ? n_rows : n_columns;
2098 constexpr
int n_cols = nn / 2;
2099 constexpr
int mid = mm / 2;
2102 constexpr
int n_blocks1 = one_line ? 1 : stride;
2103 constexpr
int n_blocks2 =
2104 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
2110 for (
int i2 = 0; i2 < n_blocks2; ++i2)
2112 for (
int i1 = 0; i1 < n_blocks1; ++i1)
2114 if (contract_over_rows)
2117 for (
unsigned int i = 0; i < mm; ++i)
2118 x[i] = in[stride * i];
2119 for (
unsigned int col = 0; col < n_cols; ++col)
2124 r0 = shapes[col] * x[0];
2125 r1 = shapes[col + n_columns] * x[1];
2126 for (
unsigned int ind = 1; ind < mid; ++ind)
2129 shapes[col + 2 * ind * n_columns] * x[2 * ind];
2130 r1 += shapes[col + (2 * ind + 1) * n_columns] *
2137 r0 += shapes[col + (mm - 1) * n_columns] * x[mm - 1];
2140 out[stride * col] = r0 + r1;
2142 out[stride * (nn - 1 - col)] = r1 - r0;
2144 out[stride * (nn - 1 - col)] = r0 - r1;
2148 out[stride * col] += r0 + r1;
2150 out[stride * (nn - 1 - col)] += r1 - r0;
2152 out[stride * (nn - 1 - col)] += r0 - r1;
2158 const unsigned int shift = type == 1 ? 1 : 0;
2161 r0 = shapes[n_cols +
shift * n_columns] * x[
shift];
2162 for (
unsigned int ind = 1; ind < mid; ++ind)
2163 r0 += shapes[n_cols + (2 * ind +
shift) * n_columns] *
2168 if (type != 1 && mm % 2 == 1)
2169 r0 += shapes[n_cols + (mm - 1) * n_columns] * x[mm - 1];
2171 out[stride * n_cols] = r0;
2173 out[stride * n_cols] += r0;
2178 Number xp[mid + 1], xm[mid > 0 ? mid : 1];
2179 for (
int i = 0; i < mid; ++i)
2182 xp[i] = in[stride * i] + in[stride * (mm - 1 - i)];
2183 xm[i] = in[stride * i] - in[stride * (mm - 1 - i)];
2187 xp[i] = in[stride * i] - in[stride * (mm - 1 - i)];
2188 xm[i] = in[stride * i] + in[stride * (mm - 1 - i)];
2191 xp[mid] = in[stride * mid];
2192 for (
unsigned int col = 0; col < n_cols; ++col)
2197 r0 = shapes[2 * col * n_columns] * xp[0];
2198 r1 = shapes[(2 * col + 1) * n_columns] * xm[0];
2199 for (
unsigned int ind = 1; ind < mid; ++ind)
2201 r0 += shapes[2 * col * n_columns + ind] * xp[ind];
2203 shapes[(2 * col + 1) * n_columns + ind] * xm[ind];
2212 shapes[(2 * col + 1) * n_columns + mid] * xp[mid];
2214 r0 += shapes[2 * col * n_columns + mid] * xp[mid];
2218 out[stride * (2 * col)] = r0;
2219 out[stride * (2 * col + 1)] = r1;
2223 out[stride * (2 * col)] += r0;
2224 out[stride * (2 * col + 1)] += r1;
2232 r0 = shapes[(nn - 1) * n_columns] * xp[0];
2233 for (
unsigned int ind = 1; ind < mid; ++ind)
2234 r0 += shapes[(nn - 1) * n_columns + ind] * xp[ind];
2238 if (mm % 2 == 1 && type == 0)
2239 r0 += shapes[(nn - 1) * n_columns + mid] * xp[mid];
2241 out[stride * (nn - 1)] = r0;
2243 out[stride * (nn - 1)] += r0;
2246 if (one_line ==
false)
2252 if (one_line ==
false)
2254 in += stride * (mm - 1);
2255 out += stride * (nn - 1);