17 #ifndef dealii_matrix_free_tensor_product_kernels_h 18 #define dealii_matrix_free_tensor_product_kernels_h 20 #include <deal.II/base/config.h> 21 #include <deal.II/base/aligned_vector.h> 22 #include <deal.II/base/utilities.h> 25 DEAL_II_NAMESPACE_OPEN
90 typename Number,
typename Number2=Number>
113 template <
int dim,
int n_rows,
int n_columns,
typename Number,
typename Number2>
116 static constexpr
unsigned int n_rows_of_product =
Utilities::pow(n_rows, dim);
117 static constexpr
unsigned int n_columns_of_product =
Utilities::pow(n_columns, dim);
125 shape_values (nullptr),
126 shape_gradients (nullptr),
127 shape_hessians (nullptr)
136 const unsigned int dummy1 = 0,
137 const unsigned int dummy2 = 0)
139 shape_values (shape_values.begin()),
140 shape_gradients (shape_gradients.begin()),
141 shape_hessians (shape_hessians.begin())
148 shape_values.
size() == n_rows*n_columns ||
149 shape_values.
size() == 3*n_rows,
152 shape_gradients.
size() == n_rows*n_columns,
155 shape_hessians.
size() == n_rows*n_columns,
161 template <
int direction,
bool contract_over_rows,
bool add>
163 values (
const Number in [],
166 apply<direction,contract_over_rows,add>(shape_values, in, out);
169 template <
int direction,
bool contract_over_rows,
bool add>
171 gradients (
const Number in [],
174 apply<direction,contract_over_rows,add>(shape_gradients, in, out);
177 template <
int direction,
bool contract_over_rows,
bool add>
179 hessians (
const Number in [],
182 apply<direction,contract_over_rows,add>(shape_hessians, in, out);
185 template <
int direction,
bool contract_over_rows,
bool add>
187 values_one_line (
const Number in [],
191 apply<direction,contract_over_rows,add,true>(shape_values, in, out);
194 template <
int direction,
bool contract_over_rows,
bool add>
196 gradients_one_line (
const Number in [],
200 apply<direction,contract_over_rows,add,true>(shape_gradients, in, out);
203 template <
int direction,
bool contract_over_rows,
bool add>
205 hessians_one_line (
const Number in [],
209 apply<direction,contract_over_rows,add,true>(shape_hessians, in, out);
236 template <
int direction,
bool contract_over_rows,
bool add,
bool one_line=false>
237 static void apply (
const Number2 *DEAL_II_RESTRICT shape_data,
270 template <
int face_direction,
bool contract_onto_face,
bool add,
int max_derivative>
271 void apply_face (
const Number *DEAL_II_RESTRICT in,
272 Number *DEAL_II_RESTRICT out)
const;
274 const Number2 *shape_values;
275 const Number2 *shape_gradients;
276 const Number2 *shape_hessians;
281 template <
int dim,
int n_rows,
int n_columns,
typename Number,
typename Number2>
282 template <
int direction,
bool contract_over_rows,
bool add,
bool one_line>
286 ::apply (
const Number2 *DEAL_II_RESTRICT shape_data,
290 static_assert (one_line ==
false || direction==dim-1,
291 "Single-line evaluation only works for direction=dim-1.");
292 Assert(shape_data !=
nullptr,
293 ExcMessage(
"The given array shape_data must not be the null pointer!"));
294 Assert (dim == direction+1 || one_line ==
true || n_rows == n_columns || in != out,
295 ExcMessage(
"In-place operation only supported for " 296 "n_rows==n_columns or single-line interpolation"));
298 constexpr
int mm = contract_over_rows ? n_rows : n_columns,
299 nn = contract_over_rows ? n_columns : n_rows;
302 constexpr
int n_blocks1 = one_line ? 1 : stride;
303 constexpr
int n_blocks2 =
Utilities::pow(n_rows, (direction>=dim) ? 0 : (dim-direction-1));
305 for (
int i2=0; i2<n_blocks2; ++i2)
307 for (
int i1=0; i1<n_blocks1; ++i1)
310 for (
int i=0; i<mm; ++i)
312 for (
int col=0; col<nn; ++col)
315 if (contract_over_rows ==
true)
316 val0 = shape_data[col];
318 val0 = shape_data[col*n_columns];
319 Number res0 = val0 * x[0];
320 for (
int i=1; i<mm; ++i)
322 if (contract_over_rows ==
true)
323 val0 = shape_data[i*n_columns+col];
325 val0 = shape_data[col*n_columns+i];
329 out[stride*col] = res0;
331 out[stride*col] += res0;
334 if (one_line ==
false)
340 if (one_line ==
false)
343 out += stride*(nn-1);
350 template <
int dim,
int n_rows,
int n_columns,
typename Number,
typename Number2>
351 template <
int face_direction,
bool contract_onto_face,
bool add,
int max_derivative>
356 Number *DEAL_II_RESTRICT out)
const 358 static_assert(dim > 0 && dim<4,
"Only dim=1,2,3 supported");
359 static_assert(max_derivative >= 0 && max_derivative<3,
360 "Only derivative orders 0-2 implemented");
361 Assert(shape_values !=
nullptr,
362 ExcMessage(
"The given array shape_values must not be the null pointer."));
364 constexpr
int n_blocks1 = dim > 1 ? n_rows : 1;
365 constexpr
int n_blocks2 = dim > 2 ? n_rows : 1;
370 const Number *DEAL_II_RESTRICT shape_values = this->shape_values;
372 for (
int i2=0; i2<n_blocks2; ++i2)
374 for (
int i1=0; i1<n_blocks1; ++i1)
376 if (contract_onto_face ==
true)
378 Number res0 = shape_values[0] * in[0];
380 if (max_derivative > 0)
381 res1 = shape_values[n_rows] * in[0];
382 if (max_derivative > 1)
383 res2 = shape_values[2*n_rows] * in[0];
384 for (
int ind=1; ind<n_rows; ++ind)
386 res0 += shape_values[ind] * in[stride*ind];
387 if (max_derivative > 0)
388 res1 += shape_values[ind+n_rows] * in[stride*ind];
389 if (max_derivative > 1)
390 res2 += shape_values[ind+2*n_rows] * in[stride*ind];
395 if (max_derivative > 0)
396 out[out_stride] = res1;
397 if (max_derivative > 1)
398 out[2*out_stride] = res2;
403 if (max_derivative > 0)
404 out[out_stride] += res1;
405 if (max_derivative > 1)
406 out[2*out_stride] += res2;
411 for (
int col=0; col<n_rows; ++col)
414 out[col*stride] = shape_values[col] * in[0];
416 out[col*stride] += shape_values[col] * in[0];
417 if (max_derivative > 0)
418 out[col*stride] += shape_values[col+n_rows] * in[out_stride];
419 if (max_derivative > 1)
420 out[col*stride] += shape_values[col+2*n_rows] * in[2*out_stride];
427 switch (face_direction)
430 in += contract_onto_face ? n_rows : 1;
431 out += contract_onto_face ? 1 : n_rows;
441 if (contract_onto_face)
455 if (face_direction == 1 && dim == 3)
458 if (contract_onto_face)
460 in += n_rows*(n_rows-1);
461 out -= n_rows*n_rows-1;
465 out += n_rows*(n_rows-1);
466 in -= n_rows*n_rows-1;
487 template <
int dim,
typename Number,
typename Number2>
499 shape_values (nullptr),
500 shape_gradients (nullptr),
501 shape_hessians (nullptr),
502 n_rows (
numbers::invalid_unsigned_int),
503 n_columns (
numbers::invalid_unsigned_int)
512 const unsigned int n_rows,
513 const unsigned int n_columns)
515 shape_values (shape_values.begin()),
516 shape_gradients (shape_gradients.begin()),
517 shape_hessians (shape_hessians.begin()),
519 n_columns (n_columns)
526 shape_values.
size() == n_rows*n_columns ||
527 shape_values.
size() == n_rows*3,
530 shape_gradients.
size() == n_rows*n_columns,
533 shape_hessians.
size() == n_rows*n_columns,
537 template <
int direction,
bool contract_over_rows,
bool add>
539 values (
const Number *in,
542 apply<direction,contract_over_rows,add>(shape_values, in, out);
545 template <
int direction,
bool contract_over_rows,
bool add>
547 gradients (
const Number *in,
550 apply<direction,contract_over_rows,add>(shape_gradients, in, out);
553 template <
int direction,
bool contract_over_rows,
bool add>
555 hessians (
const Number *in,
558 apply<direction,contract_over_rows,add>(shape_hessians, in, out);
561 template <
int direction,
bool contract_over_rows,
bool add>
563 values_one_line (
const Number in [],
567 apply<direction,contract_over_rows,add,true>(shape_values, in, out);
570 template <
int direction,
bool contract_over_rows,
bool add>
572 gradients_one_line (
const Number in [],
576 apply<direction,contract_over_rows,add,true>(shape_gradients, in, out);
579 template <
int direction,
bool contract_over_rows,
bool add>
581 hessians_one_line (
const Number in [],
585 apply<direction,contract_over_rows,add,true>(shape_hessians, in, out);
588 template <
int direction,
bool contract_over_rows,
bool add,
bool one_line=false>
589 void apply (
const Number2 *DEAL_II_RESTRICT shape_data,
593 template <
int face_direction,
bool contract_onto_face,
bool add,
int max_derivative>
594 void apply_face (
const Number *DEAL_II_RESTRICT in,
595 Number *DEAL_II_RESTRICT out)
const;
597 const Number2 *shape_values;
598 const Number2 *shape_gradients;
599 const Number2 *shape_hessians;
600 const unsigned int n_rows;
601 const unsigned int n_columns;
606 template <
int dim,
typename Number,
typename Number2>
607 template <
int direction,
bool contract_over_rows,
bool add,
bool one_line>
610 EvaluatorTensorProduct<evaluate_general,dim,0,0,Number,Number2>
611 ::apply (
const Number2 *DEAL_II_RESTRICT shape_data,
615 static_assert (one_line ==
false || direction==dim-1,
616 "Single-line evaluation only works for direction=dim-1.");
617 Assert(shape_data !=
nullptr,
618 ExcMessage(
"The given array shape_data must not be the null pointer!"));
619 Assert (dim == direction+1 || one_line ==
true || n_rows == n_columns || in != out,
620 ExcMessage(
"In-place operation only supported for " 621 "n_rows==n_columns or single-line interpolation"));
623 const int mm = contract_over_rows ? n_rows : n_columns,
624 nn = contract_over_rows ? n_columns : n_rows;
626 const int stride = direction==0 ? 1 : Utilities::fixed_power<direction>(n_columns);
627 const int n_blocks1 = one_line ? 1 : stride;
631 for (
int i2=0; i2<n_blocks2; ++i2)
633 for (
int i1=0; i1<n_blocks1; ++i1)
636 for (
int i=0; i<mm; ++i)
638 for (
int col=0; col<nn; ++col)
641 if (contract_over_rows ==
true)
642 val0 = shape_data[col];
644 val0 = shape_data[col*n_columns];
645 Number res0 = val0 * x[0];
646 for (
int i=1; i<mm; ++i)
648 if (contract_over_rows ==
true)
649 val0 = shape_data[i*n_columns+col];
651 val0 = shape_data[col*n_columns+i];
655 out[stride*col] = res0;
657 out[stride*col] += res0;
660 if (one_line ==
false)
666 if (one_line ==
false)
669 out += stride*(nn-1);
676 template <
int dim,
typename Number,
typename Number2>
677 template <
int face_direction,
bool contract_onto_face,
bool add,
int max_derivative>
680 EvaluatorTensorProduct<evaluate_general,dim,0,0,Number,Number2>
681 ::apply_face (
const Number *DEAL_II_RESTRICT in,
682 Number *DEAL_II_RESTRICT out)
const 684 Assert(shape_values !=
nullptr,
685 ExcMessage(
"The given array shape_data must not be the null pointer!"));
686 static_assert(dim > 0 && dim<4,
"Only dim=1,2,3 supported");
687 const int n_blocks1 = dim > 1 ? n_rows : 1;
688 const int n_blocks2 = dim > 2 ? n_rows : 1;
691 const int stride = face_direction > 0 ? Utilities::fixed_power<face_direction>(n_rows) : 1;
694 for (
int i2=0; i2<n_blocks2; ++i2)
696 for (
int i1=0; i1<n_blocks1; ++i1)
698 if (contract_onto_face ==
true)
700 Number res0 = shape_values[0] * in[0];
702 if (max_derivative > 0)
703 res1 = shape_values[n_rows] * in[0];
704 if (max_derivative > 1)
705 res2 = shape_values[2*n_rows] * in[0];
706 for (
unsigned int ind=1; ind<n_rows; ++ind)
708 res0 += shape_values[ind] * in[stride*ind];
709 if (max_derivative > 0)
710 res1 += shape_values[ind+n_rows] * in[stride*ind];
711 if (max_derivative > 1)
712 res2 += shape_values[ind+2*n_rows] * in[stride*ind];
717 if (max_derivative > 0)
718 out[out_stride] = res1;
719 if (max_derivative > 1)
720 out[2*out_stride] = res2;
725 if (max_derivative > 0)
726 out[out_stride] += res1;
727 if (max_derivative > 1)
728 out[2*out_stride] += res2;
733 for (
unsigned int col=0; col<n_rows; ++col)
736 out[col*stride] = shape_values[col] * in[0];
738 out[col*stride] += shape_values[col] * in[0];
739 if (max_derivative > 0)
740 out[col*stride] += shape_values[col+n_rows] * in[out_stride];
741 if (max_derivative > 1)
742 out[col*stride] += shape_values[col+2*n_rows] * in[2*out_stride];
749 switch (face_direction)
752 in += contract_onto_face ? n_rows : 1;
753 out += contract_onto_face ? 1 : n_rows;
763 if (contract_onto_face)
777 if (face_direction == 1 && dim == 3)
780 if (contract_onto_face)
782 in += n_rows*(n_rows-1);
783 out -= n_rows*n_rows-1;
787 out += n_rows*(n_rows-1);
788 in -= n_rows*n_rows-1;
816 template <
int dim,
int n_rows,
int n_columns,
typename Number,
typename Number2>
819 static constexpr
unsigned int n_rows_of_product =
Utilities::pow(n_rows, dim);
820 static constexpr
unsigned int n_columns_of_product =
Utilities::pow(n_columns, dim);
828 const unsigned int dummy1 = 0,
829 const unsigned int dummy2 = 0)
831 shape_values (shape_values.begin()),
832 shape_gradients (shape_gradients.begin()),
833 shape_hessians (shape_hessians.begin())
836 shape_values.
size() == n_rows*n_columns,
839 shape_gradients.
size() == n_rows*n_columns,
842 shape_hessians.
size() == n_rows*n_columns,
848 template <
int direction,
bool contract_over_rows,
bool add>
850 values (
const Number in [],
853 template <
int direction,
bool contract_over_rows,
bool add>
855 gradients (
const Number in [],
858 template <
int direction,
bool contract_over_rows,
bool add>
860 hessians (
const Number in [],
863 const Number2 *shape_values;
864 const Number2 *shape_gradients;
865 const Number2 *shape_hessians;
888 template <
int dim,
int n_rows,
int n_columns,
typename Number,
typename Number2>
889 template <
int direction,
bool contract_over_rows,
bool add>
892 EvaluatorTensorProduct<evaluate_symmetric,dim,n_rows,n_columns,Number,Number2>
893 ::values (
const Number in [],
898 constexpr
int mm = contract_over_rows ? n_rows : n_columns,
899 nn = contract_over_rows ? n_columns : n_rows;
900 constexpr
int n_cols = nn / 2;
901 constexpr
int mid = mm / 2;
904 constexpr
int n_blocks1 = stride;
905 constexpr
int n_blocks2 =
Utilities::pow(n_rows, (direction>=dim) ? 0 : (dim-direction-1));
907 for (
int i2=0; i2<n_blocks2; ++i2)
909 for (
int i1=0; i1<n_blocks1; ++i1)
911 for (
int col=0; col<n_cols; ++col)
914 Number in0, in1, res0, res1;
915 if (contract_over_rows ==
true)
917 val0 = shape_values[col];
918 val1 = shape_values[nn-1-col];
922 val0 = shape_values[col*n_columns];
923 val1 = shape_values[(col+1)*n_columns-1];
928 in1 = in[stride*(mm-1)];
933 for (
int ind=1; ind<mid; ++ind)
935 if (contract_over_rows ==
true)
937 val0 = shape_values[ind*n_columns+col];
938 val1 = shape_values[ind*n_columns+nn-1-col];
942 val0 = shape_values[col*n_columns+ind];
943 val1 = shape_values[(col+1)*n_columns-1-ind];
945 in0 = in[stride*ind];
946 in1 = in[stride*(mm-1-ind)];
954 res0 = res1 = Number();
955 if (contract_over_rows ==
true)
959 val0 = shape_values[mid*n_columns+col];
960 in1 = val0 * in[stride*mid];
967 if (mm % 2 == 1 && nn % 2 == 0)
969 val0 = shape_values[col*n_columns+mid];
970 in1 = val0 * in[stride*mid];
977 out[stride*col] = res0;
978 out[stride*(nn-1-col)] = res1;
982 out[stride*col] += res0;
983 out[stride*(nn-1-col)] += res1;
986 if ( contract_over_rows ==
true && nn%2==1 && mm%2==1 )
989 out[stride*n_cols] = in[stride*mid];
991 out[stride*n_cols] += in[stride*mid];
993 else if (contract_over_rows ==
true && nn%2==1)
996 Number2 val0 = shape_values[n_cols];
999 res0 = val0 * (in[0] + in[stride*(mm-1)]);
1000 for (
int ind=1; ind<mid; ++ind)
1002 val0 = shape_values[ind*n_columns+n_cols];
1003 res0 += val0 * (in[stride*ind] + in[stride*(mm-1-ind)]);
1009 out[stride*n_cols] = res0;
1011 out[stride*n_cols] += res0;
1013 else if (contract_over_rows ==
false && nn%2 == 1)
1018 Number2 val0 = shape_values[n_cols*n_columns];
1019 res0 = val0 * (in[0] + in[stride*(mm-1)]);
1020 for (
int ind=1; ind<mid; ++ind)
1022 val0 = shape_values[n_cols*n_columns+ind];
1023 Number in1 = val0 * (in[stride*ind] + in[stride*(mm-1-ind)]);
1027 res0 += in[stride*mid];
1032 out[stride*n_cols] = res0;
1034 out[stride*n_cols] += res0;
1040 in += stride*(mm-1);
1041 out += stride*(nn-1);
1066 template <
int dim,
int n_rows,
int n_columns,
typename Number,
typename Number2>
1067 template <
int direction,
bool contract_over_rows,
bool add>
1070 EvaluatorTensorProduct<evaluate_symmetric,dim,n_rows,n_columns,Number,Number2>
1071 ::gradients (
const Number in [],
1072 Number out [])
const 1076 constexpr
int mm = contract_over_rows ? n_rows : n_columns,
1077 nn = contract_over_rows ? n_columns : n_rows;
1078 constexpr
int n_cols = nn / 2;
1079 constexpr
int mid = mm / 2;
1082 constexpr
int n_blocks1 = stride;
1083 constexpr
int n_blocks2 =
Utilities::pow(n_rows, (direction>=dim) ? 0 : (dim-direction-1));
1085 for (
int i2=0; i2<n_blocks2; ++i2)
1087 for (
int i1=0; i1<n_blocks1; ++i1)
1089 for (
int col=0; col<n_cols; ++col)
1092 Number in0, in1, res0, res1;
1093 if (contract_over_rows ==
true)
1095 val0 = shape_gradients[col];
1096 val1 = shape_gradients[nn-1-col];
1100 val0 = shape_gradients[col*n_columns];
1101 val1 = shape_gradients[(nn-col-1)*n_columns];
1106 in1 = in[stride*(mm-1)];
1111 for (
int ind=1; ind<mid; ++ind)
1113 if (contract_over_rows ==
true)
1115 val0 = shape_gradients[ind*n_columns+col];
1116 val1 = shape_gradients[ind*n_columns+nn-1-col];
1120 val0 = shape_gradients[col*n_columns+ind];
1121 val1 = shape_gradients[(nn-col-1)*n_columns+ind];
1123 in0 = in[stride*ind];
1124 in1 = in[stride*(mm-1-ind)];
1132 res0 = res1 = Number();
1135 if (contract_over_rows ==
true)
1136 val0 = shape_gradients[mid*n_columns+col];
1138 val0 = shape_gradients[col*n_columns+mid];
1139 in1 = val0 * in[stride*mid];
1145 out[stride*col] = res0;
1146 out[stride*(nn-1-col)] = res1;
1150 out[stride*col] += res0;
1151 out[stride*(nn-1-col)] += res1;
1158 if (contract_over_rows ==
true)
1159 val0 = shape_gradients[n_cols];
1161 val0 = shape_gradients[n_cols*n_columns];
1162 res0 = val0 * (in[0] - in[stride*(mm-1)]);
1163 for (
int ind=1; ind<mid; ++ind)
1165 if (contract_over_rows ==
true)
1166 val0 = shape_gradients[ind*n_columns+n_cols];
1168 val0 = shape_gradients[n_cols*n_columns+ind];
1169 Number in1 = val0 * (in[stride*ind] - in[stride*(mm-1-ind)]);
1173 out[stride*n_cols] = res0;
1175 out[stride*n_cols] += res0;
1181 in += stride*(mm-1);
1182 out += stride*(nn-1);
1191 template <
int dim,
int n_rows,
int n_columns,
typename Number,
typename Number2>
1192 template <
int direction,
bool contract_over_rows,
bool add>
1195 EvaluatorTensorProduct<evaluate_symmetric,dim,n_rows,n_columns,Number,Number2>
1196 ::hessians (
const Number in [],
1197 Number out [])
const 1201 constexpr
int mm = contract_over_rows ? n_rows : n_columns;
1202 constexpr
int nn = contract_over_rows ? n_columns : n_rows;
1203 constexpr
int n_cols = nn / 2;
1204 constexpr
int mid = mm / 2;
1207 constexpr
int n_blocks1 = stride;
1208 constexpr
int n_blocks2 =
Utilities::pow(n_rows, (direction>=dim) ? 0 : (dim-direction-1));
1210 for (
int i2=0; i2<n_blocks2; ++i2)
1212 for (
int i1=0; i1<n_blocks1; ++i1)
1214 for (
int col=0; col<n_cols; ++col)
1217 Number in0, in1, res0, res1;
1218 if (contract_over_rows ==
true)
1220 val0 = shape_hessians[col];
1221 val1 = shape_hessians[nn-1-col];
1225 val0 = shape_hessians[col*n_columns];
1226 val1 = shape_hessians[(col+1)*n_columns-1];
1231 in1 = in[stride*(mm-1)];
1236 for (
int ind=1; ind<mid; ++ind)
1238 if (contract_over_rows ==
true)
1240 val0 = shape_hessians[ind*n_columns+col];
1241 val1 = shape_hessians[ind*n_columns+nn-1-col];
1245 val0 = shape_hessians[col*n_columns+ind];
1246 val1 = shape_hessians[(col+1)*n_columns-1-ind];
1248 in0 = in[stride*ind];
1249 in1 = in[stride*(mm-1-ind)];
1257 res0 = res1 = Number();
1260 if (contract_over_rows ==
true)
1261 val0 = shape_hessians[mid*n_columns+col];
1263 val0 = shape_hessians[col*n_columns+mid];
1264 in1 = val0 * in[stride*mid];
1270 out[stride*col] = res0;
1271 out[stride*(nn-1-col)] = res1;
1275 out[stride*col] += res0;
1276 out[stride*(nn-1-col)] += res1;
1283 if (contract_over_rows ==
true)
1284 val0 = shape_hessians[n_cols];
1286 val0 = shape_hessians[n_cols*n_columns];
1289 res0 = val0 * (in[0] + in[stride*(mm-1)]);
1290 for (
int ind=1; ind<mid; ++ind)
1292 if (contract_over_rows ==
true)
1293 val0 = shape_hessians[ind*n_columns+n_cols];
1295 val0 = shape_hessians[n_cols*n_columns+ind];
1296 Number in1 = val0*(in[stride*ind] + in[stride*(mm-1-ind)]);
1304 if (contract_over_rows ==
true)
1305 val0 = shape_hessians[mid*n_columns+n_cols];
1307 val0 = shape_hessians[n_cols*n_columns+mid];
1308 res0 += val0 * in[stride*mid];
1311 out[stride*n_cols] = res0;
1313 out[stride*n_cols] += res0;
1319 in += stride*(mm-1);
1320 out += stride*(nn-1);
1357 template <
int dim,
int n_rows,
int n_columns,
typename Number,
typename Number2>
1360 static constexpr
unsigned int n_rows_of_product =
Utilities::pow(n_rows, dim);
1361 static constexpr
unsigned int n_columns_of_product =
Utilities::pow(n_columns, dim);
1370 shape_values (nullptr),
1371 shape_gradients (nullptr),
1372 shape_hessians (nullptr)
1381 shape_values (shape_values.begin()),
1382 shape_gradients (nullptr),
1383 shape_hessians (nullptr)
1395 const unsigned int dummy1 = 0,
1396 const unsigned int dummy2 = 0)
1398 shape_values (shape_values.begin()),
1399 shape_gradients (shape_gradients.begin()),
1400 shape_hessians (shape_hessians.begin())
1404 if (!shape_values.
empty())
1406 if (!shape_gradients.
empty())
1408 if (!shape_hessians.
empty())
1414 template <
int direction,
bool contract_over_rows,
bool add>
1416 values (
const Number in [],
1420 apply<direction,contract_over_rows,add,0>(shape_values, in, out);
1423 template <
int direction,
bool contract_over_rows,
bool add>
1425 gradients (
const Number in [],
1429 apply<direction,contract_over_rows,add,1>(shape_gradients, in, out);
1432 template <
int direction,
bool contract_over_rows,
bool add>
1434 hessians (
const Number in [],
1438 apply<direction,contract_over_rows,add,2>(shape_hessians, in, out);
1441 template <
int direction,
bool contract_over_rows,
bool add>
1443 values_one_line (
const Number in [],
1447 apply<direction,contract_over_rows,add,0,true>(shape_values, in, out);
1450 template <
int direction,
bool contract_over_rows,
bool add>
1452 gradients_one_line (
const Number in [],
1456 apply<direction,contract_over_rows,add,1,true>(shape_gradients, in, out);
1459 template <
int direction,
bool contract_over_rows,
bool add>
1461 hessians_one_line (
const Number in [],
1465 apply<direction,contract_over_rows,add,2,true>(shape_hessians, in, out);
1496 template <
int direction,
bool contract_over_rows,
bool add,
int type,
1497 bool one_line=
false>
1498 static void apply (
const Number2 *DEAL_II_RESTRICT shape_data,
1502 const Number2 *shape_values;
1503 const Number2 *shape_gradients;
1504 const Number2 *shape_hessians;
1509 template <
int dim,
int n_rows,
int n_columns,
typename Number,
typename Number2>
1510 template <
int direction,
bool contract_over_rows,
bool add,
int type,
bool one_line>
1518 static_assert (type < 3,
"Only three variants type=0,1,2 implemented");
1519 static_assert (one_line ==
false || direction==dim-1,
1520 "Single-line evaluation only works for direction=dim-1.");
1521 Assert (dim == direction+1 || one_line ==
true || n_rows == n_columns || in != out,
1522 ExcMessage(
"In-place operation only supported for " 1523 "n_rows==n_columns or single-line interpolation"));
1529 constexpr
int nn = contract_over_rows ? n_columns : n_rows;
1530 constexpr
int mm = contract_over_rows ? n_rows : n_columns;
1531 constexpr
int n_cols = nn / 2;
1532 constexpr
int mid = mm / 2;
1535 constexpr
int n_blocks1 = one_line ? 1 : stride;
1536 constexpr
int n_blocks2 =
Utilities::pow(n_rows, (direction>=dim) ? 0 : (dim-direction-1));
1538 constexpr
int offset = (n_columns+1)/2;
1544 for (
int i2=0; i2<n_blocks2; ++i2)
1546 for (
int i1=0; i1<n_blocks1; ++i1)
1548 Number xp[mid>0?mid:1], xm[mid>0?mid:1];
1549 for (
int i=0; i<mid; ++i)
1551 if (contract_over_rows ==
true && type == 1)
1553 xp[i] = in[stride*i] - in[stride*(mm-1-i)];
1554 xm[i] = in[stride*i] + in[stride*(mm-1-i)];
1558 xp[i] = in[stride*i] + in[stride*(mm-1-i)];
1559 xm[i] = in[stride*i] - in[stride*(mm-1-i)];
1562 Number xmid = in[stride*mid];
1563 for (
int col=0; col<n_cols; ++col)
1568 if (contract_over_rows ==
true)
1570 r0 = shapes[col] * xp[0];
1571 r1 = shapes[(n_rows-1)*offset + col] * xm[0];
1575 r0 = shapes[col*offset] * xp[0];
1576 r1 = shapes[(n_rows-1-col)*offset] * xm[0];
1578 for (
int ind=1; ind<mid; ++ind)
1580 if (contract_over_rows ==
true)
1582 r0 += shapes[ind*offset+col] * xp[ind];
1583 r1 += shapes[(n_rows-1-ind)*offset+col] * xm[ind];
1587 r0 += shapes[col*offset+ind] * xp[ind];
1588 r1 += shapes[(n_rows-1-col)*offset+ind] * xm[ind];
1594 if (mm % 2 == 1 && contract_over_rows ==
true)
1597 r1 += shapes[mid*offset+col] * xmid;
1599 r0 += shapes[mid*offset+col] * xmid;
1601 else if (mm % 2 == 1 && (nn % 2 == 0 || type > 0))
1602 r0 += shapes[col*offset+mid] * xmid;
1606 out[stride*col] = r0 + r1;
1607 if (type == 1 && contract_over_rows ==
false)
1608 out[stride*(nn-1-col)] = r1 - r0;
1610 out[stride*(nn-1-col)] = r0 - r1;
1614 out[stride*col] += r0 + r1;
1615 if (type == 1 && contract_over_rows ==
false)
1616 out[stride*(nn-1-col)] += r1 - r0;
1618 out[stride*(nn-1-col)] += r0 - r1;
1621 if ( type == 0 && contract_over_rows ==
true && nn%2==1 && mm%2==1 )
1624 out[stride*n_cols] = shapes[mid*offset+n_cols] * xmid;
1626 out[stride*n_cols] += shapes[mid*offset+n_cols] * xmid;
1628 else if (contract_over_rows ==
true && nn%2==1)
1633 r0 = shapes[n_cols] * xp[0];
1634 for (
int ind=1; ind<mid; ++ind)
1635 r0 += shapes[ind*offset+n_cols] * xp[ind];
1639 if (type != 1 && mm % 2 == 1)
1640 r0 += shapes[mid*offset+n_cols] * xmid;
1643 out[stride*n_cols] = r0;
1645 out[stride*n_cols] += r0;
1647 else if (contract_over_rows ==
false && nn%2 == 1)
1654 r0 = shapes[n_cols*offset] * xm[0];
1655 for (
int ind=1; ind<mid; ++ind)
1656 r0 += shapes[n_cols*offset+ind] * xm[ind];
1660 r0 = shapes[n_cols*offset] * xp[0];
1661 for (
int ind=1; ind<mid; ++ind)
1662 r0 += shapes[n_cols*offset+ind] * xp[ind];
1668 if ((type == 0 || type == 2) && mm % 2 == 1)
1669 r0 += shapes[n_cols*offset+mid] * xmid;
1672 out[stride*n_cols] = r0;
1674 out[stride*n_cols] += r0;
1676 if (one_line ==
false)
1682 if (one_line ==
false)
1684 in += stride * (mm-1);
1685 out += stride * (nn-1);
1720 template <
int dim,
int n_rows,
int n_columns,
typename Number,
typename Number2>
1723 static constexpr
unsigned int n_rows_of_product =
Utilities::pow(n_rows, dim);
1724 static constexpr
unsigned int n_columns_of_product =
Utilities::pow(n_columns, dim);
1733 shape_values (nullptr),
1734 shape_gradients (nullptr),
1735 shape_hessians (nullptr)
1744 shape_values (shape_values.begin()),
1745 shape_gradients (nullptr),
1746 shape_hessians (nullptr)
1756 const unsigned int dummy1 = 0,
1757 const unsigned int dummy2 = 0)
1759 shape_values (shape_values.begin()),
1760 shape_gradients (shape_gradients.begin()),
1761 shape_hessians (shape_hessians.begin())
1767 template <
int direction,
bool contract_over_rows,
bool add>
1769 values (
const Number in [],
1773 apply<direction,contract_over_rows,add,0>(shape_values, in, out);
1776 template <
int direction,
bool contract_over_rows,
bool add>
1778 gradients (
const Number in [],
1782 apply<direction,contract_over_rows,add,1>(shape_gradients, in, out);
1785 template <
int direction,
bool contract_over_rows,
bool add>
1787 hessians (
const Number in [],
1791 apply<direction,contract_over_rows,add,0>(shape_hessians, in, out);
1794 template <
int direction,
bool contract_over_rows,
bool add>
1796 values_one_line (
const Number in [],
1800 apply<direction,contract_over_rows,add,0,true>(shape_values, in, out);
1803 template <
int direction,
bool contract_over_rows,
bool add>
1805 gradients_one_line (
const Number in [],
1809 apply<direction,contract_over_rows,add,1,true>(shape_gradients, in, out);
1812 template <
int direction,
bool contract_over_rows,
bool add>
1814 hessians_one_line (
const Number in [],
1818 apply<direction,contract_over_rows,add,0,true>(shape_hessians, in, out);
1848 template <
int direction,
bool contract_over_rows,
bool add,
int type,
1849 bool one_line=
false>
1850 static void apply (
const Number2 *DEAL_II_RESTRICT shape_data,
1854 const Number2 *shape_values;
1855 const Number2 *shape_gradients;
1856 const Number2 *shape_hessians;
1861 template <
int dim,
int n_rows,
int n_columns,
typename Number,
typename Number2>
1862 template <
int direction,
bool contract_over_rows,
bool add,
int type,
bool one_line>
1870 static_assert (one_line ==
false || direction==dim-1,
1871 "Single-line evaluation only works for direction=dim-1.");
1872 static_assert (type == 0 || type == 1,
1873 "Only types 0 and 1 implemented for evaluate_symmetric_hierarchical.");
1874 Assert (dim == direction+1 || one_line ==
true || n_rows == n_columns || in != out,
1875 ExcMessage(
"In-place operation only supported for " 1876 "n_rows==n_columns or single-line interpolation"));
1882 constexpr
int nn = contract_over_rows ? n_columns : n_rows;
1883 constexpr
int mm = contract_over_rows ? n_rows : n_columns;
1884 constexpr
int n_cols = nn / 2;
1885 constexpr
int mid = mm / 2;
1888 constexpr
int n_blocks1 = one_line ? 1 : stride;
1889 constexpr
int n_blocks2 =
Utilities::pow(n_rows, (direction>=dim) ? 0 : (dim-direction-1));
1895 for (
int i2=0; i2<n_blocks2; ++i2)
1897 for (
int i1=0; i1<n_blocks1; ++i1)
1899 if (contract_over_rows)
1902 for (
unsigned int i=0; i<mm; ++i)
1903 x[i] = in[stride*i];
1904 for (
unsigned int col=0; col<n_cols; ++col)
1909 r0 = shapes[col] * x[0];
1910 r1 = shapes[col+n_columns] * x[1];
1911 for (
unsigned int ind=1; ind<mid; ++ind)
1913 r0 += shapes[col+2*ind*n_columns] * x[2*ind];
1914 r1 += shapes[col+(2*ind+1)*n_columns] * x[2*ind+1];
1920 r0 += shapes[col+(mm-1)*n_columns] * x[mm-1];
1923 out[stride*col] = r0 + r1;
1925 out[stride*(nn-1-col)] = r1 - r0;
1927 out[stride*(nn-1-col)] = r0 - r1;
1931 out[stride*col] += r0 + r1;
1933 out[stride*(nn-1-col)] += r1 - r0;
1935 out[stride*(nn-1-col)] += r0 - r1;
1941 const unsigned int shift = type==1 ? 1 : 0;
1944 r0 = shapes[n_cols + shift*n_columns] * x[shift];
1945 for (
unsigned int ind=1; ind<mid; ++ind)
1946 r0 += shapes[n_cols + (2*ind+shift)*n_columns] * x[2*ind+shift];
1950 if (type != 1 && mm%2 == 1)
1951 r0 += shapes[n_cols + (mm-1)*n_columns] * x[mm-1];
1953 out[stride*n_cols] = r0;
1955 out[stride*n_cols] += r0;
1960 Number xp[mid+1], xm[mid>0?mid:1];
1961 for (
int i=0; i<mid; ++i)
1964 xp[i] = in[stride*i] + in[stride*(mm-1-i)];
1965 xm[i] = in[stride*i] - in[stride*(mm-1-i)];
1969 xp[i] = in[stride*i] - in[stride*(mm-1-i)];
1970 xm[i] = in[stride*i] + in[stride*(mm-1-i)];
1973 xp[mid] = in[stride*mid];
1974 for (
unsigned int col=0; col<n_cols; ++col)
1979 r0 = shapes[2*col*n_columns] * xp[0];
1980 r1 = shapes[(2*col+1)*n_columns] * xm[0];
1981 for (
unsigned int ind=1; ind<mid; ++ind)
1983 r0 += shapes[2*col*n_columns+ind] * xp[ind];
1984 r1 += shapes[(2*col+1)*n_columns+ind] * xm[ind];
1992 r1 += shapes[(2*col+1)*n_columns+mid] * xp[mid];
1994 r0 += shapes[2*col*n_columns+mid] * xp[mid];
1998 out[stride*(2*col)] = r0;
1999 out[stride*(2*col+1)] = r1;
2003 out[stride*(2*col)] += r0;
2004 out[stride*(2*col+1)] += r1;
2012 r0 = shapes[(nn-1)*n_columns] * xp[0];
2013 for (
unsigned int ind=1; ind<mid; ++ind)
2014 r0 += shapes[(nn-1)*n_columns+ind] * xp[ind];
2018 if (mm%2 == 1 && type == 0)
2019 r0 += shapes[(nn-1)*n_columns+mid] * xp[mid];
2021 out[stride*(nn-1)] = r0;
2023 out[stride*(nn-1)] += r0;
2026 if (one_line ==
false)
2032 if (one_line ==
false)
2034 in += stride * (mm-1);
2035 out += stride * (nn-1);
2043 DEAL_II_NAMESPACE_CLOSE
static const unsigned int invalid_unsigned_int
#define AssertDimension(dim1, dim2)
constexpr unsigned int pow(const unsigned int base, const unsigned int iexp)
EvaluatorTensorProduct(const AlignedVector< Number2 > &shape_values, const AlignedVector< Number2 > &shape_gradients, const AlignedVector< Number2 > &shape_hessians, const unsigned int dummy1=0, const unsigned int dummy2=0)
#define AssertIndexRange(index, range)
static void apply(const Number2 *DEAL_II_RESTRICT shape_data, const Number *in, Number *out)
static ::ExceptionBase & ExcNotInitialized()
EvaluatorTensorProduct(const AlignedVector< Number > &shape_values)
static ::ExceptionBase & ExcMessage(std::string arg1)
EvaluatorTensorProduct(const AlignedVector< Number2 > &shape_values, const AlignedVector< Number2 > &shape_gradients, const AlignedVector< Number2 > &shape_hessians, const unsigned int dummy1=0, const unsigned int dummy2=0)
#define Assert(cond, exc)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
EvaluatorTensorProduct(const AlignedVector< Number2 > &shape_values, const AlignedVector< Number2 > &shape_gradients, const AlignedVector< Number2 > &shape_hessians, const unsigned int n_rows, const unsigned int n_columns)
EvaluatorTensorProduct(const AlignedVector< Number2 > &shape_values, const AlignedVector< Number2 > &shape_gradients, const AlignedVector< Number2 > &shape_hessians, const unsigned int dummy1=0, const unsigned int dummy2=0)
EvaluatorTensorProduct(const AlignedVector< Number2 > &shape_values)
EvaluatorTensorProduct(const AlignedVector< Number2 > &shape_values, const AlignedVector< Number2 > &shape_gradients, const AlignedVector< Number2 > &shape_hessians, const unsigned int dummy1=0, const unsigned int dummy2=0)
static void apply(const Number2 *DEAL_II_RESTRICT shape_data, const Number *in, Number *out)
static ::ExceptionBase & ExcNotImplemented()
static void apply(const Number2 *DEAL_II_RESTRICT shape_data, const Number *in, Number *out)