17#ifndef dealii_matrix_free_tensor_product_kernels_h
18#define dealii_matrix_free_tensor_product_kernels_h
122 typename Number2 = Number>
154 typename Number2 = Number>
189 static constexpr unsigned int n_rows_of_product =
191 static constexpr unsigned int n_columns_of_product =
199 : shape_values(nullptr)
200 , shape_gradients(nullptr)
201 , shape_hessians(nullptr)
210 const unsigned int dummy1 = 0,
211 const unsigned int dummy2 = 0)
212 : shape_values(shape_values.begin())
213 , shape_gradients(shape_gradients.begin())
214 , shape_hessians(shape_hessians.begin())
221 shape_values.
size() == n_rows * n_columns ||
222 shape_values.
size() == 3 * n_rows,
225 shape_gradients.
size() == n_rows * n_columns,
228 shape_hessians.
size() == n_rows * n_columns,
234 template <
int direction,
bool contract_over_rows,
bool add>
236 values(
const Number in[], Number out[])
const
238 apply<direction, contract_over_rows, add>(shape_values, in, out);
241 template <
int direction,
bool contract_over_rows,
bool add>
245 apply<direction, contract_over_rows, add>(shape_gradients, in, out);
248 template <
int direction,
bool contract_over_rows,
bool add>
252 apply<direction, contract_over_rows, add>(shape_hessians, in, out);
255 template <
int direction,
bool contract_over_rows,
bool add>
260 apply<direction, contract_over_rows, add, true>(shape_values, in, out);
263 template <
int direction,
bool contract_over_rows,
bool add>
268 apply<direction, contract_over_rows, add, true>(shape_gradients, in, out);
271 template <
int direction,
bool contract_over_rows,
bool add>
276 apply<direction, contract_over_rows, add, true>(shape_hessians, in, out);
303 template <
int direction,
304 bool contract_over_rows,
306 bool one_line =
false>
341 template <
int face_direction,
342 bool contract_onto_face,
362 template <
int direction,
bool contract_over_rows,
bool add,
bool one_line>
374 static_assert(one_line ==
false || direction == dim - 1,
375 "Single-line evaluation only works for direction=dim-1.");
376 Assert(shape_data !=
nullptr,
378 "The given array shape_data must not be the null pointer!"));
379 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
381 ExcMessage(
"In-place operation only supported for "
382 "n_rows==n_columns or single-line interpolation"));
384 constexpr int mm = contract_over_rows ? n_rows : n_columns,
385 nn = contract_over_rows ? n_columns : n_rows;
388 constexpr int n_blocks1 = one_line ? 1 : stride;
389 constexpr int n_blocks2 =
390 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
392 for (
int i2 = 0; i2 < n_blocks2; ++i2)
394 for (
int i1 = 0; i1 < n_blocks1; ++i1)
397 for (
int i = 0; i < mm; ++i)
398 x[i] = in[stride * i];
399 for (
int col = 0; col < nn; ++col)
402 if (contract_over_rows ==
true)
403 val0 = shape_data[col];
405 val0 = shape_data[col * n_columns];
406 Number res0 = val0 * x[0];
407 for (
int i = 1; i < mm; ++i)
409 if (contract_over_rows ==
true)
410 val0 = shape_data[i * n_columns + col];
412 val0 = shape_data[col * n_columns + i];
416 out[stride * col] += res0;
418 out[stride * col] = res0;
421 if (one_line ==
false)
427 if (one_line ==
false)
429 in += stride * (mm - 1);
430 out += stride * (nn - 1);
442 template <
int face_direction,
443 bool contract_onto_face,
457 static_assert(max_derivative >= 0 && max_derivative < 3,
458 "Only derivative orders 0-2 implemented");
459 Assert(shape_values !=
nullptr,
461 "The given array shape_values must not be the null pointer."));
463 constexpr int n_blocks1 = (dim > 1 ? n_rows : 1);
464 constexpr int n_blocks2 = (dim > 2 ? n_rows : 1);
471 for (
int i2 = 0; i2 < n_blocks2; ++i2)
473 for (
int i1 = 0; i1 < n_blocks1; ++i1)
475 if (contract_onto_face ==
true)
477 Number res0 = shape_values[0] * in[0];
479 if (max_derivative > 0)
480 res1 = shape_values[n_rows] * in[0];
481 if (max_derivative > 1)
482 res2 = shape_values[2 * n_rows] * in[0];
483 for (
int ind = 1; ind < n_rows; ++ind)
485 res0 += shape_values[ind] * in[in_stride * ind];
486 if (max_derivative > 0)
487 res1 += shape_values[ind + n_rows] * in[in_stride * ind];
488 if (max_derivative > 1)
490 shape_values[ind + 2 * n_rows] * in[in_stride * ind];
495 if (max_derivative > 0)
496 out[out_stride] += res1;
497 if (max_derivative > 1)
498 out[2 * out_stride] += res2;
503 if (max_derivative > 0)
504 out[out_stride] = res1;
505 if (max_derivative > 1)
506 out[2 * out_stride] = res2;
511 for (
int col = 0; col < n_rows; ++col)
514 out[col * in_stride] += shape_values[col] * in[0];
516 out[col * in_stride] = shape_values[col] * in[0];
517 if (max_derivative > 0)
518 out[col * in_stride] +=
519 shape_values[col + n_rows] * in[out_stride];
520 if (max_derivative > 1)
521 out[col * in_stride] +=
522 shape_values[col + 2 * n_rows] * in[2 * out_stride];
529 switch (face_direction)
532 in += contract_onto_face ? n_rows : 1;
533 out += contract_onto_face ? 1 : n_rows;
543 if (contract_onto_face)
559 if (face_direction == 1 && dim == 3)
561 if (contract_onto_face)
563 in += n_rows * (n_rows - 1);
564 out -= n_rows * n_rows - 1;
568 out += n_rows * (n_rows - 1);
569 in -= n_rows * n_rows - 1;
590 template <
int dim,
typename Number,
typename Number2>
593 static constexpr unsigned int n_rows_of_product =
595 static constexpr unsigned int n_columns_of_product =
603 : shape_values(nullptr)
604 , shape_gradients(nullptr)
605 , shape_hessians(nullptr)
606 , n_rows(
numbers::invalid_unsigned_int)
607 , n_columns(
numbers::invalid_unsigned_int)
616 const unsigned int n_rows,
617 const unsigned int n_columns)
618 : shape_values(shape_values.begin())
619 , shape_gradients(shape_gradients.begin())
620 , shape_hessians(shape_hessians.begin())
622 , n_columns(n_columns)
629 shape_values.
size() == n_rows * n_columns ||
630 shape_values.
size() == n_rows * 3,
633 shape_gradients.
size() == n_rows * n_columns,
636 shape_hessians.
size() == n_rows * n_columns,
644 const Number2 * shape_gradients,
645 const Number2 * shape_hessians,
646 const unsigned int n_rows,
647 const unsigned int n_columns)
648 : shape_values(shape_values)
649 , shape_gradients(shape_gradients)
650 , shape_hessians(shape_hessians)
652 , n_columns(n_columns)
655 template <
int direction,
bool contract_over_rows,
bool add>
657 values(
const Number *in, Number *out)
const
659 apply<direction, contract_over_rows, add>(shape_values, in, out);
662 template <
int direction,
bool contract_over_rows,
bool add>
666 apply<direction, contract_over_rows, add>(shape_gradients, in, out);
669 template <
int direction,
bool contract_over_rows,
bool add>
673 apply<direction, contract_over_rows, add>(shape_hessians, in, out);
676 template <
int direction,
bool contract_over_rows,
bool add>
681 apply<direction, contract_over_rows, add, true>(shape_values, in, out);
684 template <
int direction,
bool contract_over_rows,
bool add>
689 apply<direction, contract_over_rows, add, true>(shape_gradients, in, out);
692 template <
int direction,
bool contract_over_rows,
bool add>
697 apply<direction, contract_over_rows, add, true>(shape_hessians, in, out);
700 template <
int direction,
701 bool contract_over_rows,
703 bool one_line =
false>
709 template <
int face_direction,
710 bool contract_onto_face,
726 template <
int dim,
typename Number,
typename Number2>
727 template <
int direction,
bool contract_over_rows,
bool add,
bool one_line>
734 static_assert(one_line ==
false || direction == dim - 1,
735 "Single-line evaluation only works for direction=dim-1.");
736 Assert(shape_data !=
nullptr,
738 "The given array shape_data must not be the null pointer!"));
739 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
741 ExcMessage(
"In-place operation only supported for "
742 "n_rows==n_columns or single-line interpolation"));
744 const int mm = contract_over_rows ? n_rows : n_columns,
745 nn = contract_over_rows ? n_columns : n_rows;
748 direction == 0 ? 1 : Utilities::fixed_power<direction>(n_columns);
749 const int n_blocks1 = one_line ? 1 : stride;
750 const int n_blocks2 = direction >= dim - 1 ?
760 if (contract_over_rows && n_rows == 2)
762 const Number2 *shape_data_1 = shape_data + n_columns;
763 for (
int i2 = 0; i2 < n_blocks2; ++i2)
765 for (
int i1 = 0; i1 < n_blocks1; ++i1)
767 const Number x0 = in[0], x1 = in[stride];
768 for (
int col = 0; col < nn; ++col)
770 const Number result =
771 shape_data[col] * x0 + shape_data_1[col] * x1;
773 out[stride * col] += result;
775 out[stride * col] = result;
778 if (one_line ==
false)
784 if (one_line ==
false)
786 in += stride * (mm - 1);
787 out += stride * (nn - 1);
792 else if (contract_over_rows && n_rows == 3)
794 const Number2 *shape_data_1 = shape_data + n_columns;
795 const Number2 *shape_data_2 = shape_data + 2 * n_columns;
796 for (
int i2 = 0; i2 < n_blocks2; ++i2)
798 for (
int i1 = 0; i1 < n_blocks1; ++i1)
800 const Number x0 = in[0], x1 = in[stride], x2 = in[2 * stride];
801 for (
int col = 0; col < nn; ++col)
803 const Number result = shape_data[col] * x0 +
804 shape_data_1[col] * x1 +
805 shape_data_2[col] * x2;
807 out[stride * col] += result;
809 out[stride * col] = result;
812 if (one_line ==
false)
818 if (one_line ==
false)
820 in += stride * (mm - 1);
821 out += stride * (nn - 1);
827 for (
int i2 = 0; i2 < n_blocks2; ++i2)
829 for (
int i1 = 0; i1 < n_blocks1; ++i1)
832 for (
int i = 0; i < mm; ++i)
833 x[i] = in[stride * i];
834 for (
int col = 0; col < nn; ++col)
837 if (contract_over_rows ==
true)
838 val0 = shape_data[col];
840 val0 = shape_data[col * n_columns];
841 Number res0 = val0 * x[0];
842 for (
int i = 1; i < mm; ++i)
844 if (contract_over_rows ==
true)
845 val0 = shape_data[i * n_columns + col];
847 val0 = shape_data[col * n_columns + i];
851 out[stride * col] += res0;
853 out[stride * col] = res0;
856 if (one_line ==
false)
862 if (one_line ==
false)
864 in += stride * (mm - 1);
865 out += stride * (nn - 1);
872 template <
int dim,
typename Number,
typename Number2>
873 template <
int face_direction,
874 bool contract_onto_face,
882 Assert(shape_values !=
nullptr,
884 "The given array shape_data must not be the null pointer!"));
885 static_assert(dim > 0 && dim < 4,
"Only dim=1,2,3 supported");
886 const int n_blocks1 = dim > 1 ? n_rows : 1;
887 const int n_blocks2 = dim > 2 ? n_rows : 1;
890 const int in_stride =
891 face_direction > 0 ? Utilities::fixed_power<face_direction>(n_rows) : 1;
892 const int out_stride =
895 for (
int i2 = 0; i2 < n_blocks2; ++i2)
897 for (
int i1 = 0; i1 < n_blocks1; ++i1)
899 if (contract_onto_face ==
true)
901 Number res0 = shape_values[0] * in[0];
903 if (max_derivative > 0)
904 res1 = shape_values[n_rows] * in[0];
905 if (max_derivative > 1)
906 res2 = shape_values[2 * n_rows] * in[0];
907 for (
unsigned int ind = 1; ind < n_rows; ++ind)
909 res0 += shape_values[ind] * in[in_stride * ind];
910 if (max_derivative > 0)
911 res1 += shape_values[ind + n_rows] * in[in_stride * ind];
912 if (max_derivative > 1)
914 shape_values[ind + 2 * n_rows] * in[in_stride * ind];
919 if (max_derivative > 0)
920 out[out_stride] += res1;
921 if (max_derivative > 1)
922 out[2 * out_stride] += res2;
927 if (max_derivative > 0)
928 out[out_stride] = res1;
929 if (max_derivative > 1)
930 out[2 * out_stride] = res2;
935 for (
unsigned int col = 0; col < n_rows; ++col)
938 out[col * in_stride] += shape_values[col] * in[0];
940 out[col * in_stride] = shape_values[col] * in[0];
941 if (max_derivative > 0)
942 out[col * in_stride] +=
943 shape_values[col + n_rows] * in[out_stride];
944 if (max_derivative > 1)
945 out[col * in_stride] +=
946 shape_values[col + 2 * n_rows] * in[2 * out_stride];
953 switch (face_direction)
956 in += contract_onto_face ? n_rows : 1;
957 out += contract_onto_face ? 1 : n_rows;
967 if (contract_onto_face)
981 if (face_direction == 1 && dim == 3)
984 if (contract_onto_face)
986 in += n_rows * (n_rows - 1);
987 out -= n_rows * n_rows - 1;
991 out += n_rows * (n_rows - 1);
992 in -= n_rows * n_rows - 1;
1032 static constexpr unsigned int n_rows_of_product =
1034 static constexpr unsigned int n_columns_of_product =
1043 const unsigned int dummy1 = 0,
1044 const unsigned int dummy2 = 0)
1045 : shape_values(shape_values.begin())
1046 , shape_gradients(shape_gradients.begin())
1047 , shape_hessians(shape_hessians.begin())
1050 shape_values.
size() == n_rows * n_columns,
1053 shape_gradients.
size() == n_rows * n_columns,
1056 shape_hessians.
size() == n_rows * n_columns,
1062 template <
int direction,
bool contract_over_rows,
bool add>
1064 values(
const Number in[], Number out[])
const;
1066 template <
int direction,
bool contract_over_rows,
bool add>
1068 gradients(
const Number in[], Number out[])
const;
1070 template <
int direction,
bool contract_over_rows,
bool add>
1072 hessians(
const Number in[], Number out[])
const;
1105 template <
int direction,
bool contract_over_rows,
bool add>
1112 Number2>::values(
const Number in[], Number out[])
const
1116 constexpr int mm = contract_over_rows ? n_rows : n_columns,
1117 nn = contract_over_rows ? n_columns : n_rows;
1118 constexpr int n_cols = nn / 2;
1119 constexpr int mid = mm / 2;
1122 constexpr int n_blocks1 = stride;
1123 constexpr int n_blocks2 =
1124 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
1126 for (
int i2 = 0; i2 < n_blocks2; ++i2)
1128 for (
int i1 = 0; i1 < n_blocks1; ++i1)
1130 for (
int col = 0; col < n_cols; ++col)
1133 Number in0, in1, res0, res1;
1134 if (contract_over_rows ==
true)
1136 val0 = shape_values[col];
1137 val1 = shape_values[nn - 1 - col];
1141 val0 = shape_values[col * n_columns];
1142 val1 = shape_values[(col + 1) * n_columns - 1];
1147 in1 = in[stride * (mm - 1)];
1152 for (
int ind = 1; ind < mid; ++ind)
1154 if (contract_over_rows ==
true)
1156 val0 = shape_values[ind * n_columns + col];
1157 val1 = shape_values[ind * n_columns + nn - 1 - col];
1161 val0 = shape_values[col * n_columns + ind];
1163 shape_values[(col + 1) * n_columns - 1 - ind];
1165 in0 = in[stride * ind];
1166 in1 = in[stride * (mm - 1 - ind)];
1174 res0 = res1 = Number();
1175 if (contract_over_rows ==
true)
1179 val0 = shape_values[mid * n_columns + col];
1180 in1 = val0 * in[stride * mid];
1187 if (mm % 2 == 1 && nn % 2 == 0)
1189 val0 = shape_values[col * n_columns + mid];
1190 in1 = val0 * in[stride * mid];
1197 out[stride * col] += res0;
1198 out[stride * (nn - 1 - col)] += res1;
1202 out[stride * col] = res0;
1203 out[stride * (nn - 1 - col)] = res1;
1206 if (contract_over_rows ==
true && nn % 2 == 1 && mm % 2 == 1)
1209 out[stride * n_cols] += in[stride * mid];
1211 out[stride * n_cols] = in[stride * mid];
1213 else if (contract_over_rows ==
true && nn % 2 == 1)
1216 Number2 val0 = shape_values[n_cols];
1219 res0 = val0 * (in[0] + in[stride * (mm - 1)]);
1220 for (
int ind = 1; ind < mid; ++ind)
1222 val0 = shape_values[ind * n_columns + n_cols];
1223 res0 += val0 * (in[stride * ind] +
1224 in[stride * (mm - 1 - ind)]);
1230 out[stride * n_cols] += res0;
1232 out[stride * n_cols] = res0;
1234 else if (contract_over_rows ==
false && nn % 2 == 1)
1239 Number2 val0 = shape_values[n_cols * n_columns];
1240 res0 = val0 * (in[0] + in[stride * (mm - 1)]);
1241 for (
int ind = 1; ind < mid; ++ind)
1243 val0 = shape_values[n_cols * n_columns + ind];
1244 Number in1 = val0 * (in[stride * ind] +
1245 in[stride * (mm - 1 - ind)]);
1249 res0 += in[stride * mid];
1254 out[stride * n_cols] += res0;
1256 out[stride * n_cols] = res0;
1262 in += stride * (mm - 1);
1263 out += stride * (nn - 1);
1293 template <
int direction,
bool contract_over_rows,
bool add>
1300 Number2>::gradients(
const Number in[],
1305 constexpr int mm = contract_over_rows ? n_rows : n_columns,
1306 nn = contract_over_rows ? n_columns : n_rows;
1307 constexpr int n_cols = nn / 2;
1308 constexpr int mid = mm / 2;
1311 constexpr int n_blocks1 = stride;
1312 constexpr int n_blocks2 =
1313 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
1315 for (
int i2 = 0; i2 < n_blocks2; ++i2)
1317 for (
int i1 = 0; i1 < n_blocks1; ++i1)
1319 for (
int col = 0; col < n_cols; ++col)
1322 Number in0, in1, res0, res1;
1323 if (contract_over_rows ==
true)
1325 val0 = shape_gradients[col];
1326 val1 = shape_gradients[nn - 1 - col];
1330 val0 = shape_gradients[col * n_columns];
1331 val1 = shape_gradients[(nn - col - 1) * n_columns];
1336 in1 = in[stride * (mm - 1)];
1341 for (
int ind = 1; ind < mid; ++ind)
1343 if (contract_over_rows ==
true)
1345 val0 = shape_gradients[ind * n_columns + col];
1347 shape_gradients[ind * n_columns + nn - 1 - col];
1351 val0 = shape_gradients[col * n_columns + ind];
1353 shape_gradients[(nn - col - 1) * n_columns + ind];
1355 in0 = in[stride * ind];
1356 in1 = in[stride * (mm - 1 - ind)];
1364 res0 = res1 = Number();
1367 if (contract_over_rows ==
true)
1368 val0 = shape_gradients[mid * n_columns + col];
1370 val0 = shape_gradients[col * n_columns + mid];
1371 in1 = val0 * in[stride * mid];
1377 out[stride * col] += res0;
1378 out[stride * (nn - 1 - col)] += res1;
1382 out[stride * col] = res0;
1383 out[stride * (nn - 1 - col)] = res1;
1390 if (contract_over_rows ==
true)
1391 val0 = shape_gradients[n_cols];
1393 val0 = shape_gradients[n_cols * n_columns];
1394 res0 = val0 * (in[0] - in[stride * (mm - 1)]);
1395 for (
int ind = 1; ind < mid; ++ind)
1397 if (contract_over_rows ==
true)
1398 val0 = shape_gradients[ind * n_columns + n_cols];
1400 val0 = shape_gradients[n_cols * n_columns + ind];
1402 val0 * (in[stride * ind] - in[stride * (mm - 1 - ind)]);
1406 out[stride * n_cols] += res0;
1408 out[stride * n_cols] = res0;
1414 in += stride * (mm - 1);
1415 out += stride * (nn - 1);
1429 template <
int direction,
bool contract_over_rows,
bool add>
1436 Number2>::hessians(
const Number in[],
1441 constexpr int mm = contract_over_rows ? n_rows : n_columns;
1442 constexpr int nn = contract_over_rows ? n_columns : n_rows;
1443 constexpr int n_cols = nn / 2;
1444 constexpr int mid = mm / 2;
1447 constexpr int n_blocks1 = stride;
1448 constexpr int n_blocks2 =
1449 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
1451 for (
int i2 = 0; i2 < n_blocks2; ++i2)
1453 for (
int i1 = 0; i1 < n_blocks1; ++i1)
1455 for (
int col = 0; col < n_cols; ++col)
1458 Number in0, in1, res0, res1;
1459 if (contract_over_rows ==
true)
1461 val0 = shape_hessians[col];
1462 val1 = shape_hessians[nn - 1 - col];
1466 val0 = shape_hessians[col * n_columns];
1467 val1 = shape_hessians[(col + 1) * n_columns - 1];
1472 in1 = in[stride * (mm - 1)];
1477 for (
int ind = 1; ind < mid; ++ind)
1479 if (contract_over_rows ==
true)
1481 val0 = shape_hessians[ind * n_columns + col];
1483 shape_hessians[ind * n_columns + nn - 1 - col];
1487 val0 = shape_hessians[col * n_columns + ind];
1489 shape_hessians[(col + 1) * n_columns - 1 - ind];
1491 in0 = in[stride * ind];
1492 in1 = in[stride * (mm - 1 - ind)];
1500 res0 = res1 = Number();
1503 if (contract_over_rows ==
true)
1504 val0 = shape_hessians[mid * n_columns + col];
1506 val0 = shape_hessians[col * n_columns + mid];
1507 in1 = val0 * in[stride * mid];
1513 out[stride * col] += res0;
1514 out[stride * (nn - 1 - col)] += res1;
1518 out[stride * col] = res0;
1519 out[stride * (nn - 1 - col)] = res1;
1526 if (contract_over_rows ==
true)
1527 val0 = shape_hessians[n_cols];
1529 val0 = shape_hessians[n_cols * n_columns];
1532 res0 = val0 * (in[0] + in[stride * (mm - 1)]);
1533 for (
int ind = 1; ind < mid; ++ind)
1535 if (contract_over_rows ==
true)
1536 val0 = shape_hessians[ind * n_columns + n_cols];
1538 val0 = shape_hessians[n_cols * n_columns + ind];
1539 Number in1 = val0 * (in[stride * ind] +
1540 in[stride * (mm - 1 - ind)]);
1548 if (contract_over_rows ==
true)
1549 val0 = shape_hessians[mid * n_columns + n_cols];
1551 val0 = shape_hessians[n_cols * n_columns + mid];
1552 res0 += val0 * in[stride * mid];
1555 out[stride * n_cols] += res0;
1557 out[stride * n_cols] = res0;
1563 in += stride * (mm - 1);
1564 out += stride * (nn - 1);
1613 static constexpr unsigned int n_rows_of_product =
1615 static constexpr unsigned int n_columns_of_product =
1624 : shape_values(nullptr)
1625 , shape_gradients(nullptr)
1626 , shape_hessians(nullptr)
1634 : shape_values(shape_values.begin())
1635 , shape_gradients(nullptr)
1636 , shape_hessians(nullptr)
1648 const unsigned int dummy1 = 0,
1649 const unsigned int dummy2 = 0)
1650 : shape_values(shape_values.begin())
1651 , shape_gradients(shape_gradients.begin())
1652 , shape_hessians(shape_hessians.begin())
1656 if (!shape_values.
empty())
1658 if (!shape_gradients.
empty())
1660 if (!shape_hessians.
empty())
1666 template <
int direction,
bool contract_over_rows,
bool add>
1668 values(
const Number in[], Number out[])
const
1671 apply<direction, contract_over_rows, add, 0>(shape_values, in, out);
1674 template <
int direction,
bool contract_over_rows,
bool add>
1679 apply<direction, contract_over_rows, add, 1>(shape_gradients, in, out);
1682 template <
int direction,
bool contract_over_rows,
bool add>
1687 apply<direction, contract_over_rows, add, 2>(shape_hessians, in, out);
1690 template <
int direction,
bool contract_over_rows,
bool add>
1695 apply<direction, contract_over_rows, add, 0, true>(shape_values, in, out);
1698 template <
int direction,
bool contract_over_rows,
bool add>
1703 apply<direction, contract_over_rows, add, 1, true>(shape_gradients,
1708 template <
int direction,
bool contract_over_rows,
bool add>
1713 apply<direction, contract_over_rows, add, 2, true>(shape_hessians,
1746 template <
int direction,
1747 bool contract_over_rows,
1750 bool one_line =
false>
1769 template <
int direction,
1770 bool contract_over_rows,
1784 static_assert(type < 3,
"Only three variants type=0,1,2 implemented");
1785 static_assert(one_line ==
false || direction == dim - 1,
1786 "Single-line evaluation only works for direction=dim-1.");
1787 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
1789 ExcMessage(
"In-place operation only supported for "
1790 "n_rows==n_columns or single-line interpolation"));
1796 constexpr int nn = contract_over_rows ? n_columns : n_rows;
1797 constexpr int mm = contract_over_rows ? n_rows : n_columns;
1798 constexpr int n_cols = nn / 2;
1799 constexpr int mid = mm / 2;
1802 constexpr int n_blocks1 = one_line ? 1 : stride;
1803 constexpr int n_blocks2 =
1804 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
1806 constexpr int offset = (n_columns + 1) / 2;
1812 for (
int i2 = 0; i2 < n_blocks2; ++i2)
1814 for (
int i1 = 0; i1 < n_blocks1; ++i1)
1816 Number xp[mid > 0 ? mid : 1], xm[mid > 0 ? mid : 1];
1817 for (
int i = 0; i < mid; ++i)
1819 if (contract_over_rows ==
true && type == 1)
1821 xp[i] = in[stride * i] - in[stride * (mm - 1 - i)];
1822 xm[i] = in[stride * i] + in[stride * (mm - 1 - i)];
1826 xp[i] = in[stride * i] + in[stride * (mm - 1 - i)];
1827 xm[i] = in[stride * i] - in[stride * (mm - 1 - i)];
1830 Number xmid = in[stride * mid];
1831 for (
int col = 0; col < n_cols; ++col)
1836 if (contract_over_rows ==
true)
1838 r0 = shapes[col] * xp[0];
1839 r1 = shapes[(n_rows - 1) * offset + col] * xm[0];
1843 r0 = shapes[col * offset] * xp[0];
1844 r1 = shapes[(n_rows - 1 - col) * offset] * xm[0];
1846 for (
int ind = 1; ind < mid; ++ind)
1848 if (contract_over_rows ==
true)
1850 r0 += shapes[ind * offset + col] * xp[ind];
1851 r1 += shapes[(n_rows - 1 - ind) * offset + col] *
1856 r0 += shapes[col * offset + ind] * xp[ind];
1857 r1 += shapes[(n_rows - 1 - col) * offset + ind] *
1864 if (mm % 2 == 1 && contract_over_rows ==
true)
1867 r1 += shapes[mid * offset + col] * xmid;
1869 r0 += shapes[mid * offset + col] * xmid;
1871 else if (mm % 2 == 1 && (nn % 2 == 0 || type > 0 || mm == 3))
1872 r0 += shapes[col * offset + mid] * xmid;
1876 out[stride * col] += r0 + r1;
1877 if (type == 1 && contract_over_rows ==
false)
1878 out[stride * (nn - 1 - col)] += r1 - r0;
1880 out[stride * (nn - 1 - col)] += r0 - r1;
1884 out[stride * col] = r0 + r1;
1885 if (type == 1 && contract_over_rows ==
false)
1886 out[stride * (nn - 1 - col)] = r1 - r0;
1888 out[stride * (nn - 1 - col)] = r0 - r1;
1891 if (type == 0 && contract_over_rows ==
true && nn % 2 == 1 &&
1892 mm % 2 == 1 && mm > 3)
1895 out[stride * n_cols] += shapes[mid * offset + n_cols] * xmid;
1897 out[stride * n_cols] = shapes[mid * offset + n_cols] * xmid;
1899 else if (contract_over_rows ==
true && nn % 2 == 1)
1904 r0 = shapes[n_cols] * xp[0];
1905 for (
int ind = 1; ind < mid; ++ind)
1906 r0 += shapes[ind * offset + n_cols] * xp[ind];
1910 if (type != 1 && mm % 2 == 1)
1911 r0 += shapes[mid * offset + n_cols] * xmid;
1914 out[stride * n_cols] += r0;
1916 out[stride * n_cols] = r0;
1918 else if (contract_over_rows ==
false && nn % 2 == 1)
1925 r0 = shapes[n_cols * offset] * xm[0];
1926 for (
int ind = 1; ind < mid; ++ind)
1927 r0 += shapes[n_cols * offset + ind] * xm[ind];
1931 r0 = shapes[n_cols * offset] * xp[0];
1932 for (
int ind = 1; ind < mid; ++ind)
1933 r0 += shapes[n_cols * offset + ind] * xp[ind];
1939 if ((type == 0 || type == 2) && mm % 2 == 1)
1940 r0 += shapes[n_cols * offset + mid] * xmid;
1943 out[stride * n_cols] += r0;
1945 out[stride * n_cols] = r0;
1947 if (one_line ==
false)
1953 if (one_line ==
false)
1955 in += stride * (mm - 1);
1956 out += stride * (nn - 1);
2003 static constexpr unsigned int n_rows_of_product =
2005 static constexpr unsigned int n_columns_of_product =
2014 : shape_values(nullptr)
2015 , shape_gradients(nullptr)
2016 , shape_hessians(nullptr)
2024 : shape_values(shape_values.begin())
2025 , shape_gradients(nullptr)
2026 , shape_hessians(nullptr)
2036 const unsigned int dummy1 = 0,
2037 const unsigned int dummy2 = 0)
2038 : shape_values(shape_values.begin())
2039 , shape_gradients(shape_gradients.begin())
2040 , shape_hessians(shape_hessians.begin())
2046 template <
int direction,
bool contract_over_rows,
bool add>
2048 values(
const Number in[], Number out[])
const
2051 apply<direction, contract_over_rows, add, 0>(shape_values, in, out);
2054 template <
int direction,
bool contract_over_rows,
bool add>
2059 apply<direction, contract_over_rows, add, 1>(shape_gradients, in, out);
2062 template <
int direction,
bool contract_over_rows,
bool add>
2067 apply<direction, contract_over_rows, add, 0>(shape_hessians, in, out);
2070 template <
int direction,
bool contract_over_rows,
bool add>
2075 apply<direction, contract_over_rows, add, 0, true>(shape_values, in, out);
2078 template <
int direction,
bool contract_over_rows,
bool add>
2083 apply<direction, contract_over_rows, add, 1, true>(shape_gradients,
2088 template <
int direction,
bool contract_over_rows,
bool add>
2093 apply<direction, contract_over_rows, add, 0, true>(shape_hessians,
2125 template <
int direction,
2126 bool contract_over_rows,
2129 bool one_line =
false>
2148 template <
int direction,
2149 bool contract_over_rows,
2163 static_assert(one_line ==
false || direction == dim - 1,
2164 "Single-line evaluation only works for direction=dim-1.");
2166 type == 0 || type == 1,
2167 "Only types 0 and 1 implemented for evaluate_symmetric_hierarchical.");
2168 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
2170 ExcMessage(
"In-place operation only supported for "
2171 "n_rows==n_columns or single-line interpolation"));
2177 constexpr int nn = contract_over_rows ? n_columns : n_rows;
2178 constexpr int mm = contract_over_rows ? n_rows : n_columns;
2179 constexpr int n_cols = nn / 2;
2180 constexpr int mid = mm / 2;
2183 constexpr int n_blocks1 = one_line ? 1 : stride;
2184 constexpr int n_blocks2 =
2185 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
2191 for (
int i2 = 0; i2 < n_blocks2; ++i2)
2193 for (
int i1 = 0; i1 < n_blocks1; ++i1)
2195 if (contract_over_rows)
2198 for (
unsigned int i = 0; i < mm; ++i)
2199 x[i] = in[stride * i];
2200 for (
unsigned int col = 0; col < n_cols; ++col)
2205 r0 = shapes[col] * x[0];
2206 r1 = shapes[col + n_columns] * x[1];
2207 for (
unsigned int ind = 1; ind < mid; ++ind)
2210 shapes[col + 2 * ind * n_columns] * x[2 * ind];
2211 r1 += shapes[col + (2 * ind + 1) * n_columns] *
2218 r0 += shapes[col + (mm - 1) * n_columns] * x[mm - 1];
2221 out[stride * col] += r0 + r1;
2223 out[stride * (nn - 1 - col)] += r1 - r0;
2225 out[stride * (nn - 1 - col)] += r0 - r1;
2229 out[stride * col] = r0 + r1;
2231 out[stride * (nn - 1 - col)] = r1 - r0;
2233 out[stride * (nn - 1 - col)] = r0 - r1;
2239 const unsigned int shift = type == 1 ? 1 : 0;
2242 r0 = shapes[n_cols + shift * n_columns] * x[shift];
2243 for (
unsigned int ind = 1; ind < mid; ++ind)
2244 r0 += shapes[n_cols + (2 * ind + shift) * n_columns] *
2249 if (type != 1 && mm % 2 == 1)
2250 r0 += shapes[n_cols + (mm - 1) * n_columns] * x[mm - 1];
2252 out[stride * n_cols] += r0;
2254 out[stride * n_cols] = r0;
2259 Number xp[mid + 1], xm[mid > 0 ? mid : 1];
2260 for (
int i = 0; i < mid; ++i)
2263 xp[i] = in[stride * i] + in[stride * (mm - 1 - i)];
2264 xm[i] = in[stride * i] - in[stride * (mm - 1 - i)];
2268 xp[i] = in[stride * i] - in[stride * (mm - 1 - i)];
2269 xm[i] = in[stride * i] + in[stride * (mm - 1 - i)];
2272 xp[mid] = in[stride * mid];
2273 for (
unsigned int col = 0; col < n_cols; ++col)
2278 r0 = shapes[2 * col * n_columns] * xp[0];
2279 r1 = shapes[(2 * col + 1) * n_columns] * xm[0];
2280 for (
unsigned int ind = 1; ind < mid; ++ind)
2282 r0 += shapes[2 * col * n_columns + ind] * xp[ind];
2284 shapes[(2 * col + 1) * n_columns + ind] * xm[ind];
2293 shapes[(2 * col + 1) * n_columns + mid] * xp[mid];
2295 r0 += shapes[2 * col * n_columns + mid] * xp[mid];
2299 out[stride * (2 * col)] += r0;
2300 out[stride * (2 * col + 1)] += r1;
2304 out[stride * (2 * col)] = r0;
2305 out[stride * (2 * col + 1)] = r1;
2313 r0 = shapes[(nn - 1) * n_columns] * xp[0];
2314 for (
unsigned int ind = 1; ind < mid; ++ind)
2315 r0 += shapes[(nn - 1) * n_columns + ind] * xp[ind];
2319 if (mm % 2 == 1 && type == 0)
2320 r0 += shapes[(nn - 1) * n_columns + mid] * xp[mid];
2322 out[stride * (nn - 1)] += r0;
2324 out[stride * (nn - 1)] = r0;
2327 if (one_line ==
false)
2333 if (one_line ==
false)
2335 in += stride * (mm - 1);
2336 out += stride * (nn - 1);
2376 static constexpr unsigned int n_rows_of_product =
2378 static constexpr unsigned int n_columns_of_product =
2386 : shape_values(nullptr)
2387 , shape_gradients(nullptr)
2388 , shape_hessians(nullptr)
2398 const unsigned int dummy1 = 0,
2399 const unsigned int dummy2 = 0)
2400 : shape_values(shape_values.begin())
2401 , shape_gradients(shape_gradients.begin())
2402 , shape_hessians(shape_hessians.begin())
2409 shape_values.
size() == n_rows * n_columns ||
2410 shape_values.
size() == 3 * n_rows,
2413 shape_gradients.
size() == n_rows * n_columns,
2416 shape_hessians.
size() == n_rows * n_columns,
2422 template <
int direction,
bool contract_over_rows,
bool add>
2424 values(
const Number in[], Number out[])
const
2426 apply<direction, contract_over_rows, add>(shape_values, in, out);
2429 template <
int direction,
bool contract_over_rows,
bool add>
2433 apply<direction, contract_over_rows, add>(shape_gradients, in, out);
2436 template <
int direction,
bool contract_over_rows,
bool add>
2440 apply<direction, contract_over_rows, add>(shape_hessians, in, out);
2471 template <
int direction,
2472 bool contract_over_rows,
2474 bool one_line =
false>
2480 template <
int face_direction,
2481 bool contract_onto_face,
2500 template <
int direction,
bool contract_over_rows,
bool add,
bool one_line>
2513 static_assert(one_line ==
false || direction == dim - 1,
2514 "Single-line evaluation only works for direction=dim-1.");
2515 Assert(shape_data !=
nullptr,
2517 "The given array shape_data must not be the null pointer!"));
2518 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
2520 ExcMessage(
"In-place operation only supported for "
2521 "n_rows==n_columns or single-line interpolation"));
2523 constexpr int mm = contract_over_rows ? n_rows : n_columns,
2524 nn = contract_over_rows ? n_columns : n_rows;
2527 constexpr int n_blocks1 = one_line ? 1 : stride;
2530 constexpr int n_blocks2 =
2531 (dim - direction - 1 == 0) ?
2533 ((direction == normal_dir) ?
2535 (direction >= dim) ? 0 : dim - direction - 1) :
2536 (((direction < normal_dir) ? (n_rows + 1) : n_rows) *
2537 ((dim - direction == 3) ? n_rows : 1)));
2539 for (
int i2 = 0; i2 < n_blocks2; ++i2)
2541 for (
int i1 = 0; i1 < n_blocks1; ++i1)
2544 for (
int i = 0; i < mm; ++i)
2545 x[i] = in[stride * i];
2547 for (
int col = 0; col < nn; ++col)
2551 if (contract_over_rows)
2552 val0 = shape_data[col];
2554 val0 = shape_data[col * n_columns];
2556 Number res0 = val0 * x[0];
2557 for (
int i = 1; i < mm; ++i)
2559 if (contract_over_rows)
2560 val0 = shape_data[i * n_columns + col];
2562 val0 = shape_data[col * n_columns + i];
2564 res0 += val0 * x[i];
2567 out[stride * col] += res0;
2570 out[stride * col] = res0;
2573 if (one_line ==
false)
2579 if (one_line ==
false)
2581 in += stride * (mm - 1);
2582 out += stride * (nn - 1);
2593 template <
int face_direction,
2594 bool contract_onto_face,
2609 static_assert(max_derivative >= 0 && max_derivative < 3,
2610 "Only derivative orders 0-2 implemented");
2611 Assert(shape_values !=
nullptr,
2613 "The given array shape_values must not be the null pointer."));
2617 constexpr int n_blocks1 = (face_direction == normal_dir) ? (n_rows - 1) :
2618 ((face_direction == 0 && normal_dir == 2) ||
2619 (face_direction == 1 && normal_dir == 2) ||
2620 (face_direction == 2 && normal_dir == 1)) ?
2623 constexpr int n_blocks2 = (dim == 2) ?
2625 ((face_direction == normal_dir) ?
2627 (((face_direction == 0 && normal_dir == 1) ||
2628 (face_direction == 1 && normal_dir == 0) ||
2629 (face_direction == 2 && normal_dir == 0)) ?
2635 constexpr int in_stride =
2636 (face_direction == normal_dir) ?
2638 ((face_direction == 0) ?
2640 ((face_direction == 2) ?
2641 n_rows * (n_rows + 1) :
2642 ((face_direction == 1 && normal_dir == 0) ? (n_rows + 1) :
2644 constexpr int out_stride = n_blocks1 * n_blocks2;
2648 for (
int i2 = 0; i2 < n_blocks2; ++i2)
2650 for (
int i1 = 0; i1 < n_blocks1; ++i1)
2652 if (contract_onto_face ==
true)
2654 Number res0 = shape_values[0] * in[0];
2657 if (max_derivative > 0)
2658 res1 = shape_values[n_rows] * in[0];
2660 if (max_derivative > 1)
2661 res2 = shape_values[2 * n_rows] * in[0];
2663 for (
int ind = 1; ind < n_rows; ++ind)
2665 res0 += shape_values[ind] * in[in_stride * ind];
2666 if (max_derivative > 0)
2667 res1 += shape_values[ind + n_rows] * in[in_stride * ind];
2669 if (max_derivative > 1)
2671 shape_values[ind + 2 * n_rows] * in[in_stride * ind];
2677 if (max_derivative > 0)
2678 out[out_stride] += res1;
2680 if (max_derivative > 1)
2681 out[2 * out_stride] += res2;
2687 if (max_derivative > 0)
2688 out[out_stride] = res1;
2690 if (max_derivative > 1)
2691 out[2 * out_stride] = res2;
2696 for (
int col = 0; col < n_rows; ++col)
2699 out[col * in_stride] += shape_values[col] * in[0];
2701 out[col * in_stride] = shape_values[col] * in[0];
2703 if (max_derivative > 0)
2704 out[col * in_stride] +=
2705 shape_values[col + n_rows] * in[out_stride];
2707 if (max_derivative > 1)
2708 out[col * in_stride] +=
2709 shape_values[col + 2 * n_rows] * in[2 * out_stride];
2716 switch (face_direction)
2719 in += contract_onto_face ? n_rows : 1;
2720 out += contract_onto_face ? 1 : n_rows;
2731 if (normal_dir == 0)
2733 if (contract_onto_face)
2738 if (normal_dir == 1)
2740 if (contract_onto_face)
2745 if (normal_dir == 2)
2747 if (contract_onto_face)
2764 if (face_direction == 1 && dim == 3)
2767 if (contract_onto_face)
2769 if (normal_dir == 0)
2771 in += (n_rows + 1) * (n_rows - 1);
2772 out -= n_rows * (n_rows + 1) - 1;
2774 if (normal_dir == 1)
2776 in += (n_rows - 1) * (n_rows - 1);
2777 out -= (n_rows - 1) * (n_rows - 1) - 1;
2779 if (normal_dir == 2)
2781 in += (n_rows - 1) * (n_rows);
2782 out -= (n_rows) * (n_rows + 1) - 1;
2787 if (normal_dir == 0)
2789 out += (n_rows + 1) * (n_rows - 1);
2790 in -= n_rows * (n_rows + 1) - 1;
2792 if (normal_dir == 1)
2794 out += (n_rows - 1) * (n_rows - 1);
2795 in -= (n_rows - 1) * (n_rows - 1) - 1;
2797 if (normal_dir == 2)
2799 out += (n_rows - 1) * (n_rows);
2800 in -= (n_rows) * (n_rows + 1) - 1;
2815 template <
typename Number,
typename Number2>
2821 template <
int dim,
typename Number,
typename Number2>
2863 template <
int dim,
typename Number,
typename Number2>
2869 const std::vector<Number> & values,
2871 const bool d_linear =
false,
2872 const std::vector<unsigned int> & renumber = {})
2874 static_assert(dim >= 1 && dim <= 3,
"Only dim=1,2,3 implemented");
2882 const int n_shapes = poly.size();
2884 Assert(renumber.empty() || renumber.size() == values.size(),
2891 for (
unsigned int i = 0; i < renumber.size(); ++i)
2897 derivative[0] = values[1] - values[0];
2898 return std::make_pair((1. - p[0]) * values[0] + p[0] * values[1],
2903 const Number2 x0 = 1. - p[0], x1 = p[0];
2906 const Number3 mapped = (1. - p[1]) * tmp0 + p[1] * tmp1;
2908 derivative[0] = (1. - p[1]) * (values[1] - values[0]) +
2910 derivative[1] = tmp1 - tmp0;
2911 return std::make_pair(mapped, derivative);
2915 const Number2 x0 = 1. - p[0], x1 = p[0], y0 = 1. - p[1], y1 = p[1],
2916 z0 = 1. - p[2], z1 = p[2];
2919 const Number3 tmpy0 = y0 * tmp0 + y1 * tmp1;
2922 const Number3 tmpy1 = y0 * tmp2 + y1 * tmp3;
2923 const Number3 mapped = z0 * tmpy0 + z1 * tmpy1;
2925 derivative[2] = tmpy1 - tmpy0;
2926 derivative[1] = z0 * (tmp1 - tmp0) + z1 * (tmp3 - tmp2);
2929 (y0 * (
values[1] -
values[0]) + y1 * (values[3] - values[2])) +
2931 (y0 * (values[5] - values[4]) + y1 * (
values[7] -
values[6]));
2932 return std::make_pair(mapped, derivative);
2940 std::array<Number2, dim>
point;
2941 for (
unsigned int d = 0;
d < dim; ++
d)
2943 for (
int i = 0; i < n_shapes; ++i)
2944 poly[i].values_of_array(point, 1, &shapes[i][0]);
2948 std::pair<Number3, Tensor<1, dim, Number3>> result = {};
2949 for (
int i2 = 0, i = 0; i2 < (dim > 2 ? n_shapes : 1); ++i2)
2951 Number3 value_y = {}, deriv_x = {}, deriv_y = {};
2952 for (
int i1 = 0; i1 < (dim > 1 ? n_shapes : 1); ++i1)
2955 Number3
value = {}, deriv = {};
2959 if (renumber.empty())
2960 for (
int i0 = 0; i0 < n_shapes; ++i0, ++i)
2963 deriv += shapes[i0][1][0] *
values[i];
2966 for (
int i0 = 0; i0 < n_shapes; ++i0, ++i)
2969 deriv += shapes[i0][1][0] *
values[renumber[i]];
2975 value_y +=
value * shapes[i1][0][1];
2976 deriv_x += deriv * shapes[i1][0][1];
2977 deriv_y +=
value * shapes[i1][1][1];
2981 result.first =
value;
2982 result.second[0] = deriv;
2988 result.first += value_y * shapes[i2][0][2];
2989 result.second[0] += deriv_x * shapes[i2][0][2];
2990 result.second[1] += deriv_y * shapes[i2][0][2];
2991 result.second[2] += value_y * shapes[i2][1][2];
2995 result.first = value_y;
2996 result.second[0] = deriv_x;
2997 result.second[1] = deriv_y;
3006 template <
int dim,
typename Number,
typename Number2>
3010 const std::vector<Number> & values,
3012 const std::vector<unsigned int> & renumber = {})
3014 static_assert(dim >= 1 && dim <= 3,
"Only dim=1,2,3 implemented");
3022 const int n_shapes = poly.size();
3024 Assert(renumber.empty() || renumber.size() == values.size(),
3031 std::array<Number2, dim> point;
3032 for (
unsigned int d = 0; d < dim; ++d)
3034 for (
int i = 0; i < n_shapes; ++i)
3035 poly[i].values_of_array(point, 2, &shapes[i][0]);
3040 for (
int i2 = 0, i = 0; i2 < (dim > 2 ? n_shapes : 1); ++i2)
3042 Number3 value_y = {}, deriv_x = {}, deriv_y = {}, deriv_xx = {},
3043 deriv_xy = {}, deriv_yy = {};
3044 for (
int i1 = 0; i1 < (dim > 1 ? n_shapes : 1); ++i1)
3047 Number3
value = {}, deriv_1 = {}, deriv_2 = {};
3051 if (renumber.empty())
3052 for (
int i0 = 0; i0 < n_shapes; ++i0, ++i)
3055 deriv_1 += shapes[i0][1][0] *
values[i];
3056 deriv_2 += shapes[i0][2][0] *
values[i];
3059 for (
int i0 = 0; i0 < n_shapes; ++i0, ++i)
3062 deriv_1 += shapes[i0][1][0] *
values[renumber[i]];
3063 deriv_2 += shapes[i0][2][0] *
values[renumber[i]];
3071 value_y +=
value * shapes[i1][0][1];
3072 deriv_x += deriv_1 * shapes[i1][0][1];
3073 deriv_y +=
value * shapes[i1][1][1];
3075 deriv_xx += deriv_2 * shapes[i1][0][1];
3076 deriv_xy += deriv_1 * shapes[i1][1][1];
3077 deriv_yy +=
value * shapes[i1][2][1];
3081 result[0][0] = deriv_2;
3087 result[0][0] += deriv_xx * shapes[i2][0][2];
3088 result[0][1] += deriv_xy * shapes[i2][0][2];
3089 result[0][2] += deriv_x * shapes[i2][1][2];
3090 result[1][1] += deriv_yy * shapes[i2][0][2];
3091 result[1][2] += deriv_y * shapes[i2][1][2];
3092 result[2][2] += value_y * shapes[i2][2][2];
3096 result[0][0] = deriv_xx;
3097 result[1][0] = deriv_xy;
3098 result[1][1] = deriv_yy;
3110 template <
int dim,
typename Number,
typename Number2>
3114 const Number2 &
value,
3118 const std::vector<unsigned int> & renumber = {})
3120 static_assert(dim >= 1 && dim <= 3,
"Only dim=1,2,3 implemented");
3123 const int n_shapes = poly.size();
3125 Assert(renumber.empty() || renumber.size() == values.size(),
3132 std::array<Number, dim> point;
3133 for (
unsigned int d = 0; d < dim; ++d)
3135 for (
int i = 0; i < n_shapes; ++i)
3136 poly[i].values_of_array(point, 1, &shapes[i][0]);
3139 for (
int i2 = 0, i = 0; i2 < (dim > 2 ? n_shapes : 1); ++i2)
3141 const Number2 test_value_z =
3143 (
value * shapes[i2][0][2] +
gradient[2] * shapes[i2][1][2]) :
3145 const Number2 test_grad_x =
3147 const Number2 test_grad_y = dim > 2 ?
3149 (dim > 1 ?
gradient[1] : Number2());
3150 for (
int i1 = 0; i1 < (dim > 1 ? n_shapes : 1); ++i1)
3152 const Number2 test_value_y = dim > 1 ?
3153 (test_value_z * shapes[i1][0][1] +
3154 test_grad_y * shapes[i1][1][1]) :
3156 const Number2 test_grad_xy =
3157 dim > 1 ? test_grad_x * shapes[i1][0][1] : test_grad_x;
3158 if (renumber.empty())
3159 for (
int i0 = 0; i0 < n_shapes; ++i0, ++i)
3160 values[i] += shapes[i0][0][0] * test_value_y +
3161 shapes[i0][1][0] * test_grad_xy;
3163 for (
int i0 = 0; i0 < n_shapes; ++i0, ++i)
3164 values[renumber[i]] += shapes[i0][0][0] * test_value_y +
3165 shapes[i0][1][0] * test_grad_xy;
3171 template <
int dim,
int loop_length_
template,
typename Number>
3174 const unsigned int n_components,
3175 const int loop_length_non_template,
3178 const int loop_length = loop_length_template != -1 ?
3179 loop_length_template :
3180 loop_length_non_template;
3184 unsigned int degree_to_3[100];
3186 for (
int i = 1; i < loop_length - 1; ++i)
3188 degree_to_3[loop_length - 1] = 2;
3189 for (
unsigned int c = 0; c < n_components; ++c)
3190 for (
int k = 0; k < (dim > 2 ? loop_length : 1); ++k)
3191 for (
int j = 0; j < (dim > 1 ? loop_length : 1); ++j)
3193 const unsigned int shift = 9 * degree_to_3[k] + 3 * degree_to_3[j];
3194 data[0] *= weights[shift];
3197 for (
int i = 1; i < loop_length - 1; ++i)
3198 data[i] *= weights[shift + 1];
3199 data[loop_length - 1] *= weights[shift + 2];
3200 data += loop_length;
#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)
Point< spacedim > point(const gp_Pnt &p, const double tolerance=1e-10)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
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={})
void weight_fe_q_dofs_by_entity(const VectorizedArray< Number > *weights, const unsigned int n_components, const int loop_length_non_template, VectorizedArray< Number > *data)
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_raviart_thomas
@ evaluate_symmetric_hierarchical
SymmetricTensor< 2, dim, typename ProductTypeNoPoint< Number, Number2 >::type > evaluate_tensor_product_hessian(const std::vector< Polynomials::Polynomial< double > > &poly, const std::vector< Number > &values, const Point< dim, Number2 > &p, const std::vector< unsigned int > &renumber={})
static const unsigned int invalid_unsigned_int
typename internal::ndarray::HelperArray< T, Ns... >::type ndarray
typename internal::ProductTypeImpl< typename std::decay< T >::type, typename std::decay< U >::type >::type type
void gradients(const Number in[], Number out[]) const
const Number2 * shape_hessians
void hessians(const Number in[], Number out[]) const
EvaluatorTensorProductAnisotropic()
void values(const Number in[], Number out[]) const
const Number2 * shape_gradients
EvaluatorTensorProductAnisotropic(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
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