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
59 template <
EvaluatorVariant variant,
int dim,
int fe_degree,
int n_q_points_1d,
68 template <
int dim,
int fe_degree,
int n_q_po
ints_1d,
typename Number>
91 const unsigned int dummy1 = 0,
92 const unsigned int dummy2 = 0)
94 shape_values (shape_values.begin()),
95 shape_gradients (shape_gradients.begin()),
96 shape_hessians (shape_hessians.begin())
102 template <
int direction,
bool dof_to_quad,
bool add>
104 values (
const Number in [],
107 apply<direction,dof_to_quad,add>(shape_values, in, out);
110 template <
int direction,
bool dof_to_quad,
bool add>
112 gradients (
const Number in [],
115 apply<direction,dof_to_quad,add>(shape_gradients, in, out);
118 template <
int direction,
bool dof_to_quad,
bool add>
120 hessians (
const Number in [],
123 apply<direction,dof_to_quad,add>(shape_hessians, in, out);
126 template <
int direction,
bool dof_to_quad,
bool add>
127 static void apply (
const Number *shape_data,
131 const Number *shape_values;
132 const Number *shape_gradients;
133 const Number *shape_hessians;
140 template <
int dim,
int fe_degree,
int n_q_po
ints_1d,
typename Number>
141 template <
int direction,
bool dof_to_quad,
bool add>
144 EvaluatorTensorProduct<evaluate_general,dim,fe_degree,n_q_points_1d,Number>
145 ::apply (
const Number *shape_data,
150 const int mm = dof_to_quad ? (fe_degree+1) : n_q_points_1d,
151 nn = dof_to_quad ? n_q_points_1d : (fe_degree+1);
153 const int n_blocks1 = (dim > 1 ? (direction > 0 ? nn : mm) : 1);
154 const int n_blocks2 = (dim > 2 ? (direction > 1 ? nn : mm) : 1);
157 for (
int i2=0; i2<n_blocks2; ++i2)
159 for (
int i1=0; i1<n_blocks1; ++i1)
161 for (
int col=0; col<nn; ++col)
164 if (dof_to_quad ==
true)
165 val0 = shape_data[col];
167 val0 = shape_data[col*n_q_points_1d];
168 Number res0 = val0 * in[0];
169 for (
int ind=1; ind<mm; ++ind)
171 if (dof_to_quad ==
true)
172 val0 = shape_data[ind*n_q_points_1d+col];
174 val0 = shape_data[col*n_q_points_1d+ind];
175 res0 += val0 * in[stride*ind];
178 out[stride*col] = res0;
180 out[stride*col] += res0;
216 template <
int dim,
int fe_degree,
typename Number,
int face_direction,
217 bool dof_to_quad,
bool add>
220 apply_tensor_product_face (
const Number *shape_data,
224 const int n_blocks1 = dim > 1 ? (fe_degree+1) : 1;
225 const int n_blocks2 = dim > 2 ? (fe_degree+1) : 1;
228 const int mm = dof_to_quad ? (fe_degree+1) : 1,
229 nn = dof_to_quad ? 1 : (fe_degree+1);
233 for (
int i2=0; i2<n_blocks2; ++i2)
235 for (
int i1=0; i1<n_blocks1; ++i1)
237 if (dof_to_quad ==
true)
239 Number res0 = shape_data[0] * in[0];
240 for (
int ind=1; ind<mm; ++ind)
241 res0 += shape_data[ind] * in[stride*ind];
249 for (
int col=0; col<nn; ++col)
251 out[col*stride] = shape_data[col] * in[0];
253 out[col*stride] += shape_data[col] * in[0];
259 switch (face_direction)
287 if (face_direction == 1 && dim == 3)
293 out -= (fe_degree+1)*(fe_degree+1)-1;
295 in -= (fe_degree+1)*(fe_degree+1)-1;
307 template <
int dim,
typename Number>
322 fe_degree (
numbers::invalid_unsigned_int),
323 n_q_points_1d (
numbers::invalid_unsigned_int)
332 const unsigned int fe_degree,
333 const unsigned int n_q_points_1d)
335 shape_values (shape_values.begin()),
336 shape_gradients (shape_gradients.begin()),
337 shape_hessians (shape_hessians.begin()),
338 fe_degree (fe_degree),
339 n_q_points_1d (n_q_points_1d)
342 template <
int direction,
bool dof_to_quad,
bool add>
344 values (
const Number *in,
347 apply<direction,dof_to_quad,add>(shape_values, in, out);
350 template <
int direction,
bool dof_to_quad,
bool add>
352 gradients (
const Number *in,
355 apply<direction,dof_to_quad,add>(shape_gradients, in, out);
358 template <
int direction,
bool dof_to_quad,
bool add>
360 hessians (
const Number *in,
363 apply<direction,dof_to_quad,add>(shape_hessians, in, out);
366 template <
int direction,
bool dof_to_quad,
bool add>
367 void apply (
const Number *shape_data,
371 const Number *shape_values;
372 const Number *shape_gradients;
373 const Number *shape_hessians;
374 const unsigned int fe_degree;
375 const unsigned int n_q_points_1d;
382 template <
int dim,
typename Number>
383 template <
int direction,
bool dof_to_quad,
bool add>
386 EvaluatorTensorProduct<evaluate_general,dim,-1,0,Number>
387 ::apply (
const Number *shape_data,
392 const int mm = dof_to_quad ? (fe_degree+1) : n_q_points_1d,
393 nn = dof_to_quad ? n_q_points_1d : (fe_degree+1);
395 const int n_blocks1 = (dim > 1 ? (direction > 0 ? nn : mm) : 1);
396 const int n_blocks2 = (dim > 2 ? (direction > 1 ? nn : mm) : 1);
397 const int stride = direction==0 ? 1 : Utilities::fixed_power<direction>(nn);
399 for (
int i2=0; i2<n_blocks2; ++i2)
401 for (
int i1=0; i1<n_blocks1; ++i1)
403 for (
int col=0; col<nn; ++col)
406 if (dof_to_quad ==
true)
407 val0 = shape_data[col];
409 val0 = shape_data[col*n_q_points_1d];
410 Number res0 = val0 * in[0];
411 for (
int ind=1; ind<mm; ++ind)
413 if (dof_to_quad ==
true)
414 val0 = shape_data[ind*n_q_points_1d+col];
416 val0 = shape_data[col*n_q_points_1d+ind];
417 res0 += val0 * in[stride*ind];
420 out[stride*col] = res0;
422 out[stride*col] += res0;
460 template <
int dim,
int fe_degree,
int n_q_po
ints_1d,
typename Number>
472 const unsigned int dummy1 = 0,
473 const unsigned int dummy2 = 0)
475 shape_values (shape_values.begin()),
476 shape_gradients (shape_gradients.begin()),
477 shape_hessians (shape_hessians.begin())
483 template <
int direction,
bool dof_to_quad,
bool add>
485 values (
const Number in [],
488 template <
int direction,
bool dof_to_quad,
bool add>
490 gradients (
const Number in [],
493 template <
int direction,
bool dof_to_quad,
bool add>
495 hessians (
const Number in [],
498 const Number *shape_values;
499 const Number *shape_gradients;
500 const Number *shape_hessians;
523 template <
int dim,
int fe_degree,
int n_q_po
ints_1d,
typename Number>
524 template <
int direction,
bool dof_to_quad,
bool add>
527 EvaluatorTensorProduct<evaluate_symmetric,dim,fe_degree,n_q_points_1d,Number>
528 ::values (
const Number in [],
532 const int mm = dof_to_quad ? (fe_degree+1) : n_q_points_1d,
533 nn = dof_to_quad ? n_q_points_1d : (fe_degree+1);
534 const int n_cols = nn / 2;
535 const int mid = mm / 2;
537 const int n_blocks1 = (dim > 1 ? (direction > 0 ? nn : mm) : 1);
538 const int n_blocks2 = (dim > 2 ? (direction > 1 ? nn : mm) : 1);
541 for (
int i2=0; i2<n_blocks2; ++i2)
543 for (
int i1=0; i1<n_blocks1; ++i1)
545 for (
int col=0; col<n_cols; ++col)
547 Number val0, val1, in0, in1, res0, res1;
548 if (dof_to_quad ==
true)
550 val0 = shape_values[col];
551 val1 = shape_values[nn-1-col];
555 val0 = shape_values[col*n_q_points_1d];
556 val1 = shape_values[(col+1)*n_q_points_1d-1];
561 in1 = in[stride*(mm-1)];
566 for (
int ind=1; ind<mid; ++ind)
568 if (dof_to_quad ==
true)
570 val0 = shape_values[ind*n_q_points_1d+col];
571 val1 = shape_values[ind*n_q_points_1d+nn-1-col];
575 val0 = shape_values[col*n_q_points_1d+ind];
576 val1 = shape_values[(col+1)*n_q_points_1d-1-ind];
578 in0 = in[stride*ind];
579 in1 = in[stride*(mm-1-ind)];
587 res0 = res1 = Number();
588 if (dof_to_quad ==
true)
592 val0 = shape_values[mid*n_q_points_1d+col];
593 val1 = val0 * in[stride*mid];
600 if (mm % 2 == 1 && nn % 2 == 0)
602 val0 = shape_values[col*n_q_points_1d+mid];
603 val1 = val0 * in[stride*mid];
610 out[stride*col] = res0;
611 out[stride*(nn-1-col)] = res1;
615 out[stride*col] += res0;
616 out[stride*(nn-1-col)] += res1;
619 if ( dof_to_quad ==
true && nn%2==1 && mm%2==1 )
622 out[stride*n_cols] = in[stride*mid];
624 out[stride*n_cols] += in[stride*mid];
626 else if (dof_to_quad ==
true && nn%2==1)
629 Number val0 = shape_values[n_cols];
632 res0 = in[0] + in[stride*(mm-1)];
634 for (
int ind=1; ind<mid; ++ind)
636 val0 = shape_values[ind*n_q_points_1d+n_cols];
637 Number val1 = in[stride*ind] + in[stride*(mm-1-ind)];
645 out[stride*n_cols] = res0;
647 out[stride*n_cols] += res0;
649 else if (dof_to_quad ==
false && nn%2 == 1)
654 Number val0 = shape_values[n_cols*n_q_points_1d];
655 res0 = in[0] + in[stride*(mm-1)];
657 for (
int ind=1; ind<mid; ++ind)
659 val0 = shape_values[n_cols*n_q_points_1d+ind];
660 Number val1 = in[stride*ind] + in[stride*(mm-1-ind)];
665 res0 += in[stride*mid];
670 out[stride*n_cols] = res0;
672 out[stride*n_cols] += res0;
722 template <
int dim,
int fe_degree,
int n_q_po
ints_1d,
typename Number>
723 template <
int direction,
bool dof_to_quad,
bool add>
726 EvaluatorTensorProduct<evaluate_symmetric,dim,fe_degree,n_q_points_1d,Number>
727 ::gradients (
const Number in [],
731 const int mm = dof_to_quad ? (fe_degree+1) : n_q_points_1d,
732 nn = dof_to_quad ? n_q_points_1d : (fe_degree+1);
733 const int n_cols = nn / 2;
734 const int mid = mm / 2;
736 const int n_blocks1 = (dim > 1 ? (direction > 0 ? nn : mm) : 1);
737 const int n_blocks2 = (dim > 2 ? (direction > 1 ? nn : mm) : 1);
740 for (
int i2=0; i2<n_blocks2; ++i2)
742 for (
int i1=0; i1<n_blocks1; ++i1)
744 for (
int col=0; col<n_cols; ++col)
746 Number val0, val1, in0, in1, res0, res1;
747 if (dof_to_quad ==
true)
749 val0 = shape_gradients[col];
750 val1 = shape_gradients[nn-1-col];
754 val0 = shape_gradients[col*n_q_points_1d];
755 val1 = shape_gradients[(nn-col-1)*n_q_points_1d];
760 in1 = in[stride*(mm-1)];
765 for (
int ind=1; ind<mid; ++ind)
767 if (dof_to_quad ==
true)
769 val0 = shape_gradients[ind*n_q_points_1d+col];
770 val1 = shape_gradients[ind*n_q_points_1d+nn-1-col];
774 val0 = shape_gradients[col*n_q_points_1d+ind];
775 val1 = shape_gradients[(nn-col-1)*n_q_points_1d+ind];
777 in0 = in[stride*ind];
778 in1 = in[stride*(mm-1-ind)];
786 res0 = res1 = Number();
789 if (dof_to_quad ==
true)
790 val0 = shape_gradients[mid*n_q_points_1d+col];
792 val0 = shape_gradients[col*n_q_points_1d+mid];
793 val1 = val0 * in[stride*mid];
799 out[stride*col] = res0;
800 out[stride*(nn-1-col)] = res1;
804 out[stride*col] += res0;
805 out[stride*(nn-1-col)] += res1;
811 if (dof_to_quad ==
true)
812 val0 = shape_gradients[n_cols];
814 val0 = shape_gradients[n_cols*n_q_points_1d];
815 res0 = in[0] - in[stride*(mm-1)];
817 for (
int ind=1; ind<mid; ++ind)
819 if (dof_to_quad ==
true)
820 val0 = shape_gradients[ind*n_q_points_1d+n_cols];
822 val0 = shape_gradients[n_cols*n_q_points_1d+ind];
823 Number val1 = in[stride*ind] - in[stride*(mm-1-ind)];
828 out[stride*n_cols] = res0;
830 out[stride*n_cols] += res0;
866 template <
int dim,
int fe_degree,
int n_q_po
ints_1d,
typename Number>
867 template <
int direction,
bool dof_to_quad,
bool add>
870 EvaluatorTensorProduct<evaluate_symmetric,dim,fe_degree,n_q_points_1d,Number>
871 ::hessians (
const Number in [],
875 const int mm = dof_to_quad ? (fe_degree+1) : n_q_points_1d,
876 nn = dof_to_quad ? n_q_points_1d : (fe_degree+1);
877 const int n_cols = nn / 2;
878 const int mid = mm / 2;
880 const int n_blocks1 = (dim > 1 ? (direction > 0 ? nn : mm) : 1);
881 const int n_blocks2 = (dim > 2 ? (direction > 1 ? nn : mm) : 1);
884 for (
int i2=0; i2<n_blocks2; ++i2)
886 for (
int i1=0; i1<n_blocks1; ++i1)
888 for (
int col=0; col<n_cols; ++col)
890 Number val0, val1, in0, in1, res0, res1;
891 if (dof_to_quad ==
true)
893 val0 = shape_hessians[col];
894 val1 = shape_hessians[nn-1-col];
898 val0 = shape_hessians[col*n_q_points_1d];
899 val1 = shape_hessians[(col+1)*n_q_points_1d-1];
904 in1 = in[stride*(mm-1)];
909 for (
int ind=1; ind<mid; ++ind)
911 if (dof_to_quad ==
true)
913 val0 = shape_hessians[ind*n_q_points_1d+col];
914 val1 = shape_hessians[ind*n_q_points_1d+nn-1-col];
918 val0 = shape_hessians[col*n_q_points_1d+ind];
919 val1 = shape_hessians[(col+1)*n_q_points_1d-1-ind];
921 in0 = in[stride*ind];
922 in1 = in[stride*(mm-1-ind)];
930 res0 = res1 = Number();
933 if (dof_to_quad ==
true)
934 val0 = shape_hessians[mid*n_q_points_1d+col];
936 val0 = shape_hessians[col*n_q_points_1d+mid];
937 val1 = val0 * in[stride*mid];
943 out[stride*col] = res0;
944 out[stride*(nn-1-col)] = res1;
948 out[stride*col] += res0;
949 out[stride*(nn-1-col)] += res1;
955 if (dof_to_quad ==
true)
956 val0 = shape_hessians[n_cols];
958 val0 = shape_hessians[n_cols*n_q_points_1d];
961 res0 = in[0] + in[stride*(mm-1)];
963 for (
int ind=1; ind<mid; ++ind)
965 if (dof_to_quad ==
true)
966 val0 = shape_hessians[ind*n_q_points_1d+n_cols];
968 val0 = shape_hessians[n_cols*n_q_points_1d+ind];
969 Number val1 = in[stride*ind] + in[stride*(mm-1-ind)];
978 if (dof_to_quad ==
true)
979 val0 = shape_hessians[mid*n_q_points_1d+n_cols];
981 val0 = shape_hessians[n_cols*n_q_points_1d+mid];
982 res0 += val0 * in[stride*mid];
985 out[stride*n_cols] = res0;
987 out[stride*n_cols] += res0;
1036 template <
int dim,
int fe_degree,
int n_q_po
ints_1d,
typename Number>
1049 shape_gradients (0),
1060 const unsigned int dummy1 = 0,
1061 const unsigned int dummy2 = 0)
1063 shape_values (shape_values.begin()),
1064 shape_gradients (shape_gradients.begin()),
1065 shape_hessians (shape_hessians.begin())
1071 template <
int direction,
bool dof_to_quad,
bool add>
1073 values (
const Number in [],
1076 apply<direction,dof_to_quad,add,0>(shape_values, in, out);
1079 template <
int direction,
bool dof_to_quad,
bool add>
1081 gradients (
const Number in [],
1084 apply<direction,dof_to_quad,add,1>(shape_gradients, in, out);
1087 template <
int direction,
bool dof_to_quad,
bool add>
1089 hessians (
const Number in [],
1092 apply<direction,dof_to_quad,add,2>(shape_hessians, in, out);
1095 template <
int direction,
bool dof_to_quad,
bool add,
int type>
1096 static void apply (
const Number *shape_data,
1100 const Number *shape_values;
1101 const Number *shape_gradients;
1102 const Number *shape_hessians;
1107 template <
int dim,
int fe_degree,
int n_q_po
ints_1d,
typename Number>
1108 template <
int direction,
bool dof_to_quad,
bool add,
int type>
1111 EvaluatorTensorProduct<evaluate_evenodd,dim,fe_degree,n_q_points_1d,Number>
1112 ::apply (
const Number *shapes,
1118 const int mm = dof_to_quad ? (fe_degree+1) : n_q_points_1d,
1119 nn = dof_to_quad ? n_q_points_1d : (fe_degree+1);
1120 const int n_cols = nn / 2;
1121 const int mid = mm / 2;
1123 const int n_blocks1 = (dim > 1 ? (direction > 0 ? nn : mm) : 1);
1124 const int n_blocks2 = (dim > 2 ? (direction > 1 ? nn : mm) : 1);
1127 const int offset = (n_q_points_1d+1)/2;
1133 for (
int i2=0; i2<n_blocks2; ++i2)
1135 for (
int i1=0; i1<n_blocks1; ++i1)
1137 Number xp[mid>0?mid:1], xm[mid>0?mid:1];
1138 for (
int i=0; i<mid; ++i)
1140 if (dof_to_quad ==
true && type == 1)
1142 xp[i] = in[stride*i] - in[stride*(mm-1-i)];
1143 xm[i] = in[stride*i] + in[stride*(mm-1-i)];
1147 xp[i] = in[stride*i] + in[stride*(mm-1-i)];
1148 xm[i] = in[stride*i] - in[stride*(mm-1-i)];
1151 for (
int col=0; col<n_cols; ++col)
1156 if (dof_to_quad ==
true)
1158 r0 = shapes[col] * xp[0];
1159 r1 = shapes[fe_degree*offset + col] * xm[0];
1163 r0 = shapes[col*offset] * xp[0];
1164 r1 = shapes[(fe_degree-col)*offset] * xm[0];
1166 for (
int ind=1; ind<mid; ++ind)
1168 if (dof_to_quad ==
true)
1170 r0 += shapes[ind*offset+col] * xp[ind];
1171 r1 += shapes[(fe_degree-ind)*offset+col] * xm[ind];
1175 r0 += shapes[col*offset+ind] * xp[ind];
1176 r1 += shapes[(fe_degree-col)*offset+ind] * xm[ind];
1182 if (mm % 2 == 1 && dof_to_quad ==
true)
1185 r1 += shapes[mid*offset+col] * in[stride*mid];
1187 r0 += shapes[mid*offset+col] * in[stride*mid];
1189 else if (mm % 2 == 1 && (nn % 2 == 0 || type > 0))
1190 r0 += shapes[col*offset+mid] * in[stride*mid];
1194 out[stride*col] = r0 + r1;
1195 if (type == 1 && dof_to_quad ==
false)
1196 out[stride*(nn-1-col)] = r1 - r0;
1198 out[stride*(nn-1-col)] = r0 - r1;
1202 out[stride*col] += r0 + r1;
1203 if (type == 1 && dof_to_quad ==
false)
1204 out[stride*(nn-1-col)] += r1 - r0;
1206 out[stride*(nn-1-col)] += r0 - r1;
1209 if ( type == 0 && dof_to_quad ==
true && nn%2==1 && mm%2==1 )
1212 out[stride*n_cols] = in[stride*mid];
1214 out[stride*n_cols] += in[stride*mid];
1216 else if (dof_to_quad ==
true && nn%2==1)
1221 r0 = shapes[n_cols] * xp[0];
1222 for (
int ind=1; ind<mid; ++ind)
1223 r0 += shapes[ind*offset+n_cols] * xp[ind];
1227 if (type != 1 && mm % 2 == 1)
1228 r0 += shapes[mid*offset+n_cols] * in[stride*mid];
1231 out[stride*n_cols] = r0;
1233 out[stride*n_cols] += r0;
1235 else if (dof_to_quad ==
false && nn%2 == 1)
1242 r0 = shapes[n_cols*offset] * xm[0];
1243 for (
int ind=1; ind<mid; ++ind)
1244 r0 += shapes[n_cols*offset+ind] * xm[ind];
1248 r0 = shapes[n_cols*offset] * xp[0];
1249 for (
int ind=1; ind<mid; ++ind)
1250 r0 += shapes[n_cols*offset+ind] * xp[ind];
1256 if (type == 0 && mm % 2 == 1)
1257 r0 += in[stride*mid];
1258 else if (type == 2 && mm % 2 == 1)
1259 r0 += shapes[n_cols*offset+mid] * in[stride*mid];
1262 out[stride*n_cols] = r0;
1264 out[stride*n_cols] += r0;
1296 DEAL_II_NAMESPACE_CLOSE
static const unsigned int invalid_unsigned_int
EvaluatorTensorProduct(const AlignedVector< Number > &shape_values, const AlignedVector< Number > &shape_gradients, const AlignedVector< Number > &shape_hessians, const unsigned int dummy1=0, const unsigned int dummy2=0)
EvaluatorTensorProduct(const AlignedVector< Number > &shape_values, const AlignedVector< Number > &shape_gradients, const AlignedVector< Number > &shape_hessians, const unsigned int dummy1=0, const unsigned int dummy2=0)
#define AssertIndexRange(index, range)
EvaluatorTensorProduct(const AlignedVector< Number > &shape_values, const AlignedVector< Number > &shape_gradients, const AlignedVector< Number > &shape_hessians, const unsigned int fe_degree, const unsigned int n_q_points_1d)
#define Assert(cond, exc)
EvaluatorTensorProduct(const AlignedVector< Number > &shape_values, const AlignedVector< Number > &shape_gradients, const AlignedVector< Number > &shape_hessians, const unsigned int dummy1=0, const unsigned int dummy2=0)
static ::ExceptionBase & ExcNotImplemented()