17#ifndef dealii_matrix_free_tensor_product_kernels_h
18#define dealii_matrix_free_tensor_product_kernels_h
117 typename Number2 = Number>
152 static constexpr unsigned int n_rows_of_product =
154 static constexpr unsigned int n_columns_of_product =
162 : shape_values(nullptr)
163 , shape_gradients(nullptr)
164 , shape_hessians(nullptr)
173 const unsigned int dummy1 = 0,
174 const unsigned int dummy2 = 0)
175 : shape_values(shape_values.
begin())
176 , shape_gradients(shape_gradients.
begin())
177 , shape_hessians(shape_hessians.
begin())
184 shape_values.
size() == n_rows * n_columns ||
185 shape_values.
size() == 3 * n_rows,
188 shape_gradients.
size() == n_rows * n_columns,
191 shape_hessians.
size() == n_rows * n_columns,
197 template <
int direction,
bool contract_over_rows,
bool add>
199 values(
const Number in[], Number out[])
const
201 apply<direction, contract_over_rows, add>(shape_values, in, out);
204 template <
int direction,
bool contract_over_rows,
bool add>
208 apply<direction, contract_over_rows, add>(shape_gradients, in, out);
211 template <
int direction,
bool contract_over_rows,
bool add>
215 apply<direction, contract_over_rows, add>(shape_hessians, in, out);
218 template <
int direction,
bool contract_over_rows,
bool add>
223 apply<direction, contract_over_rows, add, true>(shape_values, in, out);
226 template <
int direction,
bool contract_over_rows,
bool add>
231 apply<direction, contract_over_rows, add, true>(shape_gradients, in, out);
234 template <
int direction,
bool contract_over_rows,
bool add>
239 apply<direction, contract_over_rows, add, true>(shape_hessians, in, out);
266 template <
int direction,
267 bool contract_over_rows,
269 bool one_line =
false>
309 template <
int face_direction,
310 bool contract_onto_face,
313 bool lex_faces =
false>
330 template <
int direction,
bool contract_over_rows,
bool add,
bool one_line>
342 static_assert(one_line ==
false || direction == dim - 1,
343 "Single-line evaluation only works for direction=dim-1.");
344 Assert(shape_data !=
nullptr,
346 "The given array shape_data must not be the null pointer!"));
347 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
349 ExcMessage(
"In-place operation only supported for "
350 "n_rows==n_columns or single-line interpolation"));
352 constexpr int mm = contract_over_rows ? n_rows : n_columns,
353 nn = contract_over_rows ? n_columns : n_rows;
356 constexpr int n_blocks1 = one_line ? 1 : stride;
357 constexpr int n_blocks2 =
358 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
360 for (
int i2 = 0; i2 < n_blocks2; ++i2)
362 for (
int i1 = 0; i1 < n_blocks1; ++i1)
365 for (
int i = 0; i < mm; ++i)
366 x[i] = in[stride * i];
367 for (
int col = 0; col < nn; ++col)
370 if (contract_over_rows ==
true)
371 val0 = shape_data[col];
373 val0 = shape_data[col * n_columns];
374 Number res0 = val0 * x[0];
375 for (
int i = 1; i < mm; ++i)
377 if (contract_over_rows ==
true)
378 val0 = shape_data[i * n_columns + col];
380 val0 = shape_data[col * n_columns + i];
384 out[stride * col] = res0;
386 out[stride * col] += res0;
389 if (one_line ==
false)
395 if (one_line ==
false)
397 in += stride * (mm - 1);
398 out += stride * (nn - 1);
410 template <
int face_direction,
411 bool contract_onto_face,
425 Assert(dim > 0 && (lex_faces || dim < 4),
427 static_assert(max_derivative >= 0 && max_derivative < 3,
428 "Only derivative orders 0-2 implemented");
429 Assert(shape_values !=
nullptr,
431 "The given array shape_values must not be the null pointer."));
433 constexpr int n_blocks1 =
434 lex_faces ? ::Utilities::pow<unsigned int>(n_rows, face_direction) :
435 (dim > 1 ? n_rows : 1);
436 constexpr int n_blocks2 =
437 lex_faces ? ::Utilities::pow<unsigned int>(
438 n_rows,
std::max(dim - face_direction - 1, 0)) :
439 (dim > 2 ? n_rows : 1);
446 for (
int i2 = 0; i2 < n_blocks2; ++i2)
448 for (
int i1 = 0; i1 < n_blocks1; ++i1)
450 if (contract_onto_face ==
true)
452 Number res0 = shape_values[0] * in[0];
454 if (max_derivative > 0)
455 res1 = shape_values[n_rows] * in[0];
456 if (max_derivative > 1)
457 res2 = shape_values[2 * n_rows] * in[0];
458 for (
int ind = 1; ind < n_rows; ++ind)
460 res0 += shape_values[ind] * in[stride * ind];
461 if (max_derivative > 0)
462 res1 += shape_values[ind + n_rows] * in[stride * ind];
463 if (max_derivative > 1)
464 res2 += shape_values[ind + 2 * n_rows] * in[stride * ind];
469 if (max_derivative > 0)
470 out[out_stride] = res1;
471 if (max_derivative > 1)
472 out[2 * out_stride] = res2;
477 if (max_derivative > 0)
478 out[out_stride] += res1;
479 if (max_derivative > 1)
480 out[2 * out_stride] += res2;
485 for (
int col = 0; col < n_rows; ++col)
488 out[col * stride] = shape_values[col] * in[0];
490 out[col * stride] += shape_values[col] * in[0];
491 if (max_derivative > 0)
493 shape_values[col + n_rows] * in[out_stride];
494 if (max_derivative > 1)
496 shape_values[col + 2 * n_rows] * in[2 * out_stride];
509 switch (face_direction)
512 in += contract_onto_face ? n_rows : 1;
513 out += contract_onto_face ? 1 : n_rows;
523 if (contract_onto_face)
539 if (contract_onto_face)
546 else if (face_direction == 1 && dim == 3)
549 if (contract_onto_face)
551 in += n_rows * (n_rows - 1);
552 out -= n_rows * n_rows - 1;
556 out += n_rows * (n_rows - 1);
557 in -= n_rows * n_rows - 1;
578 template <
int dim,
typename Number,
typename Number2>
581 static constexpr unsigned int n_rows_of_product =
583 static constexpr unsigned int n_columns_of_product =
591 : shape_values(nullptr)
592 , shape_gradients(nullptr)
593 , shape_hessians(nullptr)
604 const unsigned int n_rows,
605 const unsigned int n_columns)
606 : shape_values(shape_values.
begin())
607 , shape_gradients(shape_gradients.
begin())
608 , shape_hessians(shape_hessians.
begin())
610 , n_columns(n_columns)
617 shape_values.
size() == n_rows * n_columns ||
618 shape_values.
size() == n_rows * 3,
621 shape_gradients.
size() == n_rows * n_columns,
624 shape_hessians.
size() == n_rows * n_columns,
632 const Number2 * shape_gradients,
633 const Number2 * shape_hessians,
634 const unsigned int n_rows,
635 const unsigned int n_columns)
636 : shape_values(shape_values)
637 , shape_gradients(shape_gradients)
638 , shape_hessians(shape_hessians)
640 , n_columns(n_columns)
643 template <
int direction,
bool contract_over_rows,
bool add>
645 values(
const Number *in, Number *out)
const
647 apply<direction, contract_over_rows, add>(shape_values, in, out);
650 template <
int direction,
bool contract_over_rows,
bool add>
654 apply<direction, contract_over_rows, add>(shape_gradients, in, out);
657 template <
int direction,
bool contract_over_rows,
bool add>
661 apply<direction, contract_over_rows, add>(shape_hessians, in, out);
664 template <
int direction,
bool contract_over_rows,
bool add>
669 apply<direction, contract_over_rows, add, true>(shape_values, in, out);
672 template <
int direction,
bool contract_over_rows,
bool add>
677 apply<direction, contract_over_rows, add, true>(shape_gradients, in, out);
680 template <
int direction,
bool contract_over_rows,
bool add>
685 apply<direction, contract_over_rows, add, true>(shape_hessians, in, out);
688 template <
int direction,
689 bool contract_over_rows,
691 bool one_line =
false>
697 template <
int face_direction,
698 bool contract_onto_face,
701 bool lex_faces =
false>
715 template <
int dim,
typename Number,
typename Number2>
716 template <
int direction,
bool contract_over_rows,
bool add,
bool one_line>
723 static_assert(one_line ==
false || direction == dim - 1,
724 "Single-line evaluation only works for direction=dim-1.");
725 Assert(shape_data !=
nullptr,
727 "The given array shape_data must not be the null pointer!"));
728 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
730 ExcMessage(
"In-place operation only supported for "
731 "n_rows==n_columns or single-line interpolation"));
733 const int mm = contract_over_rows ? n_rows : n_columns,
734 nn = contract_over_rows ? n_columns : n_rows;
737 direction == 0 ? 1 : Utilities::fixed_power<direction>(n_columns);
738 const int n_blocks1 = one_line ? 1 : stride;
739 const int n_blocks2 = direction >= dim - 1 ?
749 if (contract_over_rows && n_rows == 2)
751 const Number2 *shape_data_1 = shape_data + n_columns;
752 for (
int i2 = 0; i2 < n_blocks2; ++i2)
754 for (
int i1 = 0; i1 < n_blocks1; ++i1)
756 const Number x0 = in[0], x1 = in[stride];
757 for (
int col = 0; col < nn; ++col)
759 const Number result =
760 shape_data[col] * x0 + shape_data_1[col] * x1;
762 out[stride * col] = result;
764 out[stride * col] += result;
767 if (one_line ==
false)
773 if (one_line ==
false)
775 in += stride * (mm - 1);
776 out += stride * (nn - 1);
781 else if (contract_over_rows && n_rows == 3)
783 const Number2 *shape_data_1 = shape_data + n_columns;
784 const Number2 *shape_data_2 = shape_data + 2 * n_columns;
785 for (
int i2 = 0; i2 < n_blocks2; ++i2)
787 for (
int i1 = 0; i1 < n_blocks1; ++i1)
789 const Number x0 = in[0], x1 = in[stride], x2 = in[2 * stride];
790 for (
int col = 0; col < nn; ++col)
792 const Number result = shape_data[col] * x0 +
793 shape_data_1[col] * x1 +
794 shape_data_2[col] * x2;
796 out[stride * col] = result;
798 out[stride * col] += result;
801 if (one_line ==
false)
807 if (one_line ==
false)
809 in += stride * (mm - 1);
810 out += stride * (nn - 1);
816 for (
int i2 = 0; i2 < n_blocks2; ++i2)
818 for (
int i1 = 0; i1 < n_blocks1; ++i1)
821 for (
int i = 0; i < mm; ++i)
822 x[i] = in[stride * i];
823 for (
int col = 0; col < nn; ++col)
826 if (contract_over_rows ==
true)
827 val0 = shape_data[col];
829 val0 = shape_data[col * n_columns];
830 Number res0 = val0 * x[0];
831 for (
int i = 1; i < mm; ++i)
833 if (contract_over_rows ==
true)
834 val0 = shape_data[i * n_columns + col];
836 val0 = shape_data[col * n_columns + i];
840 out[stride * col] = res0;
842 out[stride * col] += res0;
845 if (one_line ==
false)
851 if (one_line ==
false)
853 in += stride * (mm - 1);
854 out += stride * (nn - 1);
861 template <
int dim,
typename Number,
typename Number2>
862 template <
int face_direction,
863 bool contract_onto_face,
872 static_assert(lex_faces ==
false,
"Not implemented yet.");
874 Assert(shape_values !=
nullptr,
876 "The given array shape_data must not be the null pointer!"));
877 static_assert(dim > 0 && dim < 4,
"Only dim=1,2,3 supported");
878 const int n_blocks1 = dim > 1 ? n_rows : 1;
879 const int n_blocks2 = dim > 2 ? n_rows : 1;
883 face_direction > 0 ? Utilities::fixed_power<face_direction>(n_rows) : 1;
884 const int out_stride =
887 for (
int i2 = 0; i2 < n_blocks2; ++i2)
889 for (
int i1 = 0; i1 < n_blocks1; ++i1)
891 if (contract_onto_face ==
true)
893 Number res0 = shape_values[0] * in[0];
895 if (max_derivative > 0)
896 res1 = shape_values[n_rows] * in[0];
897 if (max_derivative > 1)
898 res2 = shape_values[2 * n_rows] * in[0];
899 for (
unsigned int ind = 1; ind < n_rows; ++ind)
901 res0 += shape_values[ind] * in[stride * ind];
902 if (max_derivative > 0)
903 res1 += shape_values[ind + n_rows] * in[stride * ind];
904 if (max_derivative > 1)
905 res2 += shape_values[ind + 2 * n_rows] * in[stride * ind];
910 if (max_derivative > 0)
911 out[out_stride] = res1;
912 if (max_derivative > 1)
913 out[2 * out_stride] = res2;
918 if (max_derivative > 0)
919 out[out_stride] += res1;
920 if (max_derivative > 1)
921 out[2 * out_stride] += res2;
926 for (
unsigned int col = 0; col < n_rows; ++col)
929 out[col * stride] = shape_values[col] * in[0];
931 out[col * stride] += shape_values[col] * in[0];
932 if (max_derivative > 0)
934 shape_values[col + n_rows] * in[out_stride];
935 if (max_derivative > 1)
937 shape_values[col + 2 * n_rows] * in[2 * out_stride];
944 switch (face_direction)
947 in += contract_onto_face ? n_rows : 1;
948 out += contract_onto_face ? 1 : n_rows;
958 if (contract_onto_face)
972 if (face_direction == 1 && dim == 3)
975 if (contract_onto_face)
977 in += n_rows * (n_rows - 1);
978 out -= n_rows * n_rows - 1;
982 out += n_rows * (n_rows - 1);
983 in -= n_rows * n_rows - 1;
1023 static constexpr unsigned int n_rows_of_product =
1025 static constexpr unsigned int n_columns_of_product =
1034 const unsigned int dummy1 = 0,
1035 const unsigned int dummy2 = 0)
1036 : shape_values(shape_values.
begin())
1037 , shape_gradients(shape_gradients.
begin())
1038 , shape_hessians(shape_hessians.
begin())
1041 shape_values.
size() == n_rows * n_columns,
1044 shape_gradients.
size() == n_rows * n_columns,
1047 shape_hessians.
size() == n_rows * n_columns,
1053 template <
int direction,
bool contract_over_rows,
bool add>
1055 values(
const Number in[], Number out[])
const;
1057 template <
int direction,
bool contract_over_rows,
bool add>
1059 gradients(
const Number in[], Number out[])
const;
1061 template <
int direction,
bool contract_over_rows,
bool add>
1063 hessians(
const Number in[], Number out[])
const;
1095 template <
int direction,
bool contract_over_rows,
bool add>
1102 Number2>
::values(
const Number in[], Number out[])
const
1106 constexpr int mm = contract_over_rows ? n_rows : n_columns,
1107 nn = contract_over_rows ? n_columns : n_rows;
1108 constexpr int n_cols = nn / 2;
1109 constexpr int mid = mm / 2;
1112 constexpr int n_blocks1 = stride;
1113 constexpr int n_blocks2 =
1114 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
1116 for (
int i2 = 0; i2 < n_blocks2; ++i2)
1118 for (
int i1 = 0; i1 < n_blocks1; ++i1)
1120 for (
int col = 0; col < n_cols; ++col)
1123 Number in0, in1, res0, res1;
1124 if (contract_over_rows ==
true)
1126 val0 = shape_values[col];
1127 val1 = shape_values[nn - 1 - col];
1131 val0 = shape_values[col * n_columns];
1132 val1 = shape_values[(col + 1) * n_columns - 1];
1137 in1 = in[stride * (mm - 1)];
1142 for (
int ind = 1; ind < mid; ++ind)
1144 if (contract_over_rows ==
true)
1146 val0 = shape_values[ind * n_columns + col];
1147 val1 = shape_values[ind * n_columns + nn - 1 - col];
1151 val0 = shape_values[col * n_columns + ind];
1153 shape_values[(col + 1) * n_columns - 1 - ind];
1155 in0 = in[stride * ind];
1156 in1 = in[stride * (mm - 1 - ind)];
1164 res0 = res1 = Number();
1165 if (contract_over_rows ==
true)
1169 val0 = shape_values[mid * n_columns + col];
1170 in1 = val0 * in[stride * mid];
1177 if (mm % 2 == 1 && nn % 2 == 0)
1179 val0 = shape_values[col * n_columns + mid];
1180 in1 = val0 * in[stride * mid];
1187 out[stride * col] = res0;
1188 out[stride * (nn - 1 - col)] = res1;
1192 out[stride * col] += res0;
1193 out[stride * (nn - 1 - col)] += res1;
1196 if (contract_over_rows ==
true && nn % 2 == 1 && mm % 2 == 1)
1199 out[stride * n_cols] = in[stride * mid];
1201 out[stride * n_cols] += in[stride * mid];
1203 else if (contract_over_rows ==
true && nn % 2 == 1)
1206 Number2 val0 = shape_values[n_cols];
1209 res0 = val0 * (in[0] + in[stride * (mm - 1)]);
1210 for (
int ind = 1; ind < mid; ++ind)
1212 val0 = shape_values[ind * n_columns + n_cols];
1213 res0 += val0 * (in[stride * ind] +
1214 in[stride * (mm - 1 - ind)]);
1220 out[stride * n_cols] = res0;
1222 out[stride * n_cols] += res0;
1224 else if (contract_over_rows ==
false && nn % 2 == 1)
1229 Number2 val0 = shape_values[n_cols * n_columns];
1230 res0 = val0 * (in[0] + in[stride * (mm - 1)]);
1231 for (
int ind = 1; ind < mid; ++ind)
1233 val0 = shape_values[n_cols * n_columns + ind];
1234 Number in1 = val0 * (in[stride * ind] +
1235 in[stride * (mm - 1 - ind)]);
1239 res0 += in[stride * mid];
1244 out[stride * n_cols] = res0;
1246 out[stride * n_cols] += res0;
1252 in += stride * (mm - 1);
1253 out += stride * (nn - 1);
1283 template <
int direction,
bool contract_over_rows,
bool add>
1295 constexpr int mm = contract_over_rows ? n_rows : n_columns,
1296 nn = contract_over_rows ? n_columns : n_rows;
1297 constexpr int n_cols = nn / 2;
1298 constexpr int mid = mm / 2;
1301 constexpr int n_blocks1 = stride;
1302 constexpr int n_blocks2 =
1303 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
1305 for (
int i2 = 0; i2 < n_blocks2; ++i2)
1307 for (
int i1 = 0; i1 < n_blocks1; ++i1)
1309 for (
int col = 0; col < n_cols; ++col)
1312 Number in0, in1, res0, res1;
1313 if (contract_over_rows ==
true)
1315 val0 = shape_gradients[col];
1316 val1 = shape_gradients[nn - 1 - col];
1320 val0 = shape_gradients[col * n_columns];
1321 val1 = shape_gradients[(nn - col - 1) * n_columns];
1326 in1 = in[stride * (mm - 1)];
1331 for (
int ind = 1; ind < mid; ++ind)
1333 if (contract_over_rows ==
true)
1335 val0 = shape_gradients[ind * n_columns + col];
1337 shape_gradients[ind * n_columns + nn - 1 - col];
1341 val0 = shape_gradients[col * n_columns + ind];
1343 shape_gradients[(nn - col - 1) * n_columns + ind];
1345 in0 = in[stride * ind];
1346 in1 = in[stride * (mm - 1 - ind)];
1354 res0 = res1 = Number();
1357 if (contract_over_rows ==
true)
1358 val0 = shape_gradients[mid * n_columns + col];
1360 val0 = shape_gradients[col * n_columns + mid];
1361 in1 = val0 * in[stride * mid];
1367 out[stride * col] = res0;
1368 out[stride * (nn - 1 - col)] = res1;
1372 out[stride * col] += res0;
1373 out[stride * (nn - 1 - col)] += res1;
1380 if (contract_over_rows ==
true)
1381 val0 = shape_gradients[n_cols];
1383 val0 = shape_gradients[n_cols * n_columns];
1384 res0 = val0 * (in[0] - in[stride * (mm - 1)]);
1385 for (
int ind = 1; ind < mid; ++ind)
1387 if (contract_over_rows ==
true)
1388 val0 = shape_gradients[ind * n_columns + n_cols];
1390 val0 = shape_gradients[n_cols * n_columns + ind];
1392 val0 * (in[stride * ind] - in[stride * (mm - 1 - ind)]);
1396 out[stride * n_cols] = res0;
1398 out[stride * n_cols] += res0;
1404 in += stride * (mm - 1);
1405 out += stride * (nn - 1);
1419 template <
int direction,
bool contract_over_rows,
bool add>
1431 constexpr int mm = contract_over_rows ? n_rows : n_columns;
1432 constexpr int nn = contract_over_rows ? n_columns : n_rows;
1433 constexpr int n_cols = nn / 2;
1434 constexpr int mid = mm / 2;
1437 constexpr int n_blocks1 = stride;
1438 constexpr int n_blocks2 =
1439 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
1441 for (
int i2 = 0; i2 < n_blocks2; ++i2)
1443 for (
int i1 = 0; i1 < n_blocks1; ++i1)
1445 for (
int col = 0; col < n_cols; ++col)
1448 Number in0, in1, res0, res1;
1449 if (contract_over_rows ==
true)
1451 val0 = shape_hessians[col];
1452 val1 = shape_hessians[nn - 1 - col];
1456 val0 = shape_hessians[col * n_columns];
1457 val1 = shape_hessians[(col + 1) * n_columns - 1];
1462 in1 = in[stride * (mm - 1)];
1467 for (
int ind = 1; ind < mid; ++ind)
1469 if (contract_over_rows ==
true)
1471 val0 = shape_hessians[ind * n_columns + col];
1473 shape_hessians[ind * n_columns + nn - 1 - col];
1477 val0 = shape_hessians[col * n_columns + ind];
1479 shape_hessians[(col + 1) * n_columns - 1 - ind];
1481 in0 = in[stride * ind];
1482 in1 = in[stride * (mm - 1 - ind)];
1490 res0 = res1 = Number();
1493 if (contract_over_rows ==
true)
1494 val0 = shape_hessians[mid * n_columns + col];
1496 val0 = shape_hessians[col * n_columns + mid];
1497 in1 = val0 * in[stride * mid];
1503 out[stride * col] = res0;
1504 out[stride * (nn - 1 - col)] = res1;
1508 out[stride * col] += res0;
1509 out[stride * (nn - 1 - col)] += res1;
1516 if (contract_over_rows ==
true)
1517 val0 = shape_hessians[n_cols];
1519 val0 = shape_hessians[n_cols * n_columns];
1522 res0 = val0 * (in[0] + in[stride * (mm - 1)]);
1523 for (
int ind = 1; ind < mid; ++ind)
1525 if (contract_over_rows ==
true)
1526 val0 = shape_hessians[ind * n_columns + n_cols];
1528 val0 = shape_hessians[n_cols * n_columns + ind];
1529 Number in1 = val0 * (in[stride * ind] +
1530 in[stride * (mm - 1 - ind)]);
1538 if (contract_over_rows ==
true)
1539 val0 = shape_hessians[mid * n_columns + n_cols];
1541 val0 = shape_hessians[n_cols * n_columns + mid];
1542 res0 += val0 * in[stride * mid];
1545 out[stride * n_cols] = res0;
1547 out[stride * n_cols] += res0;
1553 in += stride * (mm - 1);
1554 out += stride * (nn - 1);
1603 static constexpr unsigned int n_rows_of_product =
1605 static constexpr unsigned int n_columns_of_product =
1614 : shape_values(nullptr)
1615 , shape_gradients(nullptr)
1616 , shape_hessians(nullptr)
1624 : shape_values(shape_values.
begin())
1625 , shape_gradients(nullptr)
1626 , shape_hessians(nullptr)
1638 const unsigned int dummy1 = 0,
1639 const unsigned int dummy2 = 0)
1640 : shape_values(shape_values.
begin())
1641 , shape_gradients(shape_gradients.
begin())
1642 , shape_hessians(shape_hessians.
begin())
1646 if (!shape_values.
empty())
1648 if (!shape_gradients.
empty())
1650 if (!shape_hessians.
empty())
1656 template <
int direction,
bool contract_over_rows,
bool add>
1658 values(
const Number in[], Number out[])
const
1661 apply<direction, contract_over_rows, add, 0>(shape_values, in, out);
1664 template <
int direction,
bool contract_over_rows,
bool add>
1669 apply<direction, contract_over_rows, add, 1>(shape_gradients, in, out);
1672 template <
int direction,
bool contract_over_rows,
bool add>
1677 apply<direction, contract_over_rows, add, 2>(shape_hessians, in, out);
1680 template <
int direction,
bool contract_over_rows,
bool add>
1685 apply<direction, contract_over_rows, add, 0, true>(shape_values, in, out);
1688 template <
int direction,
bool contract_over_rows,
bool add>
1693 apply<direction, contract_over_rows, add, 1, true>(shape_gradients,
1698 template <
int direction,
bool contract_over_rows,
bool add>
1703 apply<direction, contract_over_rows, add, 2, true>(shape_hessians,
1736 template <
int direction,
1737 bool contract_over_rows,
1740 bool one_line =
false>
1758 template <
int direction,
1759 bool contract_over_rows,
1773 static_assert(type < 3,
"Only three variants type=0,1,2 implemented");
1774 static_assert(one_line ==
false || direction == dim - 1,
1775 "Single-line evaluation only works for direction=dim-1.");
1776 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
1778 ExcMessage(
"In-place operation only supported for "
1779 "n_rows==n_columns or single-line interpolation"));
1785 constexpr int nn = contract_over_rows ? n_columns : n_rows;
1786 constexpr int mm = contract_over_rows ? n_rows : n_columns;
1787 constexpr int n_cols = nn / 2;
1788 constexpr int mid = mm / 2;
1791 constexpr int n_blocks1 = one_line ? 1 : stride;
1792 constexpr int n_blocks2 =
1793 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
1795 constexpr int offset = (n_columns + 1) / 2;
1801 for (
int i2 = 0; i2 < n_blocks2; ++i2)
1803 for (
int i1 = 0; i1 < n_blocks1; ++i1)
1805 Number xp[mid > 0 ? mid : 1], xm[mid > 0 ? mid : 1];
1806 for (
int i = 0; i < mid; ++i)
1808 if (contract_over_rows ==
true && type == 1)
1810 xp[i] = in[stride * i] - in[stride * (mm - 1 - i)];
1811 xm[i] = in[stride * i] + in[stride * (mm - 1 - i)];
1815 xp[i] = in[stride * i] + in[stride * (mm - 1 - i)];
1816 xm[i] = in[stride * i] - in[stride * (mm - 1 - i)];
1819 Number xmid = in[stride * mid];
1820 for (
int col = 0; col < n_cols; ++col)
1825 if (contract_over_rows ==
true)
1827 r0 = shapes[col] * xp[0];
1828 r1 = shapes[(n_rows - 1) * offset + col] * xm[0];
1832 r0 = shapes[col * offset] * xp[0];
1833 r1 = shapes[(n_rows - 1 - col) * offset] * xm[0];
1835 for (
int ind = 1; ind < mid; ++ind)
1837 if (contract_over_rows ==
true)
1839 r0 += shapes[ind * offset + col] * xp[ind];
1840 r1 += shapes[(n_rows - 1 - ind) * offset + col] *
1845 r0 += shapes[col * offset + ind] * xp[ind];
1846 r1 += shapes[(n_rows - 1 - col) * offset + ind] *
1853 if (mm % 2 == 1 && contract_over_rows ==
true)
1856 r1 += shapes[mid * offset + col] * xmid;
1858 r0 += shapes[mid * offset + col] * xmid;
1860 else if (mm % 2 == 1 && (nn % 2 == 0 || type > 0 || mm == 3))
1861 r0 += shapes[col * offset + mid] * xmid;
1865 out[stride * col] = r0 + r1;
1866 if (type == 1 && contract_over_rows ==
false)
1867 out[stride * (nn - 1 - col)] = r1 - r0;
1869 out[stride * (nn - 1 - col)] = r0 - r1;
1873 out[stride * col] += r0 + r1;
1874 if (type == 1 && contract_over_rows ==
false)
1875 out[stride * (nn - 1 - col)] += r1 - r0;
1877 out[stride * (nn - 1 - col)] += r0 - r1;
1880 if (type == 0 && contract_over_rows ==
true && nn % 2 == 1 &&
1881 mm % 2 == 1 && mm > 3)
1884 out[stride * n_cols] = shapes[mid * offset + n_cols] * xmid;
1886 out[stride * n_cols] += shapes[mid * offset + n_cols] * xmid;
1888 else if (contract_over_rows ==
true && nn % 2 == 1)
1893 r0 = shapes[n_cols] * xp[0];
1894 for (
int ind = 1; ind < mid; ++ind)
1895 r0 += shapes[ind * offset + n_cols] * xp[ind];
1899 if (type != 1 && mm % 2 == 1)
1900 r0 += shapes[mid * offset + n_cols] * xmid;
1903 out[stride * n_cols] = r0;
1905 out[stride * n_cols] += r0;
1907 else if (contract_over_rows ==
false && nn % 2 == 1)
1914 r0 = shapes[n_cols * offset] * xm[0];
1915 for (
int ind = 1; ind < mid; ++ind)
1916 r0 += shapes[n_cols * offset + ind] * xm[ind];
1920 r0 = shapes[n_cols * offset] * xp[0];
1921 for (
int ind = 1; ind < mid; ++ind)
1922 r0 += shapes[n_cols * offset + ind] * xp[ind];
1928 if ((type == 0 || type == 2) && mm % 2 == 1)
1929 r0 += shapes[n_cols * offset + mid] * xmid;
1932 out[stride * n_cols] = r0;
1934 out[stride * n_cols] += r0;
1936 if (one_line ==
false)
1942 if (one_line ==
false)
1944 in += stride * (mm - 1);
1945 out += stride * (nn - 1);
1992 static constexpr unsigned int n_rows_of_product =
1994 static constexpr unsigned int n_columns_of_product =
2003 : shape_values(nullptr)
2004 , shape_gradients(nullptr)
2005 , shape_hessians(nullptr)
2013 : shape_values(shape_values.
begin())
2014 , shape_gradients(nullptr)
2015 , shape_hessians(nullptr)
2025 const unsigned int dummy1 = 0,
2026 const unsigned int dummy2 = 0)
2027 : shape_values(shape_values.
begin())
2028 , shape_gradients(shape_gradients.
begin())
2029 , shape_hessians(shape_hessians.
begin())
2035 template <
int direction,
bool contract_over_rows,
bool add>
2037 values(
const Number in[], Number out[])
const
2040 apply<direction, contract_over_rows, add, 0>(shape_values, in, out);
2043 template <
int direction,
bool contract_over_rows,
bool add>
2048 apply<direction, contract_over_rows, add, 1>(shape_gradients, in, out);
2051 template <
int direction,
bool contract_over_rows,
bool add>
2056 apply<direction, contract_over_rows, add, 0>(shape_hessians, in, out);
2059 template <
int direction,
bool contract_over_rows,
bool add>
2064 apply<direction, contract_over_rows, add, 0, true>(shape_values, in, out);
2067 template <
int direction,
bool contract_over_rows,
bool add>
2072 apply<direction, contract_over_rows, add, 1, true>(shape_gradients,
2077 template <
int direction,
bool contract_over_rows,
bool add>
2082 apply<direction, contract_over_rows, add, 0, true>(shape_hessians,
2114 template <
int direction,
2115 bool contract_over_rows,
2118 bool one_line =
false>
2136 template <
int direction,
2137 bool contract_over_rows,
2151 static_assert(one_line ==
false || direction == dim - 1,
2152 "Single-line evaluation only works for direction=dim-1.");
2154 type == 0 || type == 1,
2155 "Only types 0 and 1 implemented for evaluate_symmetric_hierarchical.");
2156 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
2158 ExcMessage(
"In-place operation only supported for "
2159 "n_rows==n_columns or single-line interpolation"));
2165 constexpr int nn = contract_over_rows ? n_columns : n_rows;
2166 constexpr int mm = contract_over_rows ? n_rows : n_columns;
2167 constexpr int n_cols = nn / 2;
2168 constexpr int mid = mm / 2;
2171 constexpr int n_blocks1 = one_line ? 1 : stride;
2172 constexpr int n_blocks2 =
2173 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
2179 for (
int i2 = 0; i2 < n_blocks2; ++i2)
2181 for (
int i1 = 0; i1 < n_blocks1; ++i1)
2183 if (contract_over_rows)
2186 for (
unsigned int i = 0; i < mm; ++i)
2187 x[i] = in[stride * i];
2188 for (
unsigned int col = 0; col < n_cols; ++col)
2193 r0 = shapes[col] * x[0];
2194 r1 = shapes[col + n_columns] * x[1];
2195 for (
unsigned int ind = 1; ind < mid; ++ind)
2198 shapes[col + 2 * ind * n_columns] * x[2 * ind];
2199 r1 += shapes[col + (2 * ind + 1) * n_columns] *
2206 r0 += shapes[col + (mm - 1) * n_columns] * x[mm - 1];
2209 out[stride * col] = r0 + r1;
2211 out[stride * (nn - 1 - col)] = r1 - r0;
2213 out[stride * (nn - 1 - col)] = r0 - r1;
2217 out[stride * col] += r0 + r1;
2219 out[stride * (nn - 1 - col)] += r1 - r0;
2221 out[stride * (nn - 1 - col)] += r0 - r1;
2227 const unsigned int shift = type == 1 ? 1 : 0;
2230 r0 = shapes[n_cols +
shift * n_columns] * x[
shift];
2231 for (
unsigned int ind = 1; ind < mid; ++ind)
2232 r0 += shapes[n_cols + (2 * ind +
shift) * n_columns] *
2237 if (type != 1 && mm % 2 == 1)
2238 r0 += shapes[n_cols + (mm - 1) * n_columns] * x[mm - 1];
2240 out[stride * n_cols] = r0;
2242 out[stride * n_cols] += r0;
2247 Number xp[mid + 1], xm[mid > 0 ? mid : 1];
2248 for (
int i = 0; i < mid; ++i)
2251 xp[i] = in[stride * i] + in[stride * (mm - 1 - i)];
2252 xm[i] = in[stride * i] - in[stride * (mm - 1 - i)];
2256 xp[i] = in[stride * i] - in[stride * (mm - 1 - i)];
2257 xm[i] = in[stride * i] + in[stride * (mm - 1 - i)];
2260 xp[mid] = in[stride * mid];
2261 for (
unsigned int col = 0; col < n_cols; ++col)
2266 r0 = shapes[2 * col * n_columns] * xp[0];
2267 r1 = shapes[(2 * col + 1) * n_columns] * xm[0];
2268 for (
unsigned int ind = 1; ind < mid; ++ind)
2270 r0 += shapes[2 * col * n_columns + ind] * xp[ind];
2272 shapes[(2 * col + 1) * n_columns + ind] * xm[ind];
2281 shapes[(2 * col + 1) * n_columns + mid] * xp[mid];
2283 r0 += shapes[2 * col * n_columns + mid] * xp[mid];
2287 out[stride * (2 * col)] = r0;
2288 out[stride * (2 * col + 1)] = r1;
2292 out[stride * (2 * col)] += r0;
2293 out[stride * (2 * col + 1)] += r1;
2301 r0 = shapes[(nn - 1) * n_columns] * xp[0];
2302 for (
unsigned int ind = 1; ind < mid; ++ind)
2303 r0 += shapes[(nn - 1) * n_columns + ind] * xp[ind];
2307 if (mm % 2 == 1 && type == 0)
2308 r0 += shapes[(nn - 1) * n_columns + mid] * xp[mid];
2310 out[stride * (nn - 1)] = r0;
2312 out[stride * (nn - 1)] += r0;
2315 if (one_line ==
false)
2321 if (one_line ==
false)
2323 in += stride * (mm - 1);
2324 out += stride * (nn - 1);
2337 template <
typename Number,
typename Number2>
2343 template <
int dim,
typename Number,
typename Number2>
2385 template <
int dim,
typename Number,
typename Number2>
2391 const std::vector<Number> &
values,
2393 const bool d_linear =
false,
2394 const std::vector<unsigned int> & renumber = {})
2396 static_assert(dim >= 1 && dim <= 3,
"Only dim=1,2,3 implemented");
2404 const int n_shapes = poly.size();
2406 Assert(renumber.empty() || renumber.size() ==
values.size(),
2413 for (
unsigned int i = 0; i < renumber.size(); ++i)
2420 return std::make_pair((1. - p[0]) *
values[0] + p[0] *
values[1],
2425 const Number2 x0 = 1. - p[0], x1 = p[0];
2428 const Number3 mapped = (1. - p[1]) * tmp0 + p[1] * tmp1;
2430 derivative[0] = (1. - p[1]) * (
values[1] -
values[0]) +
2432 derivative[1] = tmp1 - tmp0;
2433 return std::make_pair(mapped, derivative);
2437 const Number2 x0 = 1. - p[0], x1 = p[0], y0 = 1. - p[1], y1 = p[1],
2438 z0 = 1. - p[2], z1 = p[2];
2441 const Number3 tmpy0 = y0 * tmp0 + y1 * tmp1;
2444 const Number3 tmpy1 = y0 * tmp2 + y1 * tmp3;
2445 const Number3 mapped = z0 * tmpy0 + z1 * tmpy1;
2447 derivative[2] = tmpy1 - tmpy0;
2448 derivative[1] = z0 * (tmp1 - tmp0) + z1 * (tmp3 - tmp2);
2454 return std::make_pair(mapped, derivative);
2459 std::array<Number2, 2 * dim * 200> shapes;
2462 for (
unsigned int d = 0;
d < dim; ++
d)
2463 for (
int i = 0; i < n_shapes; ++i)
2464 poly[i].
value(p[
d], 1, shapes.data() + 2 * (
d * n_shapes + i));
2468 std::pair<Number3, Tensor<1, dim, Number3>> result = {};
2469 for (
int i2 = 0, i = 0; i2 < (dim > 2 ? n_shapes : 1); ++i2)
2471 Number3 value_y = {}, deriv_x = {}, deriv_y = {};
2472 for (
int i1 = 0; i1 < (dim > 1 ? n_shapes : 1); ++i1)
2475 Number3
value = {}, deriv = {};
2479 if (renumber.empty())
2480 for (
int i0 = 0; i0 < n_shapes; ++i0, ++i)
2483 deriv += shapes[2 * i0 + 1] *
values[i];
2486 for (
int i0 = 0; i0 < n_shapes; ++i0, ++i)
2489 deriv += shapes[2 * i0 + 1] *
values[renumber[i]];
2495 value_y +=
value * shapes[2 * n_shapes + 2 * i1];
2496 deriv_x += deriv * shapes[2 * n_shapes + 2 * i1];
2497 deriv_y +=
value * shapes[2 * n_shapes + 2 * i1 + 1];
2501 result.first =
value;
2502 result.second[0] = deriv;
2508 result.first += value_y * shapes[4 * n_shapes + 2 * i2];
2509 result.second[0] += deriv_x * shapes[4 * n_shapes + 2 * i2];
2510 result.second[1] += deriv_y * shapes[4 * n_shapes + 2 * i2];
2511 result.second[2] += value_y * shapes[4 * n_shapes + 2 * i2 + 1];
2515 result.first = value_y;
2516 result.second[0] = deriv_x;
2517 result.second[1] = deriv_y;
2529 template <
int dim,
typename Number,
typename Number2>
2533 const Number2 & value,
2537 const std::vector<unsigned int> & renumber = {})
2539 static_assert(dim >= 1 && dim <= 3,
"Only dim=1,2,3 implemented");
2542 const int n_shapes = poly.size();
2544 Assert(renumber.empty() || renumber.size() ==
values.size(),
2548 std::array<Number, 2 * dim * 200> shapes;
2551 for (
unsigned int d = 0;
d < dim; ++
d)
2552 for (
int i = 0; i < n_shapes; ++i)
2553 poly[i].value(p[
d], 1, shapes.data() + 2 * (
d * n_shapes + i));
2556 for (
int i2 = 0, i = 0; i2 < (dim > 2 ? n_shapes : 1); ++i2)
2558 const Number2 test_value_z =
2559 dim > 2 ? (value * shapes[4 * n_shapes + 2 * i2] +
2560 gradient[2] * shapes[4 * n_shapes + 2 * i2 + 1]) :
2562 const Number2 test_grad_x =
2563 dim > 2 ? gradient[0] * shapes[4 * n_shapes + 2 * i2] : gradient[0];
2564 const Number2 test_grad_y =
2565 dim > 2 ? gradient[1] * shapes[4 * n_shapes + 2 * i2] :
2566 (dim > 1 ? gradient[1] : Number2());
2567 for (
int i1 = 0; i1 < (dim > 1 ? n_shapes : 1); ++i1)
2569 const Number2 test_value_y =
2570 dim > 1 ? (test_value_z * shapes[2 * n_shapes + 2 * i1] +
2571 test_grad_y * shapes[2 * n_shapes + 2 * i1 + 1]) :
2573 const Number2 test_grad_xy =
2574 dim > 1 ? test_grad_x * shapes[2 * n_shapes + 2 * i1] :
2576 if (renumber.empty())
2577 for (
int i0 = 0; i0 < n_shapes; ++i0, ++i)
2578 values[i] += shapes[2 * i0] * test_value_y +
2579 shapes[2 * i0 + 1] * test_grad_xy;
2581 for (
int i0 = 0; i0 < n_shapes; ++i0, ++i)
2582 values[renumber[i]] += shapes[2 * i0] * test_value_y +
2583 shapes[2 * i0 + 1] * test_grad_xy;
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcNotInitialized()
static ::ExceptionBase & ExcMessage(std::string arg1)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
VectorType::value_type * begin(VectorType &V)
constexpr T pow(const T base, const int iexp)
void integrate_add_tensor_product_value_and_gradient(const std::vector< Polynomials::Polynomial< double > > &poly, const Number2 &value, const Tensor< 1, dim, Number2 > &gradient, const Point< dim, Number > &p, AlignedVector< Number2 > &values, const std::vector< unsigned int > &renumber={})
std::pair< typename ProductTypeNoPoint< Number, Number2 >::type, Tensor< 1, dim, typename ProductTypeNoPoint< Number, Number2 >::type > > evaluate_tensor_product_value_and_gradient(const std::vector< Polynomials::Polynomial< double > > &poly, const std::vector< Number > &values, const Point< dim, Number2 > &p, const bool d_linear=false, const std::vector< unsigned int > &renumber={})
@ evaluate_symmetric_hierarchical
static const unsigned int invalid_unsigned_int
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &, const Number p)
typename internal::ProductTypeImpl< typename std::decay< T >::type, typename std::decay< U >::type >::type type
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)
void hessians_one_line(const Number in[], Number out[]) const
EvaluatorTensorProduct(const AlignedVector< Number2 > &shape_values)
void gradients_one_line(const Number in[], Number out[]) const
const Number2 * shape_values
const Number2 * shape_hessians
const Number2 * shape_gradients
void values_one_line(const Number in[], Number out[]) const
void values(const Number in[], Number out[]) const
void gradients(const Number in[], Number out[]) const
void hessians(const Number in[], Number out[]) const
EvaluatorTensorProduct(const Number2 *shape_values, const Number2 *shape_gradients, const Number2 *shape_hessians, const unsigned int n_rows, const unsigned int n_columns)
const unsigned int n_columns
const Number2 * shape_gradients
void hessians_one_line(const Number in[], Number out[]) const
void gradients(const Number *in, Number *out) const
void values_one_line(const Number in[], Number out[]) const
void gradients_one_line(const Number in[], Number out[]) const
const Number2 * shape_values
void values(const Number *in, Number *out) const
const Number2 * shape_hessians
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)
const unsigned int n_rows
void hessians(const Number *in, Number *out) const
void gradients(const Number in[], Number out[]) const
const 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)
const Number2 * shape_gradients
void values(const Number in[], Number out[]) const
void hessians(const Number in[], Number out[]) const
void hessians_one_line(const Number in[], Number out[]) const
void values_one_line(const Number in[], Number out[]) const
const Number2 * shape_hessians
void gradients_one_line(const Number in[], Number out[]) const
const Number2 * shape_gradients
const Number2 * shape_hessians
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)
const Number2 * shape_values
const Number2 * shape_hessians
void gradients(const Number in[], Number out[]) const
void values(const Number in[], Number out[]) const
void hessians_one_line(const Number in[], Number out[]) const
EvaluatorTensorProduct(const AlignedVector< Number > &shape_values)
void values_one_line(const Number in[], Number out[]) const
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)
void gradients_one_line(const Number in[], Number out[]) const
void hessians(const Number in[], Number out[]) const
const Number2 * shape_gradients
const Number2 * shape_values
typename ProductType< Tensor< 1, dim, Number >, Number2 >::type type
typename ProductType< Number, Number2 >::type type