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,
238 const Number2 * shape_gradients,
239 const Number2 * shape_hessians,
240 const unsigned int dummy1 = 0,
241 const unsigned int dummy2 = 0)
242 : shape_values(shape_values)
243 , shape_gradients(shape_gradients)
244 , shape_hessians(shape_hessians)
250 template <
int direction,
bool contract_over_rows,
bool add>
252 values(
const Number in[], Number out[])
const
254 apply<direction, contract_over_rows, add>(shape_values, in, out);
257 template <
int direction,
bool contract_over_rows,
bool add>
261 apply<direction, contract_over_rows, add>(shape_gradients, in, out);
264 template <
int direction,
bool contract_over_rows,
bool add>
268 apply<direction, contract_over_rows, add>(shape_hessians, in, out);
271 template <
int direction,
bool contract_over_rows,
bool add>
276 apply<direction, contract_over_rows, add, true>(shape_values, in, out);
279 template <
int direction,
bool contract_over_rows,
bool add>
284 apply<direction, contract_over_rows, add, true>(shape_gradients, in, out);
287 template <
int direction,
bool contract_over_rows,
bool add>
292 apply<direction, contract_over_rows, add, true>(shape_hessians, in, out);
319 template <
int direction,
320 bool contract_over_rows,
322 bool one_line =
false>
357 template <
int face_direction,
358 bool contract_onto_face,
378 template <
int direction,
bool contract_over_rows,
bool add,
bool one_line>
390 static_assert(one_line ==
false || direction == dim - 1,
391 "Single-line evaluation only works for direction=dim-1.");
392 Assert(shape_data !=
nullptr,
394 "The given array shape_data must not be the null pointer!"));
395 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
397 ExcMessage(
"In-place operation only supported for "
398 "n_rows==n_columns or single-line interpolation"));
400 constexpr int mm = contract_over_rows ? n_rows : n_columns,
401 nn = contract_over_rows ? n_columns : n_rows;
404 constexpr int n_blocks1 = one_line ? 1 : stride;
405 constexpr int n_blocks2 =
406 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
408 for (
int i2 = 0; i2 < n_blocks2; ++i2)
410 for (
int i1 = 0; i1 < n_blocks1; ++i1)
413 for (
int i = 0; i < mm; ++i)
414 x[i] = in[stride * i];
415 for (
int col = 0; col < nn; ++col)
418 if (contract_over_rows ==
true)
419 val0 = shape_data[col];
421 val0 = shape_data[col * n_columns];
422 Number res0 = val0 * x[0];
423 for (
int i = 1; i < mm; ++i)
425 if (contract_over_rows ==
true)
426 val0 = shape_data[i * n_columns + col];
428 val0 = shape_data[col * n_columns + i];
432 out[stride * col] += res0;
434 out[stride * col] = res0;
437 if (one_line ==
false)
443 if (one_line ==
false)
445 in += stride * (mm - 1);
446 out += stride * (nn - 1);
458 template <
int face_direction,
459 bool contract_onto_face,
473 static_assert(max_derivative >= 0 && max_derivative < 3,
474 "Only derivative orders 0-2 implemented");
475 Assert(shape_values !=
nullptr,
477 "The given array shape_values must not be the null pointer."));
479 constexpr int n_blocks1 = (dim > 1 ? n_rows : 1);
480 constexpr int n_blocks2 = (dim > 2 ? n_rows : 1);
487 for (
int i2 = 0; i2 < n_blocks2; ++i2)
489 for (
int i1 = 0; i1 < n_blocks1; ++i1)
491 if (contract_onto_face ==
true)
493 Number res0 = shape_values[0] * in[0];
495 if (max_derivative > 0)
496 res1 = shape_values[n_rows] * in[0];
497 if (max_derivative > 1)
498 res2 = shape_values[2 * n_rows] * in[0];
499 for (
int ind = 1; ind < n_rows; ++ind)
501 res0 += shape_values[ind] * in[in_stride * ind];
502 if (max_derivative > 0)
503 res1 += shape_values[ind + n_rows] * in[in_stride * ind];
504 if (max_derivative > 1)
506 shape_values[ind + 2 * n_rows] * in[in_stride * ind];
511 if (max_derivative > 0)
512 out[out_stride] += res1;
513 if (max_derivative > 1)
514 out[2 * out_stride] += res2;
519 if (max_derivative > 0)
520 out[out_stride] = res1;
521 if (max_derivative > 1)
522 out[2 * out_stride] = res2;
527 for (
int col = 0; col < n_rows; ++col)
530 out[col * in_stride] += shape_values[col] * in[0];
532 out[col * in_stride] = shape_values[col] * in[0];
533 if (max_derivative > 0)
534 out[col * in_stride] +=
535 shape_values[col + n_rows] * in[out_stride];
536 if (max_derivative > 1)
537 out[col * in_stride] +=
538 shape_values[col + 2 * n_rows] * in[2 * out_stride];
545 switch (face_direction)
548 in += contract_onto_face ? n_rows : 1;
549 out += contract_onto_face ? 1 : n_rows;
559 if (contract_onto_face)
575 if (face_direction == 1 && dim == 3)
577 if (contract_onto_face)
579 in += n_rows * (n_rows - 1);
580 out -= n_rows * n_rows - 1;
584 out += n_rows * (n_rows - 1);
585 in -= n_rows * n_rows - 1;
606 template <
int dim,
typename Number,
typename Number2>
609 static constexpr unsigned int n_rows_of_product =
611 static constexpr unsigned int n_columns_of_product =
619 : shape_values(nullptr)
620 , shape_gradients(nullptr)
621 , shape_hessians(nullptr)
622 , n_rows(
numbers::invalid_unsigned_int)
623 , n_columns(
numbers::invalid_unsigned_int)
632 const unsigned int n_rows,
633 const unsigned int n_columns)
634 : shape_values(shape_values.begin())
635 , shape_gradients(shape_gradients.begin())
636 , shape_hessians(shape_hessians.begin())
638 , n_columns(n_columns)
645 shape_values.
size() == n_rows * n_columns ||
646 shape_values.
size() == n_rows * 3,
649 shape_gradients.
size() == n_rows * n_columns,
652 shape_hessians.
size() == n_rows * n_columns,
660 const Number2 * shape_gradients,
661 const Number2 * shape_hessians,
662 const unsigned int n_rows,
663 const unsigned int n_columns)
664 : shape_values(shape_values)
665 , shape_gradients(shape_gradients)
666 , shape_hessians(shape_hessians)
668 , n_columns(n_columns)
671 template <
int direction,
bool contract_over_rows,
bool add>
673 values(
const Number *in, Number *out)
const
675 apply<direction, contract_over_rows, add>(shape_values, in, out);
678 template <
int direction,
bool contract_over_rows,
bool add>
682 apply<direction, contract_over_rows, add>(shape_gradients, in, out);
685 template <
int direction,
bool contract_over_rows,
bool add>
689 apply<direction, contract_over_rows, add>(shape_hessians, in, out);
692 template <
int direction,
bool contract_over_rows,
bool add>
697 apply<direction, contract_over_rows, add, true>(shape_values, in, out);
700 template <
int direction,
bool contract_over_rows,
bool add>
705 apply<direction, contract_over_rows, add, true>(shape_gradients, in, out);
708 template <
int direction,
bool contract_over_rows,
bool add>
713 apply<direction, contract_over_rows, add, true>(shape_hessians, in, out);
716 template <
int direction,
717 bool contract_over_rows,
719 bool one_line =
false>
725 template <
int face_direction,
726 bool contract_onto_face,
742 template <
int dim,
typename Number,
typename Number2>
743 template <
int direction,
bool contract_over_rows,
bool add,
bool one_line>
750 static_assert(one_line ==
false || direction == dim - 1,
751 "Single-line evaluation only works for direction=dim-1.");
752 Assert(shape_data !=
nullptr,
754 "The given array shape_data must not be the null pointer!"));
755 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
757 ExcMessage(
"In-place operation only supported for "
758 "n_rows==n_columns or single-line interpolation"));
760 const int mm = contract_over_rows ? n_rows : n_columns,
761 nn = contract_over_rows ? n_columns : n_rows;
764 direction == 0 ? 1 : Utilities::fixed_power<direction>(n_columns);
765 const int n_blocks1 = one_line ? 1 : stride;
766 const int n_blocks2 = direction >= dim - 1 ?
776 if (contract_over_rows && n_rows == 2)
778 const Number2 *shape_data_1 = shape_data + n_columns;
779 for (
int i2 = 0; i2 < n_blocks2; ++i2)
781 for (
int i1 = 0; i1 < n_blocks1; ++i1)
783 const Number x0 = in[0], x1 = in[stride];
784 for (
int col = 0; col < nn; ++col)
786 const Number result =
787 shape_data[col] * x0 + shape_data_1[col] * x1;
789 out[stride * col] += result;
791 out[stride * col] = result;
794 if (one_line ==
false)
800 if (one_line ==
false)
802 in += stride * (mm - 1);
803 out += stride * (nn - 1);
808 else if (contract_over_rows && n_rows == 3)
810 const Number2 *shape_data_1 = shape_data + n_columns;
811 const Number2 *shape_data_2 = shape_data + 2 * n_columns;
812 for (
int i2 = 0; i2 < n_blocks2; ++i2)
814 for (
int i1 = 0; i1 < n_blocks1; ++i1)
816 const Number x0 = in[0], x1 = in[stride], x2 = in[2 * stride];
817 for (
int col = 0; col < nn; ++col)
819 const Number result = shape_data[col] * x0 +
820 shape_data_1[col] * x1 +
821 shape_data_2[col] * x2;
823 out[stride * col] += result;
825 out[stride * col] = result;
828 if (one_line ==
false)
834 if (one_line ==
false)
836 in += stride * (mm - 1);
837 out += stride * (nn - 1);
843 for (
int i2 = 0; i2 < n_blocks2; ++i2)
845 for (
int i1 = 0; i1 < n_blocks1; ++i1)
848 for (
int i = 0; i < mm; ++i)
849 x[i] = in[stride * i];
850 for (
int col = 0; col < nn; ++col)
853 if (contract_over_rows ==
true)
854 val0 = shape_data[col];
856 val0 = shape_data[col * n_columns];
857 Number res0 = val0 * x[0];
858 for (
int i = 1; i < mm; ++i)
860 if (contract_over_rows ==
true)
861 val0 = shape_data[i * n_columns + col];
863 val0 = shape_data[col * n_columns + i];
867 out[stride * col] += res0;
869 out[stride * col] = res0;
872 if (one_line ==
false)
878 if (one_line ==
false)
880 in += stride * (mm - 1);
881 out += stride * (nn - 1);
888 template <
int dim,
typename Number,
typename Number2>
889 template <
int face_direction,
890 bool contract_onto_face,
898 Assert(shape_values !=
nullptr,
900 "The given array shape_data must not be the null pointer!"));
901 static_assert(dim > 0 && dim < 4,
"Only dim=1,2,3 supported");
902 const int n_blocks1 = dim > 1 ? n_rows : 1;
903 const int n_blocks2 = dim > 2 ? n_rows : 1;
906 const int in_stride =
907 face_direction > 0 ? Utilities::fixed_power<face_direction>(n_rows) : 1;
908 const int out_stride =
911 for (
int i2 = 0; i2 < n_blocks2; ++i2)
913 for (
int i1 = 0; i1 < n_blocks1; ++i1)
915 if (contract_onto_face ==
true)
917 Number res0 = shape_values[0] * in[0];
919 if (max_derivative > 0)
920 res1 = shape_values[n_rows] * in[0];
921 if (max_derivative > 1)
922 res2 = shape_values[2 * n_rows] * in[0];
923 for (
unsigned int ind = 1; ind < n_rows; ++ind)
925 res0 += shape_values[ind] * in[in_stride * ind];
926 if (max_derivative > 0)
927 res1 += shape_values[ind + n_rows] * in[in_stride * ind];
928 if (max_derivative > 1)
930 shape_values[ind + 2 * n_rows] * in[in_stride * ind];
935 if (max_derivative > 0)
936 out[out_stride] += res1;
937 if (max_derivative > 1)
938 out[2 * out_stride] += res2;
943 if (max_derivative > 0)
944 out[out_stride] = res1;
945 if (max_derivative > 1)
946 out[2 * out_stride] = res2;
951 for (
unsigned int col = 0; col < n_rows; ++col)
954 out[col * in_stride] += shape_values[col] * in[0];
956 out[col * in_stride] = shape_values[col] * in[0];
957 if (max_derivative > 0)
958 out[col * in_stride] +=
959 shape_values[col + n_rows] * in[out_stride];
960 if (max_derivative > 1)
961 out[col * in_stride] +=
962 shape_values[col + 2 * n_rows] * in[2 * out_stride];
969 switch (face_direction)
972 in += contract_onto_face ? n_rows : 1;
973 out += contract_onto_face ? 1 : n_rows;
983 if (contract_onto_face)
997 if (face_direction == 1 && dim == 3)
1000 if (contract_onto_face)
1002 in += n_rows * (n_rows - 1);
1003 out -= n_rows * n_rows - 1;
1007 out += n_rows * (n_rows - 1);
1008 in -= n_rows * n_rows - 1;
1048 static constexpr unsigned int n_rows_of_product =
1050 static constexpr unsigned int n_columns_of_product =
1059 const unsigned int dummy1 = 0,
1060 const unsigned int dummy2 = 0)
1061 : shape_values(shape_values.begin())
1062 , shape_gradients(shape_gradients.begin())
1063 , shape_hessians(shape_hessians.begin())
1066 shape_values.
size() == n_rows * n_columns,
1069 shape_gradients.
size() == n_rows * n_columns,
1072 shape_hessians.
size() == n_rows * n_columns,
1078 template <
int direction,
bool contract_over_rows,
bool add>
1080 values(
const Number in[], Number out[])
const;
1082 template <
int direction,
bool contract_over_rows,
bool add>
1084 gradients(
const Number in[], Number out[])
const;
1086 template <
int direction,
bool contract_over_rows,
bool add>
1088 hessians(
const Number in[], Number out[])
const;
1121 template <
int direction,
bool contract_over_rows,
bool add>
1128 Number2>::values(
const Number in[], Number out[])
const
1132 constexpr int mm = contract_over_rows ? n_rows : n_columns,
1133 nn = contract_over_rows ? n_columns : n_rows;
1134 constexpr int n_cols = nn / 2;
1135 constexpr int mid = mm / 2;
1138 constexpr int n_blocks1 = stride;
1139 constexpr int n_blocks2 =
1140 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
1142 for (
int i2 = 0; i2 < n_blocks2; ++i2)
1144 for (
int i1 = 0; i1 < n_blocks1; ++i1)
1146 for (
int col = 0; col < n_cols; ++col)
1149 Number in0, in1, res0, res1;
1150 if (contract_over_rows ==
true)
1152 val0 = shape_values[col];
1153 val1 = shape_values[nn - 1 - col];
1157 val0 = shape_values[col * n_columns];
1158 val1 = shape_values[(col + 1) * n_columns - 1];
1163 in1 = in[stride * (mm - 1)];
1168 for (
int ind = 1; ind < mid; ++ind)
1170 if (contract_over_rows ==
true)
1172 val0 = shape_values[ind * n_columns + col];
1173 val1 = shape_values[ind * n_columns + nn - 1 - col];
1177 val0 = shape_values[col * n_columns + ind];
1179 shape_values[(col + 1) * n_columns - 1 - ind];
1181 in0 = in[stride * ind];
1182 in1 = in[stride * (mm - 1 - ind)];
1190 res0 = res1 = Number();
1191 if (contract_over_rows ==
true)
1195 val0 = shape_values[mid * n_columns + col];
1196 in1 = val0 * in[stride * mid];
1203 if (mm % 2 == 1 && nn % 2 == 0)
1205 val0 = shape_values[col * n_columns + mid];
1206 in1 = val0 * in[stride * mid];
1213 out[stride * col] += res0;
1214 out[stride * (nn - 1 - col)] += res1;
1218 out[stride * col] = res0;
1219 out[stride * (nn - 1 - col)] = res1;
1222 if (contract_over_rows ==
true && nn % 2 == 1 && mm % 2 == 1)
1225 out[stride * n_cols] += in[stride * mid];
1227 out[stride * n_cols] = in[stride * mid];
1229 else if (contract_over_rows ==
true && nn % 2 == 1)
1232 Number2 val0 = shape_values[n_cols];
1235 res0 = val0 * (in[0] + in[stride * (mm - 1)]);
1236 for (
int ind = 1; ind < mid; ++ind)
1238 val0 = shape_values[ind * n_columns + n_cols];
1239 res0 += val0 * (in[stride * ind] +
1240 in[stride * (mm - 1 - ind)]);
1246 out[stride * n_cols] += res0;
1248 out[stride * n_cols] = res0;
1250 else if (contract_over_rows ==
false && nn % 2 == 1)
1255 Number2 val0 = shape_values[n_cols * n_columns];
1256 res0 = val0 * (in[0] + in[stride * (mm - 1)]);
1257 for (
int ind = 1; ind < mid; ++ind)
1259 val0 = shape_values[n_cols * n_columns + ind];
1260 Number in1 = val0 * (in[stride * ind] +
1261 in[stride * (mm - 1 - ind)]);
1265 res0 += in[stride * mid];
1270 out[stride * n_cols] += res0;
1272 out[stride * n_cols] = res0;
1278 in += stride * (mm - 1);
1279 out += stride * (nn - 1);
1309 template <
int direction,
bool contract_over_rows,
bool add>
1316 Number2>::gradients(
const Number in[],
1321 constexpr int mm = contract_over_rows ? n_rows : n_columns,
1322 nn = contract_over_rows ? n_columns : n_rows;
1323 constexpr int n_cols = nn / 2;
1324 constexpr int mid = mm / 2;
1327 constexpr int n_blocks1 = stride;
1328 constexpr int n_blocks2 =
1329 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
1331 for (
int i2 = 0; i2 < n_blocks2; ++i2)
1333 for (
int i1 = 0; i1 < n_blocks1; ++i1)
1335 for (
int col = 0; col < n_cols; ++col)
1338 Number in0, in1, res0, res1;
1339 if (contract_over_rows ==
true)
1341 val0 = shape_gradients[col];
1342 val1 = shape_gradients[nn - 1 - col];
1346 val0 = shape_gradients[col * n_columns];
1347 val1 = shape_gradients[(nn - col - 1) * n_columns];
1352 in1 = in[stride * (mm - 1)];
1357 for (
int ind = 1; ind < mid; ++ind)
1359 if (contract_over_rows ==
true)
1361 val0 = shape_gradients[ind * n_columns + col];
1363 shape_gradients[ind * n_columns + nn - 1 - col];
1367 val0 = shape_gradients[col * n_columns + ind];
1369 shape_gradients[(nn - col - 1) * n_columns + ind];
1371 in0 = in[stride * ind];
1372 in1 = in[stride * (mm - 1 - ind)];
1380 res0 = res1 = Number();
1383 if (contract_over_rows ==
true)
1384 val0 = shape_gradients[mid * n_columns + col];
1386 val0 = shape_gradients[col * n_columns + mid];
1387 in1 = val0 * in[stride * mid];
1393 out[stride * col] += res0;
1394 out[stride * (nn - 1 - col)] += res1;
1398 out[stride * col] = res0;
1399 out[stride * (nn - 1 - col)] = res1;
1406 if (contract_over_rows ==
true)
1407 val0 = shape_gradients[n_cols];
1409 val0 = shape_gradients[n_cols * n_columns];
1410 res0 = val0 * (in[0] - in[stride * (mm - 1)]);
1411 for (
int ind = 1; ind < mid; ++ind)
1413 if (contract_over_rows ==
true)
1414 val0 = shape_gradients[ind * n_columns + n_cols];
1416 val0 = shape_gradients[n_cols * n_columns + ind];
1418 val0 * (in[stride * ind] - in[stride * (mm - 1 - ind)]);
1422 out[stride * n_cols] += res0;
1424 out[stride * n_cols] = res0;
1430 in += stride * (mm - 1);
1431 out += stride * (nn - 1);
1445 template <
int direction,
bool contract_over_rows,
bool add>
1452 Number2>::hessians(
const Number in[],
1457 constexpr int mm = contract_over_rows ? n_rows : n_columns;
1458 constexpr int nn = contract_over_rows ? n_columns : n_rows;
1459 constexpr int n_cols = nn / 2;
1460 constexpr int mid = mm / 2;
1463 constexpr int n_blocks1 = stride;
1464 constexpr int n_blocks2 =
1465 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
1467 for (
int i2 = 0; i2 < n_blocks2; ++i2)
1469 for (
int i1 = 0; i1 < n_blocks1; ++i1)
1471 for (
int col = 0; col < n_cols; ++col)
1474 Number in0, in1, res0, res1;
1475 if (contract_over_rows ==
true)
1477 val0 = shape_hessians[col];
1478 val1 = shape_hessians[nn - 1 - col];
1482 val0 = shape_hessians[col * n_columns];
1483 val1 = shape_hessians[(col + 1) * n_columns - 1];
1488 in1 = in[stride * (mm - 1)];
1493 for (
int ind = 1; ind < mid; ++ind)
1495 if (contract_over_rows ==
true)
1497 val0 = shape_hessians[ind * n_columns + col];
1499 shape_hessians[ind * n_columns + nn - 1 - col];
1503 val0 = shape_hessians[col * n_columns + ind];
1505 shape_hessians[(col + 1) * n_columns - 1 - ind];
1507 in0 = in[stride * ind];
1508 in1 = in[stride * (mm - 1 - ind)];
1516 res0 = res1 = Number();
1519 if (contract_over_rows ==
true)
1520 val0 = shape_hessians[mid * n_columns + col];
1522 val0 = shape_hessians[col * n_columns + mid];
1523 in1 = val0 * in[stride * mid];
1529 out[stride * col] += res0;
1530 out[stride * (nn - 1 - col)] += res1;
1534 out[stride * col] = res0;
1535 out[stride * (nn - 1 - col)] = res1;
1542 if (contract_over_rows ==
true)
1543 val0 = shape_hessians[n_cols];
1545 val0 = shape_hessians[n_cols * n_columns];
1548 res0 = val0 * (in[0] + in[stride * (mm - 1)]);
1549 for (
int ind = 1; ind < mid; ++ind)
1551 if (contract_over_rows ==
true)
1552 val0 = shape_hessians[ind * n_columns + n_cols];
1554 val0 = shape_hessians[n_cols * n_columns + ind];
1555 Number in1 = val0 * (in[stride * ind] +
1556 in[stride * (mm - 1 - ind)]);
1564 if (contract_over_rows ==
true)
1565 val0 = shape_hessians[mid * n_columns + n_cols];
1567 val0 = shape_hessians[n_cols * n_columns + mid];
1568 res0 += val0 * in[stride * mid];
1571 out[stride * n_cols] += res0;
1573 out[stride * n_cols] = res0;
1579 in += stride * (mm - 1);
1580 out += stride * (nn - 1);
1588 int n_columns_static,
1592 bool contract_over_rows,
1598 const int n_columns_in,
1603 static_assert(type < 3,
"Only three variants type=0,1,2 implemented");
1604 static_assert(one_line ==
false || direction == dim - 1,
1605 "Single-line evaluation only works for direction=dim-1.");
1607 const int n_rows = n_rows_static == -1 ? n_rows_in : n_rows_static;
1608 const int n_columns =
1609 n_columns_static == -1 ? n_columns_in : n_columns_static;
1611 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
1613 ExcMessage(
"In-place operation only supported for "
1614 "n_rows==n_columns or single-line interpolation"));
1620 const int nn = contract_over_rows ? n_columns : n_rows;
1621 const int mm = contract_over_rows ? n_rows : n_columns;
1622 constexpr int mm_static =
1623 contract_over_rows ? n_rows_static : n_columns_static;
1624 const int n_cols = nn / 2;
1625 const int mid = mm / 2;
1626 constexpr int mid_static = mm_static / 2;
1627 constexpr int max_mid = 15;
1629 Assert((n_rows_static != -1 && n_columns_static != -1) || mid <= max_mid,
1633 const int n_blocks1 = one_line ? 1 : stride;
1634 const int n_blocks2 =
1635 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
1637 const int offset = (n_columns + 1) / 2;
1643 for (
int i2 = 0; i2 < n_blocks2; ++i2)
1645 for (
int i1 = 0; i1 < n_blocks1; ++i1)
1647 constexpr unsigned int mid_size =
1648 (n_rows_static == -1 || n_columns_static == -1) ?
1650 (mid_static > 0 ? mid_static : 1);
1651 Number xp[mid_size], xm[mid_size];
1652 for (
int i = 0; i < mid; ++i)
1654 if (contract_over_rows ==
true && type == 1)
1656 xp[i] = in[stride * i] - in[stride * (mm - 1 - i)];
1657 xm[i] = in[stride * i] + in[stride * (mm - 1 - i)];
1661 xp[i] = in[stride * i] + in[stride * (mm - 1 - i)];
1662 xm[i] = in[stride * i] - in[stride * (mm - 1 - i)];
1665 Number xmid = in[stride * mid];
1666 for (
int col = 0; col < n_cols; ++col)
1671 if (contract_over_rows ==
true)
1673 r0 = shapes[col] * xp[0];
1674 r1 = shapes[(n_rows - 1) * offset + col] * xm[0];
1678 r0 = shapes[col * offset] * xp[0];
1679 r1 = shapes[(n_rows - 1 - col) * offset] * xm[0];
1681 for (
int ind = 1; ind < mid; ++ind)
1683 if (contract_over_rows ==
true)
1685 r0 += shapes[ind * offset + col] * xp[ind];
1686 r1 += shapes[(n_rows - 1 - ind) * offset + col] *
1691 r0 += shapes[col * offset + ind] * xp[ind];
1692 r1 += shapes[(n_rows - 1 - col) * offset + ind] *
1699 if (mm % 2 == 1 && contract_over_rows ==
true)
1702 r1 += shapes[mid * offset + col] * xmid;
1704 r0 += shapes[mid * offset + col] * xmid;
1706 else if (mm % 2 == 1 && (nn % 2 == 0 || type > 0 || mm == 3))
1707 r0 += shapes[col * offset + mid] * xmid;
1711 out[stride * col] += r0 + r1;
1712 if (type == 1 && contract_over_rows ==
false)
1713 out[stride * (nn - 1 - col)] += r1 - r0;
1715 out[stride * (nn - 1 - col)] += r0 - r1;
1719 out[stride * col] = r0 + r1;
1720 if (type == 1 && contract_over_rows ==
false)
1721 out[stride * (nn - 1 - col)] = r1 - r0;
1723 out[stride * (nn - 1 - col)] = r0 - r1;
1726 if (type == 0 && contract_over_rows ==
true && nn % 2 == 1 &&
1727 mm % 2 == 1 && mm > 3)
1730 out[stride * n_cols] += shapes[mid * offset + n_cols] * xmid;
1732 out[stride * n_cols] = shapes[mid * offset + n_cols] * xmid;
1734 else if (contract_over_rows ==
true && nn % 2 == 1)
1739 r0 = shapes[n_cols] * xp[0];
1740 for (
int ind = 1; ind < mid; ++ind)
1741 r0 += shapes[ind * offset + n_cols] * xp[ind];
1745 if (type != 1 && mm % 2 == 1)
1746 r0 += shapes[mid * offset + n_cols] * xmid;
1749 out[stride * n_cols] += r0;
1751 out[stride * n_cols] = r0;
1753 else if (contract_over_rows ==
false && nn % 2 == 1)
1760 r0 = shapes[n_cols * offset] * xm[0];
1761 for (
int ind = 1; ind < mid; ++ind)
1762 r0 += shapes[n_cols * offset + ind] * xm[ind];
1766 r0 = shapes[n_cols * offset] * xp[0];
1767 for (
int ind = 1; ind < mid; ++ind)
1768 r0 += shapes[n_cols * offset + ind] * xp[ind];
1774 if ((type == 0 || type == 2) && mm % 2 == 1)
1775 r0 += shapes[n_cols * offset + mid] * xmid;
1778 out[stride * n_cols] += r0;
1780 out[stride * n_cols] = r0;
1782 if (one_line ==
false)
1788 if (one_line ==
false)
1790 in += stride * (mm - 1);
1791 out += stride * (nn - 1);
1841 static constexpr unsigned int n_rows_of_product =
1843 static constexpr unsigned int n_columns_of_product =
1852 : shape_values(nullptr)
1853 , shape_gradients(nullptr)
1854 , shape_hessians(nullptr)
1862 : shape_values(shape_values.begin())
1863 , shape_gradients(nullptr)
1864 , shape_hessians(nullptr)
1876 const unsigned int dummy1 = 0,
1877 const unsigned int dummy2 = 0)
1878 : shape_values(shape_values.begin())
1879 , shape_gradients(shape_gradients.begin())
1880 , shape_hessians(shape_hessians.begin())
1884 if (!shape_values.
empty())
1886 if (!shape_gradients.
empty())
1888 if (!shape_hessians.
empty())
1894 template <
int direction,
bool contract_over_rows,
bool add>
1896 values(
const Number in[], Number out[])
const
1899 apply<direction, contract_over_rows, add, 0>(shape_values, in, out);
1902 template <
int direction,
bool contract_over_rows,
bool add>
1907 apply<direction, contract_over_rows, add, 1>(shape_gradients, in, out);
1910 template <
int direction,
bool contract_over_rows,
bool add>
1915 apply<direction, contract_over_rows, add, 2>(shape_hessians, in, out);
1918 template <
int direction,
bool contract_over_rows,
bool add>
1923 apply<direction, contract_over_rows, add, 0, true>(shape_values, in, out);
1926 template <
int direction,
bool contract_over_rows,
bool add>
1931 apply<direction, contract_over_rows, add, 1, true>(shape_gradients,
1936 template <
int direction,
bool contract_over_rows,
bool add>
1941 apply<direction, contract_over_rows, add, 2, true>(shape_hessians,
1974 template <
int direction,
1975 bool contract_over_rows,
1978 bool one_line =
false>
1993 one_line>(n_rows, n_columns, shape_data, in, out);
2009 template <
int dim,
typename Number,
typename Number2>
2013 : shape_values(nullptr)
2014 , shape_gradients(nullptr)
2015 , shape_hessians(nullptr)
2016 , n_rows(
numbers::invalid_unsigned_int)
2017 , n_columns(
numbers::invalid_unsigned_int)
2021 const unsigned int n_rows = 0,
2022 const unsigned int n_columns = 0)
2023 : shape_values(shape_values.begin())
2024 , shape_gradients(nullptr)
2025 , shape_hessians(nullptr)
2027 , n_columns(n_columns)
2035 const unsigned int n_rows = 0,
2036 const unsigned int n_columns = 0)
2037 : shape_values(shape_values.begin())
2038 , shape_gradients(shape_gradients.begin())
2039 , shape_hessians(shape_hessians.begin())
2041 , n_columns(n_columns)
2043 if (!shape_values.
empty())
2045 if (!shape_gradients.
empty())
2047 if (!shape_hessians.
empty())
2051 template <
int direction,
bool contract_over_rows,
bool add>
2053 values(
const Number in[], Number out[])
const
2056 apply<direction, contract_over_rows, add, 0>(shape_values, in, out);
2059 template <
int direction,
bool contract_over_rows,
bool add>
2064 apply<direction, contract_over_rows, add, 1>(shape_gradients, in, out);
2067 template <
int direction,
bool contract_over_rows,
bool add>
2072 apply<direction, contract_over_rows, add, 2>(shape_hessians, in, out);
2075 template <
int direction,
bool contract_over_rows,
bool add>
2080 apply<direction, contract_over_rows, add, 0, true>(shape_values, in, out);
2083 template <
int direction,
bool contract_over_rows,
bool add>
2088 apply<direction, contract_over_rows, add, 1, true>(shape_gradients,
2093 template <
int direction,
bool contract_over_rows,
bool add>
2098 apply<direction, contract_over_rows, add, 2, true>(shape_hessians,
2103 template <
int direction,
2104 bool contract_over_rows,
2107 bool one_line =
false>
2122 one_line>(n_rows, n_columns, shape_data, in, out);
2175 static constexpr unsigned int n_rows_of_product =
2177 static constexpr unsigned int n_columns_of_product =
2186 : shape_values(nullptr)
2187 , shape_gradients(nullptr)
2188 , shape_hessians(nullptr)
2196 : shape_values(shape_values.begin())
2197 , shape_gradients(nullptr)
2198 , shape_hessians(nullptr)
2208 const unsigned int dummy1 = 0,
2209 const unsigned int dummy2 = 0)
2210 : shape_values(shape_values.begin())
2211 , shape_gradients(shape_gradients.begin())
2212 , shape_hessians(shape_hessians.begin())
2218 template <
int direction,
bool contract_over_rows,
bool add>
2220 values(
const Number in[], Number out[])
const
2223 apply<direction, contract_over_rows, add, 0>(shape_values, in, out);
2226 template <
int direction,
bool contract_over_rows,
bool add>
2231 apply<direction, contract_over_rows, add, 1>(shape_gradients, in, out);
2234 template <
int direction,
bool contract_over_rows,
bool add>
2239 apply<direction, contract_over_rows, add, 0>(shape_hessians, in, out);
2242 template <
int direction,
bool contract_over_rows,
bool add>
2247 apply<direction, contract_over_rows, add, 0, true>(shape_values, in, out);
2250 template <
int direction,
bool contract_over_rows,
bool add>
2255 apply<direction, contract_over_rows, add, 1, true>(shape_gradients,
2260 template <
int direction,
bool contract_over_rows,
bool add>
2265 apply<direction, contract_over_rows, add, 0, true>(shape_hessians,
2297 template <
int direction,
2298 bool contract_over_rows,
2301 bool one_line =
false>
2320 template <
int direction,
2321 bool contract_over_rows,
2335 static_assert(one_line ==
false || direction == dim - 1,
2336 "Single-line evaluation only works for direction=dim-1.");
2338 type == 0 || type == 1,
2339 "Only types 0 and 1 implemented for evaluate_symmetric_hierarchical.");
2340 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
2342 ExcMessage(
"In-place operation only supported for "
2343 "n_rows==n_columns or single-line interpolation"));
2349 constexpr int nn = contract_over_rows ? n_columns : n_rows;
2350 constexpr int mm = contract_over_rows ? n_rows : n_columns;
2351 constexpr int n_cols = nn / 2;
2352 constexpr int mid = mm / 2;
2355 constexpr int n_blocks1 = one_line ? 1 : stride;
2356 constexpr int n_blocks2 =
2357 Utilities::pow(n_rows, (direction >= dim) ? 0 : (dim - direction - 1));
2363 for (
int i2 = 0; i2 < n_blocks2; ++i2)
2365 for (
int i1 = 0; i1 < n_blocks1; ++i1)
2367 if (contract_over_rows)
2370 for (
unsigned int i = 0; i < mm; ++i)
2371 x[i] = in[stride * i];
2372 for (
unsigned int col = 0; col < n_cols; ++col)
2377 r0 = shapes[col] * x[0];
2378 r1 = shapes[col + n_columns] * x[1];
2379 for (
unsigned int ind = 1; ind < mid; ++ind)
2382 shapes[col + 2 * ind * n_columns] * x[2 * ind];
2383 r1 += shapes[col + (2 * ind + 1) * n_columns] *
2390 r0 += shapes[col + (mm - 1) * n_columns] * x[mm - 1];
2393 out[stride * col] += r0 + r1;
2395 out[stride * (nn - 1 - col)] += r1 - r0;
2397 out[stride * (nn - 1 - col)] += r0 - r1;
2401 out[stride * col] = r0 + r1;
2403 out[stride * (nn - 1 - col)] = r1 - r0;
2405 out[stride * (nn - 1 - col)] = r0 - r1;
2411 const unsigned int shift = type == 1 ? 1 : 0;
2414 r0 = shapes[n_cols + shift * n_columns] * x[shift];
2415 for (
unsigned int ind = 1; ind < mid; ++ind)
2416 r0 += shapes[n_cols + (2 * ind + shift) * n_columns] *
2421 if (type != 1 && mm % 2 == 1)
2422 r0 += shapes[n_cols + (mm - 1) * n_columns] * x[mm - 1];
2424 out[stride * n_cols] += r0;
2426 out[stride * n_cols] = r0;
2431 Number xp[mid + 1], xm[mid > 0 ? mid : 1];
2432 for (
int i = 0; i < mid; ++i)
2435 xp[i] = in[stride * i] + in[stride * (mm - 1 - i)];
2436 xm[i] = in[stride * i] - in[stride * (mm - 1 - i)];
2440 xp[i] = in[stride * i] - in[stride * (mm - 1 - i)];
2441 xm[i] = in[stride * i] + in[stride * (mm - 1 - i)];
2444 xp[mid] = in[stride * mid];
2445 for (
unsigned int col = 0; col < n_cols; ++col)
2450 r0 = shapes[2 * col * n_columns] * xp[0];
2451 r1 = shapes[(2 * col + 1) * n_columns] * xm[0];
2452 for (
unsigned int ind = 1; ind < mid; ++ind)
2454 r0 += shapes[2 * col * n_columns + ind] * xp[ind];
2456 shapes[(2 * col + 1) * n_columns + ind] * xm[ind];
2465 shapes[(2 * col + 1) * n_columns + mid] * xp[mid];
2467 r0 += shapes[2 * col * n_columns + mid] * xp[mid];
2471 out[stride * (2 * col)] += r0;
2472 out[stride * (2 * col + 1)] += r1;
2476 out[stride * (2 * col)] = r0;
2477 out[stride * (2 * col + 1)] = r1;
2485 r0 = shapes[(nn - 1) * n_columns] * xp[0];
2486 for (
unsigned int ind = 1; ind < mid; ++ind)
2487 r0 += shapes[(nn - 1) * n_columns + ind] * xp[ind];
2491 if (mm % 2 == 1 && type == 0)
2492 r0 += shapes[(nn - 1) * n_columns + mid] * xp[mid];
2494 out[stride * (nn - 1)] += r0;
2496 out[stride * (nn - 1)] = r0;
2499 if (one_line ==
false)
2505 if (one_line ==
false)
2507 in += stride * (mm - 1);
2508 out += stride * (nn - 1);
2548 static constexpr unsigned int n_rows_of_product =
2550 static constexpr unsigned int n_columns_of_product =
2558 : shape_values(nullptr)
2559 , shape_gradients(nullptr)
2560 , shape_hessians(nullptr)
2570 const unsigned int dummy1 = 0,
2571 const unsigned int dummy2 = 0)
2572 : shape_values(shape_values.begin())
2573 , shape_gradients(shape_gradients.begin())
2574 , shape_hessians(shape_hessians.begin())
2581 shape_values.
size() == n_rows * n_columns ||
2582 shape_values.
size() == 3 * n_rows,
2585 shape_gradients.
size() == n_rows * n_columns,
2588 shape_hessians.
size() == n_rows * n_columns,
2594 template <
int direction,
bool contract_over_rows,
bool add>
2596 values(
const Number in[], Number out[])
const
2598 apply<direction, contract_over_rows, add>(shape_values, in, out);
2601 template <
int direction,
bool contract_over_rows,
bool add>
2605 apply<direction, contract_over_rows, add>(shape_gradients, in, out);
2608 template <
int direction,
bool contract_over_rows,
bool add>
2612 apply<direction, contract_over_rows, add>(shape_hessians, in, out);
2643 template <
int direction,
2644 bool contract_over_rows,
2646 bool one_line =
false>
2652 template <
int face_direction,
2653 bool contract_onto_face,
2672 template <
int direction,
bool contract_over_rows,
bool add,
bool one_line>
2685 static_assert(one_line ==
false || direction == dim - 1,
2686 "Single-line evaluation only works for direction=dim-1.");
2687 Assert(shape_data !=
nullptr,
2689 "The given array shape_data must not be the null pointer!"));
2690 Assert(dim == direction + 1 || one_line ==
true || n_rows == n_columns ||
2692 ExcMessage(
"In-place operation only supported for "
2693 "n_rows==n_columns or single-line interpolation"));
2695 constexpr int mm = contract_over_rows ? n_rows : n_columns,
2696 nn = contract_over_rows ? n_columns : n_rows;
2699 constexpr int n_blocks1 = one_line ? 1 : stride;
2702 constexpr int n_blocks2 =
2703 (dim - direction - 1 == 0) ?
2705 ((direction == normal_dir) ?
2707 (direction >= dim) ? 0 : dim - direction - 1) :
2708 (((direction < normal_dir) ? (n_rows + 1) : n_rows) *
2709 ((dim - direction == 3) ? n_rows : 1)));
2711 for (
int i2 = 0; i2 < n_blocks2; ++i2)
2713 for (
int i1 = 0; i1 < n_blocks1; ++i1)
2716 for (
int i = 0; i < mm; ++i)
2717 x[i] = in[stride * i];
2719 for (
int col = 0; col < nn; ++col)
2723 if (contract_over_rows)
2724 val0 = shape_data[col];
2726 val0 = shape_data[col * n_columns];
2728 Number res0 = val0 * x[0];
2729 for (
int i = 1; i < mm; ++i)
2731 if (contract_over_rows)
2732 val0 = shape_data[i * n_columns + col];
2734 val0 = shape_data[col * n_columns + i];
2736 res0 += val0 * x[i];
2739 out[stride * col] += res0;
2742 out[stride * col] = res0;
2745 if (one_line ==
false)
2751 if (one_line ==
false)
2753 in += stride * (mm - 1);
2754 out += stride * (nn - 1);
2765 template <
int face_direction,
2766 bool contract_onto_face,
2781 static_assert(max_derivative >= 0 && max_derivative < 3,
2782 "Only derivative orders 0-2 implemented");
2783 Assert(shape_values !=
nullptr,
2785 "The given array shape_values must not be the null pointer."));
2789 constexpr int n_blocks1 = (face_direction == normal_dir) ? (n_rows - 1) :
2790 ((face_direction == 0 && normal_dir == 2) ||
2791 (face_direction == 1 && normal_dir == 2) ||
2792 (face_direction == 2 && normal_dir == 1)) ?
2795 constexpr int n_blocks2 = (dim == 2) ?
2797 ((face_direction == normal_dir) ?
2799 (((face_direction == 0 && normal_dir == 1) ||
2800 (face_direction == 1 && normal_dir == 0) ||
2801 (face_direction == 2 && normal_dir == 0)) ?
2807 constexpr int in_stride =
2808 (face_direction == normal_dir) ?
2810 ((face_direction == 0) ?
2812 ((face_direction == 2) ?
2813 n_rows * (n_rows + 1) :
2814 ((face_direction == 1 && normal_dir == 0) ? (n_rows + 1) :
2816 constexpr int out_stride = n_blocks1 * n_blocks2;
2820 for (
int i2 = 0; i2 < n_blocks2; ++i2)
2822 for (
int i1 = 0; i1 < n_blocks1; ++i1)
2824 if (contract_onto_face ==
true)
2826 Number res0 = shape_values[0] * in[0];
2829 if (max_derivative > 0)
2830 res1 = shape_values[n_rows] * in[0];
2832 if (max_derivative > 1)
2833 res2 = shape_values[2 * n_rows] * in[0];
2835 for (
int ind = 1; ind < n_rows; ++ind)
2837 res0 += shape_values[ind] * in[in_stride * ind];
2838 if (max_derivative > 0)
2839 res1 += shape_values[ind + n_rows] * in[in_stride * ind];
2841 if (max_derivative > 1)
2843 shape_values[ind + 2 * n_rows] * in[in_stride * ind];
2849 if (max_derivative > 0)
2850 out[out_stride] += res1;
2852 if (max_derivative > 1)
2853 out[2 * out_stride] += res2;
2859 if (max_derivative > 0)
2860 out[out_stride] = res1;
2862 if (max_derivative > 1)
2863 out[2 * out_stride] = res2;
2868 for (
int col = 0; col < n_rows; ++col)
2871 out[col * in_stride] += shape_values[col] * in[0];
2873 out[col * in_stride] = shape_values[col] * in[0];
2875 if (max_derivative > 0)
2876 out[col * in_stride] +=
2877 shape_values[col + n_rows] * in[out_stride];
2879 if (max_derivative > 1)
2880 out[col * in_stride] +=
2881 shape_values[col + 2 * n_rows] * in[2 * out_stride];
2888 switch (face_direction)
2891 in += contract_onto_face ? n_rows : 1;
2892 out += contract_onto_face ? 1 : n_rows;
2903 if (normal_dir == 0)
2905 if (contract_onto_face)
2910 if (normal_dir == 1)
2912 if (contract_onto_face)
2917 if (normal_dir == 2)
2919 if (contract_onto_face)
2936 if (face_direction == 1 && dim == 3)
2939 if (contract_onto_face)
2941 if (normal_dir == 0)
2943 in += (n_rows + 1) * (n_rows - 1);
2944 out -= n_rows * (n_rows + 1) - 1;
2946 if (normal_dir == 1)
2948 in += (n_rows - 1) * (n_rows - 1);
2949 out -= (n_rows - 1) * (n_rows - 1) - 1;
2951 if (normal_dir == 2)
2953 in += (n_rows - 1) * (n_rows);
2954 out -= (n_rows) * (n_rows + 1) - 1;
2959 if (normal_dir == 0)
2961 out += (n_rows + 1) * (n_rows - 1);
2962 in -= n_rows * (n_rows + 1) - 1;
2964 if (normal_dir == 1)
2966 out += (n_rows - 1) * (n_rows - 1);
2967 in -= (n_rows - 1) * (n_rows - 1) - 1;
2969 if (normal_dir == 2)
2971 out += (n_rows - 1) * (n_rows);
2972 in -= (n_rows) * (n_rows + 1) - 1;
2987 template <
typename Number,
typename Number2>
2993 template <
int dim,
typename Number,
typename Number2>
3005 template <
int dim,
typename Number>
3011 const unsigned int derivative = 1)
3013 const int n_shapes = poly.size();
3016 std::array<Number, dim> point;
3017 for (
unsigned int d = 0; d < dim; ++d)
3019 for (
int i = 0; i < n_shapes; ++i)
3020 poly[i].values_of_array(point, derivative, shapes[i].data());
3028 template <
typename Number>
3048 bool do_renumber =
true>
3053 std::array<typename ProductTypeNoPoint<Number, Number2>::type,
3056 const std::vector<unsigned int> & renumber,
3057 const ::ndarray<Number2, 2, dim> *shapes,
3058 const int n_shapes_runtime,
3061 static_assert(0 <= dim && dim <= 3,
"Only dim=0,1,2,3 implemented");
3062 static_assert(1 <= n_values && n_values <= 2,
3063 "Only n_values=1,2 implemented");
3065 const int n_shapes = length > 0 ? length : n_shapes_runtime;
3070 const Number *values_2 =
3073 Utilities::fixed_power<dim>(n_shapes_runtime)) :
3076 std::array<Number3, 2 + n_values> result = {};
3077 for (
int i1 = 0; i1 < (dim > 1 ? n_shapes : 1); ++i1)
3080 std::array<Number3, 1 + n_values> inner_result = {};
3084 if (do_renumber && !renumber.empty())
3085 for (
int i0 = 0; i0 < n_shapes; ++i0, ++i)
3088 inner_result[0] += shapes[i0][1][0] * values[renumber[i]];
3090 inner_result[1] += shapes[i0][0][0] * values[renumber[i]];
3092 inner_result[2] += shapes[i0][0][0] * values_2[renumber[i]];
3095 for (
int i0 = 0; i0 < n_shapes; ++i0, ++i)
3098 inner_result[0] += shapes[i0][1][0] * values[i];
3100 inner_result[1] += shapes[i0][0][0] * values[i];
3102 inner_result[2] += shapes[i0][0][0] * values_2[i];
3109 result[0] += inner_result[0] * shapes[i1][0][1];
3110 result[1] += inner_result[1] * shapes[i1][1][1];
3112 result[2] += inner_result[1] * shapes[i1][0][1];
3114 result[3] += inner_result[2] * shapes[i1][0][1];
3119 result[0] = inner_result[0];
3121 result[1] = inner_result[1];
3123 result[2] = inner_result[2];
3139 bool do_renumber =
true>
3140 inline std::array<typename ProductTypeNoPoint<Number, Number2>::type,
3143 const ::ndarray<Number2, 2, dim> *shapes,
3145 const Number * values,
3146 const std::vector<unsigned int> & renumber = {})
3148 static_assert(0 <= dim && dim <= 3,
"Only dim=0,1,2,3 implemented");
3149 static_assert(1 <= n_values && n_values <= 2,
3150 "Only n_values=1,2 implemented");
3154 std::array<Number3, dim + n_values> result = {};
3168 for (
int i2 = 0, i = 0; i2 < (dim > 2 ? n_shapes : 1); ++i2)
3170 std::array<Number3, 2 + n_values> inner_result;
3175 do_interpolate_xy<dim, 2, Number2, Number, n_values, do_renumber>(
3176 values, renumber, shapes, n_shapes, i);
3177 else if (n_shapes == 3)
3179 do_interpolate_xy<dim, 3, Number2, Number, n_values, do_renumber>(
3180 values, renumber, shapes, n_shapes, i);
3181 else if (n_shapes == 4)
3183 do_interpolate_xy<dim, 4, Number2, Number, n_values, do_renumber>(
3184 values, renumber, shapes, n_shapes, i);
3185 else if (n_shapes == 5)
3187 do_interpolate_xy<dim, 5, Number2, Number, n_values, do_renumber>(
3188 values, renumber, shapes, n_shapes, i);
3189 else if (n_shapes == 6)
3191 do_interpolate_xy<dim, 6, Number2, Number, n_values, do_renumber>(
3192 values, renumber, shapes, n_shapes, i);
3196 values, renumber, shapes, n_shapes, i);
3201 result[0] += inner_result[0] * shapes[i2][0][2];
3202 result[1] += inner_result[1] * shapes[i2][0][2];
3203 result[2] += inner_result[2] * shapes[i2][1][2];
3205 result[3] += inner_result[2] * shapes[i2][0][2];
3207 result[4] += inner_result[3] * shapes[i2][0][2];
3212 result[0] = inner_result[0];
3213 result[1] = inner_result[1];
3215 result[2] = inner_result[2];
3217 result[3] = inner_result[3];
3222 result[0] = inner_result[0];
3224 result[1] = inner_result[1];
3226 result[2] = inner_result[2];
3239 template <
int dim,
typename Number,
typename Number2,
int n_values = 1>
3240 inline std::array<typename ProductTypeNoPoint<Number, Number2>::type,
3243 const unsigned int n_shapes,
3244 const Number * values,
3246 const std::vector<unsigned int> &renumber = {})
3248 static_assert(0 <= dim && dim <= 3,
"Only dim=0,1,2,3 implemented");
3249 static_assert(1 <= n_values && n_values <= 2,
3250 "Only n_values=1,2 implemented");
3257 const Number *values_2 =
3258 n_values > 1 ? values + Utilities::fixed_power<dim>(n_shapes) : nullptr;
3261 for (
unsigned int i = 0; i < renumber.size(); ++i)
3264 std::array<Number3, dim + n_values> result;
3268 result[0] = values[0];
3270 result[1] = values_2[0];
3275 result[0] = Number3(values[1] - values[0]);
3277 result[1] = Number3(values[0]) + p[0] * result[0];
3279 result[2] = Number3(values_2[0]) + p[0] * (values_2[1] - values_2[0]);
3283 const Number3 val10 = Number3(values[1] - values[0]);
3284 const Number3 val32 = Number3(values[3] - values[2]);
3285 const Number3 tmp0 = Number3(values[0]) + p[0] * val10;
3286 const Number3 tmp1 = Number3(values[2]) + p[0] * val32;
3289 result[0] = val10 + p[1] * (val32 - val10);
3290 result[1] = tmp1 - tmp0;
3293 result[2] = tmp0 + p[1] * result[1];
3297 const Number3 tmp0_2 =
3298 Number3(values_2[0]) + p[0] * (values_2[1] - values_2[0]);
3299 const Number3 tmp1_2 =
3300 Number3(values_2[2]) + p[0] * (values_2[3] - values_2[0]);
3301 result[3] = tmp0_2 + p[1] * (tmp1_2 - tmp0_2);
3306 const Number3 val10 = Number3(values[1] - values[0]);
3307 const Number3 val32 = Number3(values[3] - values[2]);
3308 const Number3 tmp0 = Number3(values[0]) + p[0] * val10;
3309 const Number3 tmp1 = Number3(values[2]) + p[0] * val32;
3310 const Number3 tmp10 = tmp1 - tmp0;
3311 const Number3 tmpy0 = tmp0 + p[1] * tmp10;
3313 const Number3 val54 = Number3(values[5] - values[4]);
3314 const Number3 val76 = Number3(values[7] - values[6]);
3315 const Number3 tmp2 = Number3(values[4]) + p[0] * val54;
3316 const Number3 tmp3 = Number3(values[6]) + p[0] * val76;
3317 const Number3 tmp32 = tmp3 - tmp2;
3318 const Number3 tmpy1 = tmp2 + p[1] * tmp32;
3321 result[2] = tmpy1 - tmpy0;
3322 result[1] = tmp10 + p[2] * (tmp32 - tmp10);
3323 const Number3 tmpz0 = val10 + p[1] * (val32 - val10);
3324 result[0] = tmpz0 + p[2] * (val54 + p[1] * (val76 - val54) - tmpz0);
3327 result[3] = tmpy0 + p[2] * result[2];
3370 template <
int dim,
typename Number,
typename Number2>
3376 const std::vector<Number> & values,
3378 const bool d_linear =
false,
3379 const std::vector<unsigned int> & renumber = {})
3383 std::array<Number3, dim + 1> result;
3387 poly.size(), values.data(), p, renumber);
3392 std::array<::ndarray<Number2, 2, dim>, 200> shapes;
3397 shapes.data(), poly.size(),
values.data(), renumber);
3399 return std::make_pair(result[dim],
3410 bool do_renumber =
true>
3417 const std::vector<unsigned int> & renumber,
3418 const ::ndarray<Number2, 2, dim> *shapes,
3419 const int n_shapes_runtime,
3422 const int n_shapes = length > 0 ? length : n_shapes_runtime;
3424 Number3 result = {};
3425 for (
int i1 = 0; i1 < (dim > 1 ? n_shapes : 1); ++i1)
3432 if (do_renumber && !renumber.empty())
3433 for (
int i0 = 0; i0 < n_shapes; ++i0, ++i)
3434 value += shapes[i0][0][0] * values[renumber[i]];
3436 for (
int i0 = 0; i0 < n_shapes; ++i0, ++i)
3437 value += shapes[i0][0][0] * values[i];
3440 result +=
value * shapes[i1][0][1];
3449 template <
int dim,
typename Number,
typename Number2,
bool do_renumber = true>
3452 const ::ndarray<Number2, 2, dim> *shapes,
3454 const Number * values,
3455 const std::vector<unsigned int> & renumber = {})
3457 static_assert(dim >= 0 && dim <= 3,
"Only dim=0,1,2,3 implemented");
3469 Number3 result = {};
3470 for (
int i2 = 0, i = 0; i2 < (dim > 2 ? n_shapes : 1); ++i2)
3472 Number3 inner_result;
3477 do_interpolate_xy_value<dim, 2, Number2, Number, do_renumber>(
3478 values, renumber, shapes, n_shapes, i);
3479 else if (n_shapes == 3)
3481 do_interpolate_xy_value<dim, 3, Number2, Number, do_renumber>(
3482 values, renumber, shapes, n_shapes, i);
3483 else if (n_shapes == 4)
3485 do_interpolate_xy_value<dim, 4, Number2, Number, do_renumber>(
3486 values, renumber, shapes, n_shapes, i);
3487 else if (n_shapes == 5)
3489 do_interpolate_xy_value<dim, 5, Number2, Number, do_renumber>(
3490 values, renumber, shapes, n_shapes, i);
3491 else if (n_shapes == 6)
3493 do_interpolate_xy_value<dim, 6, Number2, Number, do_renumber>(
3494 values, renumber, shapes, n_shapes, i);
3498 values, renumber, shapes, n_shapes, i);
3502 result += inner_result * shapes[i2][0][2];
3506 result = inner_result;
3515 template <
int dim,
typename Number,
typename Number2>
3518 const unsigned int n_shapes,
3519 const Number * values,
3521 const std::vector<unsigned int> &renumber = {})
3524 static_assert(dim >= 0 && dim <= 3,
"Only dim=0,1,2,3 implemented");
3529 for (
unsigned int i = 0; i < renumber.size(); ++i)
3539 return Number3(values[0]) + p[0] * Number3(values[1] - values[0]);
3543 const Number3 val10 = Number3(values[1] - values[0]);
3544 const Number3 val32 = Number3(values[3] - values[2]);
3545 const Number3 tmp0 = Number3(values[0]) + p[0] * val10;
3546 const Number3 tmp1 = Number3(values[2]) + p[0] * val32;
3547 return tmp0 + p[1] * (tmp1 - tmp0);
3551 const Number3 val10 = Number3(values[1] - values[0]);
3552 const Number3 val32 = Number3(values[3] - values[2]);
3553 const Number3 tmp0 = Number3(values[0]) + p[0] * val10;
3554 const Number3 tmp1 = Number3(values[2]) + p[0] * val32;
3555 const Number3 tmpy0 = tmp0 + p[1] * (tmp1 - tmp0);
3557 const Number3 val54 = Number3(values[5] - values[4]);
3558 const Number3 val76 = Number3(values[7] - values[6]);
3559 const Number3 tmp2 = Number3(values[4]) + p[0] * val54;
3560 const Number3 tmp3 = Number3(values[6]) + p[0] * val76;
3561 const Number3 tmpy1 = tmp2 + p[1] * (tmp3 - tmp2);
3563 return tmpy0 + p[2] * (tmpy1 - tmpy0);
3572 template <
int dim,
typename Number,
typename Number2>
3576 const std::vector<Number> & values,
3578 const bool d_linear =
false,
3579 const std::vector<unsigned int> & renumber = {})
3592 std::array<::ndarray<Number2, 2, dim>, 200> shapes;
3593 const int n_shapes = poly.size();
3594 std::array<Number2, dim>
point;
3595 for (
unsigned int d = 0;
d < dim; ++
d)
3597 for (
int i = 0; i < n_shapes; ++i)
3598 poly[i].values_of_array(point, 0, shapes[i].data());
3599 result = evaluate_tensor_product_value_shapes<dim, Number, Number2>(
3600 shapes.data(), n_shapes,
values.data(), renumber);
3611 template <
int derivative_order,
typename Number,
typename Number2>
3615 const std::vector<Number> & values,
3617 const std::vector<unsigned int> & renumber = {})
3621 const int n_shapes = poly.size();
3623 Assert(renumber.empty() || renumber.size() == values.size(),
3626 std::array<Number2, derivative_order + 1> shapes;
3628 if (renumber.empty())
3629 for (
int i = 0; i < n_shapes; ++i)
3631 poly[i].value(p[0], derivative_order, shapes.data());
3632 result[0] += shapes[derivative_order] * values[i];
3635 for (
int i = 0; i < n_shapes; ++i)
3637 poly[i].value(p[0], derivative_order, shapes.data());
3638 result[0] += shapes[derivative_order] *
values[renumber[i]];
3649 template <
int derivative_order,
typename Number,
typename Number2>
3651 derivative_order + 1,
3655 const std::vector<Number> & values,
3657 const std::vector<unsigned int> & renumber = {})
3660 constexpr int dim = 2;
3662 const int n_shapes = poly.size();
3664 Assert(renumber.empty() || renumber.size() == values.size(),
3670 std::array<Number2, dim> point;
3671 for (
unsigned int d = 0; d < dim; ++d)
3673 for (
int i = 0; i < n_shapes; ++i)
3674 poly[i].values_of_array(point, derivative_order, &shapes[i][0]);
3677 for (
int i1 = 0, i = 0; i1 < n_shapes; ++i1)
3680 if (renumber.empty())
3681 for (
int i0 = 0; i0 < n_shapes; ++i0, ++i)
3682 for (
unsigned int d = 0; d <= derivative_order; ++d)
3683 result_x[d] += shapes[i0][d][0] * values[i];
3685 for (
int i0 = 0; i0 < n_shapes; ++i0, ++i)
3686 for (
unsigned int d = 0; d <= derivative_order; ++d)
3687 result_x[d] += shapes[i0][d][0] * values[renumber[i]];
3689 for (
unsigned int d = 0; d <= derivative_order; ++d)
3690 result[d] += shapes[i1][d][1] * result_x[derivative_order - d];
3701 template <
int derivative_order,
typename Number,
typename Number2>
3703 ((derivative_order + 1) * (derivative_order + 2)) / 2,
3707 const std::vector<Number> & values,
3709 const std::vector<unsigned int> & renumber = {})
3712 constexpr int dim = 3;
3713 constexpr int n_derivatives =
3714 ((derivative_order + 1) * (derivative_order + 2)) / 2;
3716 const int n_shapes = poly.size();
3718 Assert(renumber.empty() || renumber.size() == values.size(),
3724 std::array<Number2, dim> point;
3725 for (
unsigned int d = 0; d < dim; ++d)
3727 for (
int i = 0; i < n_shapes; ++i)
3728 poly[i].values_of_array(point, derivative_order, &shapes[i][0]);
3731 for (
int i2 = 0, i = 0; i2 < n_shapes; ++i2)
3734 for (
int i1 = 0; i1 < n_shapes; ++i1)
3738 if (renumber.empty())
3739 for (
int i0 = 0; i0 < n_shapes; ++i0, ++i)
3740 for (
unsigned int d = 0; d <= derivative_order; ++d)
3741 result_x[d] += shapes[i0][d][0] * values[i];
3743 for (
int i0 = 0; i0 < n_shapes; ++i0, ++i)
3744 for (
unsigned int d = 0; d <= derivative_order; ++d)
3745 result_x[d] += shapes[i0][d][0] * values[renumber[i]];
3751 for (
unsigned int d = 0, c = 0; d <= derivative_order; ++d)
3752 for (
unsigned int e = d; e <= derivative_order; ++e, ++c)
3754 shapes[i1][e - d][1] * result_x[derivative_order - e];
3758 for (
unsigned int d = 0, c = 0;
d <= derivative_order; ++
d)
3759 for (
unsigned int e = d;
e <= derivative_order; ++
e, ++c)
3760 result[c] += shapes[i2][d][2] * result_xy[c];
3767 template <
int dim,
typename Number,
typename Number2>
3771 const std::vector<Number> & values,
3773 const std::vector<unsigned int> & renumber = {})
3775 static_assert(dim >= 1 && dim <= 3,
"Only dim=1,2,3 implemented");
3778 evaluate_tensor_product_higher_derivatives<2>(poly, values, p, renumber);
3788 for (
unsigned int d = 0, c = 0; d < 2; ++d)
3789 for (
unsigned int e = d; e < 2; ++e, ++c)
3793 for (
unsigned int d = 0; d < 2; ++d)
3794 result[d][2] =
hessian[3 + d];
3820 const ::ndarray<Number, 2, dim> * shapes,
3821 const std::array<Number2, 2 + n_values> &test_grads_value,
3822 const int n_shapes_runtime,
3825 static_assert(0 <= dim && dim <= 3,
"Only dim=0,1,2,3 implemented");
3826 static_assert(1 <= n_values && n_values <= 2,
3827 "Only n_values=1,2 implemented");
3833 constexpr unsigned int array_size = length > 0 ? length : 1;
3834 std::array<Number, array_size> shape_values_x;
3835 std::array<Number, array_size> shape_derivs_x;
3836 for (
unsigned int j = 0; j < array_size; ++j)
3838 shape_values_x[j] = shapes[j][0][0];
3839 shape_derivs_x[j] = shapes[j][1][0];
3841 for (
int i1 = 0; i1 < (dim > 1 ? length : 1); ++i1)
3843 const Number2 test_value_y =
3844 dim > 1 ? (test_grads_value[2] * shapes[i1][0][1] +
3845 test_grads_value[1] * shapes[i1][1][1]) :
3846 test_grads_value[2];
3847 const Number2 test_grad_xy =
3848 dim > 1 ? test_grads_value[0] * shapes[i1][0][1] :
3849 test_grads_value[0];
3850 Number2 test_value_y_2;
3852 test_value_y_2 = dim > 1 ?
3853 test_grads_value[3] * shapes[i1][0][1] :
3854 test_grads_value[3];
3856 Number2 *values_ptr = values + i + i1 * length;
3857 Number2 *values_ptr_2 =
3858 n_values > 1 ? values_ptr +
Utilities::pow(length, dim) :
nullptr;
3859 for (
int i0 = 0; i0 < length; ++i0)
3862 values_ptr[i0] += shape_values_x[i0] * test_value_y;
3864 values_ptr[i0] = shape_values_x[i0] * test_value_y;
3865 values_ptr[i0] += shape_derivs_x[i0] * test_grad_xy;
3869 values_ptr_2[i0] += shape_values_x[i0] * test_value_y_2;
3871 values_ptr_2[i0] = shape_values_x[i0] * test_value_y_2;
3875 i += (dim > 1 ? length * length : length);
3879 for (
int i1 = 0; i1 < (dim > 1 ? n_shapes_runtime : 1); ++i1)
3881 const Number2 test_value_y =
3882 dim > 1 ? (test_grads_value[2] * shapes[i1][0][1] +
3883 test_grads_value[1] * shapes[i1][1][1]) :
3884 test_grads_value[2];
3885 const Number2 test_grad_xy =
3886 dim > 1 ? test_grads_value[0] * shapes[i1][0][1] :
3887 test_grads_value[0];
3888 Number2 test_value_y_2;
3890 test_value_y_2 = dim > 1 ?
3891 test_grads_value[3] * shapes[i1][0][1] :
3892 test_grads_value[3];
3894 Number2 *values_ptr = values + i + i1 * n_shapes_runtime;
3895 Number2 *values_ptr_2 =
3897 values_ptr + Utilities::fixed_power<dim>(n_shapes_runtime) :
3899 for (
int i0 = 0; i0 < n_shapes_runtime; ++i0)
3902 values_ptr[i0] += shapes[i0][0][0] * test_value_y;
3904 values_ptr[i0] = shapes[i0][0][0] * test_value_y;
3905 values_ptr[i0] += shapes[i0][1][0] * test_grad_xy;
3909 values_ptr_2[i0] += shapes[i0][0][0] * test_value_y_2;
3911 values_ptr_2[i0] = shapes[i0][0][0] * test_value_y_2;
3915 i += (dim > 1 ? n_shapes_runtime * n_shapes_runtime : n_shapes_runtime);
3932 const ::ndarray<Number, 2, dim> *shapes,
3934 const Number2 *
value,
3938 static_assert(0 <= dim && dim <= 3,
"Only dim=0,1,2,3 implemented");
3939 static_assert(1 <= n_values && n_values <= 2,
3940 "Only n_values=1,2 implemented");
3947 values[0] +=
value[0];
3949 values[0] =
value[0];
3953 values[1] +=
value[1];
3955 values[1] =
value[1];
3962 std::array<Number2, 2 + n_values> test_grads_value;
3963 for (
int i2 = 0, i = 0; i2 < (dim > 2 ? n_shapes : 1); ++i2)
3966 test_grads_value[0] =
3969 test_grads_value[1] = dim > 2 ?
gradient[1] * shapes[i2][0][2] :
3970 (dim > 1 ?
gradient[1] : Number2());
3972 test_grads_value[2] =
3974 (
value[0] * shapes[i2][0][2] +
gradient[2] * shapes[i2][1][2]) :
3978 test_grads_value[3] =
3979 dim > 2 ?
value[1] * shapes[i2][0][2] :
value[1];
3983 do_apply_test_functions_xy<dim, 2, Number2, Number, add, n_values>(
3984 values, shapes, test_grads_value, n_shapes, i);
3985 else if (n_shapes == 3)
3986 do_apply_test_functions_xy<dim, 3, Number2, Number, add, n_values>(
3987 values, shapes, test_grads_value, n_shapes, i);
3988 else if (n_shapes == 4)
3989 do_apply_test_functions_xy<dim, 4, Number2, Number, add, n_values>(
3990 values, shapes, test_grads_value, n_shapes, i);
3991 else if (n_shapes == 5)
3992 do_apply_test_functions_xy<dim, 5, Number2, Number, add, n_values>(
3993 values, shapes, test_grads_value, n_shapes, i);
3994 else if (n_shapes == 6)
3995 do_apply_test_functions_xy<dim, 6, Number2, Number, add, n_values>(
3996 values, shapes, test_grads_value, n_shapes, i);
3999 values, shapes, test_grads_value, n_shapes, i);
4016 const unsigned int n_shapes,
4017 const Number2 *
value,
4023 static_assert(0 <= dim && dim <= 3,
"Only dim=0,1,2,3 implemented");
4024 static_assert(1 <= n_values && n_values <= 2,
4025 "Only n_values=1,2 implemented");
4034 values[0] +=
value[0];
4036 values[0] =
value[0];
4040 values[1] +=
value[1];
4042 values[1] =
value[1];
4050 values[0] +=
value[0] - difference;
4051 values[1] += difference;
4055 values[0] =
value[0] - difference;
4056 values[1] = difference;
4060 const Number2 product =
value[1] * p[0];
4063 values[2] +=
value[1] - product;
4064 values[3] += product;
4068 values[2] =
value[1] - product;
4069 values[3] = product;
4075 const Number2 test_value_y1 =
value[0] * p[1] +
gradient[1];
4076 const Number2 test_value_y0 =
value[0] - test_value_y1;
4077 const Number2 test_grad_xy1 =
gradient[0] * p[1];
4078 const Number2 test_grad_xy0 =
gradient[0] - test_grad_xy1;
4079 const Number2 value0 = p[0] * test_value_y0 + test_grad_xy0;
4080 const Number2 value1 = p[0] * test_value_y1 + test_grad_xy1;
4084 values[0] += test_value_y0 - value0;
4085 values[1] += value0;
4086 values[2] += test_value_y1 - value1;
4087 values[3] += value1;
4091 values[0] = test_value_y0 - value0;
4093 values[2] = test_value_y1 - value1;
4099 const Number2 test_value_y1_2 =
value[1] * p[1];
4100 const Number2 test_value_y0_2 =
value[1] - test_value_y1_2;
4101 const Number2 value0_2 = p[0] * test_value_y1_2;
4102 const Number2 value1_2 = p[0] * test_value_y1_2;
4106 values[4] += test_value_y0_2 - value0_2;
4107 values[5] += value0_2;
4108 values[6] += test_value_y1_2 - value1_2;
4109 values[7] += value1_2;
4113 values[4] = test_value_y0_2 - value0_2;
4114 values[5] = value0_2;
4115 values[6] = test_value_y1_2 - value1_2;
4116 values[7] = value1_2;
4124 const Number2 test_value_z1 =
value[0] * p[2] +
gradient[2];
4125 const Number2 test_value_z0 =
value[0] - test_value_z1;
4126 const Number2 test_grad_x1 =
gradient[0] * p[2];
4127 const Number2 test_grad_x0 =
gradient[0] - test_grad_x1;
4128 const Number2 test_grad_y1 =
gradient[1] * p[2];
4129 const Number2 test_grad_y0 =
gradient[1] - test_grad_y1;
4131 const Number2 test_value_y01 = test_value_z0 * p[1] + test_grad_y0;
4132 const Number2 test_value_y00 = test_value_z0 - test_value_y01;
4133 const Number2 test_grad_xy01 = test_grad_x0 * p[1];
4134 const Number2 test_grad_xy00 = test_grad_x0 - test_grad_xy01;
4135 const Number2 test_value_y11 = test_value_z1 * p[1] + test_grad_y1;
4136 const Number2 test_value_y10 = test_value_z1 - test_value_y11;
4137 const Number2 test_grad_xy11 = test_grad_x1 * p[1];
4138 const Number2 test_grad_xy10 = test_grad_x1 - test_grad_xy11;
4140 const Number2 value00 = p[0] * test_value_y00 + test_grad_xy00;
4141 const Number2 value01 = p[0] * test_value_y01 + test_grad_xy01;
4142 const Number2 value10 = p[0] * test_value_y10 + test_grad_xy10;
4143 const Number2 value11 = p[0] * test_value_y11 + test_grad_xy11;
4147 values[0] += test_value_y00 - value00;
4148 values[1] += value00;
4149 values[2] += test_value_y01 - value01;
4150 values[3] += value01;
4151 values[4] += test_value_y10 - value10;
4152 values[5] += value10;
4153 values[6] += test_value_y11 - value11;
4154 values[7] += value11;
4158 values[0] = test_value_y00 - value00;
4159 values[1] = value00;
4160 values[2] = test_value_y01 - value01;
4161 values[3] = value01;
4162 values[4] = test_value_y10 - value10;
4163 values[5] = value10;
4164 values[6] = test_value_y11 - value11;
4165 values[7] = value11;
4177 template <
int dim,
typename Number,
typename Number2,
int n_values = 1>
4180 const ::ndarray<Number, 2, dim> *shapes,
4181 const unsigned int n_shapes,
4182 const Number2 *
value,
4186 const bool is_linear,
4230 template <
int dim,
int length,
typename Number2,
typename Number,
bool add>
4238 const ::ndarray<Number, 2, dim> *shapes,
4239 const Number2 & test_value,
4240 const int n_shapes_runtime,
4245 constexpr unsigned int array_size = length > 0 ? length : 1;
4246 std::array<Number, array_size> shape_values_x;
4247 for (
unsigned int i1 = 0; i1 < array_size; ++i1)
4248 shape_values_x[i1] = shapes[i1][0][0];
4249 for (
unsigned int i1 = 0; i1 < (dim > 1 ? length : 1); ++i1)
4251 const Number2 test_value_y =
4252 dim > 1 ? test_value * shapes[i1][0][1] : test_value;
4254 Number2 *values_ptr = values + i + i1 * length;
4255 for (
unsigned int i0 = 0; i0 < length; ++i0)
4258 values_ptr[i0] += shape_values_x[i0] * test_value_y;
4260 values_ptr[i0] = shape_values_x[i0] * test_value_y;
4263 i += (dim > 1 ? length * length : length);
4267 for (
int i1 = 0; i1 < (dim > 1 ? n_shapes_runtime : 1); ++i1)
4269 const Number2 test_value_y =
4270 dim > 1 ? test_value * shapes[i1][0][1] : test_value;
4272 Number2 *values_ptr = values + i + i1 * n_shapes_runtime;
4273 for (
int i0 = 0; i0 < n_shapes_runtime; ++i0)
4276 values_ptr[i0] += shapes[i0][0][0] * test_value_y;
4278 values_ptr[i0] = shapes[i0][0][0] * test_value_y;
4281 i += (dim > 1 ? n_shapes_runtime * n_shapes_runtime : n_shapes_runtime);
4290 template <
int dim,
typename Number,
typename Number2,
bool add>
4293 const ::ndarray<Number, 2, dim> *shapes,
4295 const Number2 &
value,
4298 static_assert(dim >= 0 && dim <= 3,
"Only dim=0,1,2,3 implemented");
4313 for (
int i2 = 0, i = 0; i2 < (dim > 2 ? n_shapes : 1); ++i2)
4316 test_value = dim > 2 ?
value * shapes[i2][0][2] :
value;
4321 do_apply_test_functions_xy_value<dim, 2, Number2, Number, add>(
4322 values, shapes, test_value, n_shapes, i);
4323 else if (n_shapes == 3)
4324 do_apply_test_functions_xy_value<dim, 3, Number2, Number, add>(
4325 values, shapes, test_value, n_shapes, i);
4326 else if (n_shapes == 4)
4327 do_apply_test_functions_xy_value<dim, 4, Number2, Number, add>(
4328 values, shapes, test_value, n_shapes, i);
4329 else if (n_shapes == 5)
4330 do_apply_test_functions_xy_value<dim, 5, Number2, Number, add>(
4331 values, shapes, test_value, n_shapes, i);
4332 else if (n_shapes == 6)
4333 do_apply_test_functions_xy_value<dim, 6, Number2, Number, add>(
4334 values, shapes, test_value, n_shapes, i);
4337 values, shapes, test_value, n_shapes, i);
4347 template <
int dim,
typename Number,
typename Number2,
bool add>
4350 const Number2 &
value,
4355 static_assert(dim >= 0 && dim <= 3,
"Only dim=0,1,2,3 implemented");
4368 const auto x0 = 1. - p[0], x1 = p[0];
4372 values[0] +=
value * x0;
4373 values[1] +=
value * x1;
4377 values[0] =
value * x0;
4378 values[1] =
value * x1;
4383 const auto x0 = 1. - p[0], x1 = p[0], y0 = 1. - p[1], y1 = p[1];
4385 const auto test_value_y0 =
value * y0;
4386 const auto test_value_y1 =
value * y1;
4390 values[0] += x0 * test_value_y0;
4391 values[1] += x1 * test_value_y0;
4392 values[2] += x0 * test_value_y1;
4393 values[3] += x1 * test_value_y1;
4397 values[0] = x0 * test_value_y0;
4398 values[1] = x1 * test_value_y0;
4399 values[2] = x0 * test_value_y1;
4400 values[3] = x1 * test_value_y1;
4405 const auto x0 = 1. - p[0], x1 = p[0], y0 = 1. - p[1], y1 = p[1],
4406 z0 = 1. - p[2], z1 = p[2];
4408 const auto test_value_z0 =
value * z0;
4409 const auto test_value_z1 =
value * z1;
4411 const auto test_value_y00 = test_value_z0 * y0;
4412 const auto test_value_y01 = test_value_z0 * y1;
4413 const auto test_value_y10 = test_value_z1 * y0;
4414 const auto test_value_y11 = test_value_z1 * y1;
4418 values[0] += x0 * test_value_y00;
4419 values[1] += x1 * test_value_y00;
4420 values[2] += x0 * test_value_y01;
4421 values[3] += x1 * test_value_y01;
4422 values[4] += x0 * test_value_y10;
4423 values[5] += x1 * test_value_y10;
4424 values[6] += x0 * test_value_y11;
4425 values[7] += x1 * test_value_y11;
4429 values[0] = x0 * test_value_y00;
4430 values[1] = x1 * test_value_y00;
4431 values[2] = x0 * test_value_y01;
4432 values[3] = x1 * test_value_y01;
4433 values[4] = x0 * test_value_y10;
4434 values[5] = x1 * test_value_y10;
4435 values[6] = x0 * test_value_y11;
4436 values[7] = x1 * test_value_y11;
4448 template <
int dim,
typename Number,
typename Number2>
4451 const unsigned int n_shapes,
4452 const Number2 &
value,
4455 const bool is_linear,
4500 template <
int dim,
int n_po
ints_1d_
template,
typename Number>
4503 const unsigned int n_components,
4504 const int n_points_1d_non_template,
4507 const int n_points_1d = n_points_1d_template != -1 ?
4508 n_points_1d_template :
4509 n_points_1d_non_template;
4514 unsigned int compressed_index[100];
4515 compressed_index[0] = 0;
4516 for (
int i = 1; i < n_points_1d - 1; ++i)
4517 compressed_index[i] = 1;
4518 compressed_index[n_points_1d - 1] = 2;
4520 for (
unsigned int c = 0; c < n_components; ++c)
4521 for (
int k = 0; k < (dim > 2 ? n_points_1d : 1); ++k)
4522 for (
int j = 0; j < (dim > 1 ? n_points_1d : 1); ++j)
4524 const unsigned int shift =
4525 9 * compressed_index[k] + 3 * compressed_index[j];
4526 data[0] *= weights[shift];
4529 const Number weight = weights[shift + 1];
4530 for (
int i = 1; i < n_points_1d - 1; ++i)
4532 data[n_points_1d - 1] *= weights[shift + 2];
4533 data += n_points_1d;
4538 template <
int dim,
int n_po
ints_1d_
template,
typename Number>
4541 const unsigned int n_components,
4542 const int n_points_1d_non_template,
4545 const int n_points_1d = n_points_1d_template != -1 ?
4546 n_points_1d_template :
4547 n_points_1d_non_template;
4549 Assert((n_points_1d % 2) == 1,
4550 ExcMessage(
"The function can only with add number of points"));
4554 const unsigned int n_inside_1d = n_points_1d / 2;
4556 unsigned int compressed_index[100];
4559 for (
int i = 0; i < n_inside_1d; ++i)
4560 compressed_index[c++] = 0;
4561 compressed_index[c++] = 1;
4562 for (
int i = 0; i < n_inside_1d; ++i)
4563 compressed_index[c++] = 2;
4565 for (
unsigned int c = 0; c < n_components; ++c)
4566 for (
int k = 0; k < (dim > 2 ? n_points_1d : 1); ++k)
4567 for (
int j = 0; j < (dim > 1 ? n_points_1d : 1); ++j)
4569 const unsigned int shift =
4570 9 * compressed_index[k] + 3 * compressed_index[j];
4573 const Number weight1 = weights[shift];
4574 for (
int i = 0; i < n_inside_1d; ++i)
4575 data[c++] *= weight1;
4576 data[c++] *= weights[shift + 1];
4577 const Number weight2 = weights[shift + 2];
4578 for (
int i = 0; i < n_inside_1d; ++i)
4579 data[c++] *= weight2;
4580 data += n_points_1d;
4585 template <
int dim,
int n_po
ints_1d_
template,
typename Number>
4588 const unsigned int n_components,
4589 const int n_points_1d_non_template,
4592 const int n_points_1d = n_points_1d_template != -1 ?
4593 n_points_1d_template :
4594 n_points_1d_non_template;
4599 unsigned int compressed_index[100];
4600 compressed_index[0] = 0;
4601 for (
int i = 1; i < n_points_1d - 1; ++i)
4602 compressed_index[i] = 1;
4603 compressed_index[n_points_1d - 1] = 2;
4610 const auto check_and_set = [](Number &weight,
const Number &data) {
4611 if (weight == Number(-1.0) || weight == data)
4620 for (
unsigned int c = 0; c < Utilities::pow<unsigned int>(3, dim); ++c)
4621 weights[c] = Number(-1.0);
4623 for (
unsigned int c = 0; c < n_components; ++c)
4624 for (
int k = 0; k < (dim > 2 ? n_points_1d : 1); ++k)
4625 for (
int j = 0; j < (dim > 1 ? n_points_1d : 1);
4626 ++j, data += n_points_1d)
4628 const unsigned int shift =
4629 9 * compressed_index[k] + 3 * compressed_index[j];
4631 if (!check_and_set(weights[shift], data[0]))
4634 for (
int i = 1; i < n_points_1d - 1; ++i)
4635 if (!check_and_set(weights[shift + 1], data[i]))
4638 if (!check_and_set(weights[shift + 2], data[n_points_1d - 1]))
4646 template <
int dim,
int n_po
ints_1d_
template,
typename Number>
4649 const Number * data,
4650 const unsigned int n_components,
4651 const int n_points_1d_non_template,
4654 const int n_points_1d = n_points_1d_template != -1 ?
4655 n_points_1d_template :
4656 n_points_1d_non_template;
4658 Assert((n_points_1d % 2) == 1,
4659 ExcMessage(
"The function can only with add number of points"));
4663 const unsigned int n_inside_1d = n_points_1d / 2;
4665 unsigned int compressed_index[100];
4668 for (
int i = 0; i < n_inside_1d; ++i)
4669 compressed_index[c++] = 0;
4670 compressed_index[c++] = 1;
4671 for (
int i = 0; i < n_inside_1d; ++i)
4672 compressed_index[c++] = 2;
4679 const auto check_and_set = [](Number &weight,
const Number &data) {
4680 if (weight == Number(-1.0) || weight == data)
4689 for (
unsigned int c = 0; c < Utilities::pow<unsigned int>(3, dim); ++c)
4690 weights[c] = Number(-1.0);
4692 for (
unsigned int comp = 0; comp < n_components; ++comp)
4693 for (
int k = 0; k < (dim > 2 ? n_points_1d : 1); ++k)
4694 for (
int j = 0; j < (dim > 1 ? n_points_1d : 1);
4695 ++j, data += n_points_1d)
4697 const unsigned int shift =
4698 9 * compressed_index[k] + 3 * compressed_index[j];
4702 for (
int i = 0; i < n_inside_1d; ++i)
4703 if (!check_and_set(weights[shift], data[c++]))
4706 if (!check_and_set(weights[shift + 1], data[c++]))
4709 for (
int i = 0; i < n_inside_1d; ++i)
4710 if (!check_and_set(weights[shift + 2], data[c++]))
#define DEAL_II_ALWAYS_INLINE
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
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 > e(const Tensor< 2, dim, Number > &F)
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)
ProductTypeNoPoint< Number, Number2 >::type evaluate_tensor_product_value(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={})
std::array< typename ProductTypeNoPoint< Number, Number2 >::type, dim+n_values > evaluate_tensor_product_value_and_gradient_linear(const unsigned int n_shapes, const Number *values, const Point< dim, Number2 > &p, const std::vector< unsigned int > &renumber={})
void weight_fe_q_dofs_by_entity(const Number *weights, const unsigned int n_components, const int n_points_1d_non_template, Number *data)
void do_apply_test_functions_xy_value(Number2 *values, const ::ndarray< Number, 2, dim > *shapes, const Number2 &test_value, const int n_shapes_runtime, int &i)
void integrate_add_tensor_product_value_shapes(const ::ndarray< Number, 2, dim > *shapes, const int n_shapes, const Number2 &value, Number2 *values)
void even_odd_apply(const int n_rows_in, const int n_columns_in, const Number2 *DEAL_II_RESTRICT shapes, const Number *in, Number *out)
void compute_values_of_array(::ndarray< Number, 2, dim > *shapes, const std::vector< Polynomials::Polynomial< double > > &poly, const Point< dim, Number > &p, const unsigned int derivative=1)
void integrate_add_tensor_product_value_and_gradient_linear(const unsigned int n_shapes, const Number2 *value, const Tensor< 1, dim, Number2 > &gradient, Number2 *values, const Point< dim, Number > &p)
void integrate_add_tensor_product_value_and_gradient_shapes(const ::ndarray< Number, 2, dim > *shapes, const int n_shapes, const Number2 *value, const Tensor< 1, dim, Number2 > &gradient, Number2 *values)
void integrate_tensor_product_value(const ::ndarray< Number, 2, dim > *shapes, const unsigned int n_shapes, const Number2 &value, Number2 *values, const Point< dim, Number > &p, const bool is_linear, const bool do_add)
void weight_fe_q_dofs_by_entity_shifted(const Number *weights, const unsigned int n_components, const int n_points_1d_non_template, Number *data)
ProductTypeNoPoint< Number, Number2 >::type evaluate_tensor_product_value_linear(const unsigned int n_shapes, const Number *values, const Point< dim, Number2 > &p, const std::vector< unsigned int > &renumber={})
void do_apply_test_functions_xy(Number2 *values, const ::ndarray< Number, 2, dim > *shapes, const std::array< Number2, 2+n_values > &test_grads_value, const int n_shapes_runtime, int &i)
ProductTypeNoPoint< Number, Number2 >::type do_interpolate_xy_value(const Number *values, const std::vector< unsigned int > &renumber, const ::ndarray< Number2, 2, dim > *shapes, const int n_shapes_runtime, int &i)
ProductTypeNoPoint< Number, Number2 >::type evaluate_tensor_product_value_shapes(const ::ndarray< Number2, 2, dim > *shapes, const int n_shapes, const Number *values, const std::vector< unsigned int > &renumber={})
Tensor< 1, 1, typename ProductTypeNoPoint< Number, Number2 >::type > evaluate_tensor_product_higher_derivatives(const std::vector< Polynomials::Polynomial< double > > &poly, const std::vector< Number > &values, const Point< 1, Number2 > &p, const std::vector< unsigned int > &renumber={})
bool compute_weights_fe_q_dofs_by_entity(const Number *data, const unsigned int n_components, const int n_points_1d_non_template, Number *weights)
bool compute_weights_fe_q_dofs_by_entity_shifted(const Number *data, const unsigned int n_components, const int n_points_1d_non_template, Number *weights)
std::array< typename ProductTypeNoPoint< Number, Number2 >::type, 2+n_values > do_interpolate_xy(const Number *values, const std::vector< unsigned int > &renumber, const ::ndarray< Number2, 2, dim > *shapes, const int n_shapes_runtime, int &i)
void integrate_add_tensor_product_value_linear(const unsigned int n_shapes, const Number2 &value, Number2 *values, const Point< dim, Number > &p)
std::array< typename ProductTypeNoPoint< Number, Number2 >::type, dim+n_values > evaluate_tensor_product_value_and_gradient_shapes(const ::ndarray< Number2, 2, dim > *shapes, const int n_shapes, const Number *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_raviart_thomas
@ evaluate_symmetric_hierarchical
void integrate_tensor_product_value_and_gradient(const ::ndarray< Number, 2, dim > *shapes, const unsigned int n_shapes, const Number2 *value, const Tensor< 1, dim, Number2 > &gradient, Number2 *values, const Point< dim, Number > &p, const bool is_linear, const bool do_add)
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 values(const Number in[], Number out[]) const
const Number2 * shape_values
const Number2 * shape_hessians
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_gradients
EvaluatorTensorProductAnisotropic()
void gradients(const Number in[], Number out[]) const
void hessians(const Number in[], Number out[]) const
void hessians(const Number in[], Number out[]) const
void gradients_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 n_rows=0, const unsigned int n_columns=0)
const unsigned int n_columns
EvaluatorTensorProduct(const AlignedVector< Number2 > &shape_values, const unsigned int n_rows=0, const unsigned int n_columns=0)
void gradients(const Number in[], Number out[]) const
void hessians_one_line(const Number in[], Number out[]) const
const Number2 * shape_values
void values(const Number in[], Number out[]) const
const Number2 * shape_gradients
const unsigned int n_rows
void values_one_line(const Number in[], Number out[]) const
void apply(const Number2 *DEAL_II_RESTRICT shape_data, 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 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
static void apply(const Number2 *DEAL_II_RESTRICT shape_data, const Number *in, Number *out)
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
EvaluatorTensorProduct(const Number2 *shape_values, const Number2 *shape_gradients, const Number2 *shape_hessians, const unsigned int dummy1=0, const unsigned int dummy2=0)
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