14#ifndef dealii__tensor_product_kernels_h
15#define dealii__tensor_product_kernels_h
22#include <Kokkos_Core.hpp>
50 template <
bool add,
typename ViewTypeIn,
typename ViewTypeOut>
53 const Kokkos::TeamPolicy<
54 MemorySpace::Default::kokkos_space::execution_space>::member_type
62 Kokkos::parallel_for(Kokkos::TeamVectorRange(team_member, N),
65 Kokkos::atomic_add(&dst(i), src(i));
70 team_member.team_barrier();
75#if DEAL_II_KOKKOS_VERSION_GTE(4, 0, 0)
83 typename ShapeDataMemorySpace,
84 bool contract_over_rows,
89 apply_1d(
const Kokkos::TeamPolicy<
90 MemorySpace::Default::kokkos_space::execution_space>::member_type
92 const Kokkos::View<Number *, ShapeDataMemorySpace> shape_data,
96 constexpr int Nk = (contract_over_rows ? n_rows : n_columns),
97 Nq = (contract_over_rows ? n_columns : n_rows);
103 Kokkos::parallel_for(Kokkos::TeamThreadRange(team_member, Nq),
106 for (
int k = 0; k < Nk; ++k)
108 const int shape_idx =
109 (contract_over_rows ? q + k * Nq :
111 sum += shape_data(shape_idx) * in(k);
115 Kokkos::atomic_add(&out(q), sum);
120 team_member.team_barrier();
128 template <
int n_rows,
132 typename ShapeDataMemorySpace,
133 bool contract_over_rows,
136 typename ViewTypeOut>
138 apply_2d(
const Kokkos::TeamPolicy<
139 MemorySpace::Default::kokkos_space::execution_space>::member_type
141 const Kokkos::View<Number *, ShapeDataMemorySpace> shape_data,
145 using TeamType = Kokkos::TeamPolicy<
146 MemorySpace::Default::kokkos_space::execution_space>::member_type;
165 constexpr int Nj = (direction < 1 ? n_rows : n_columns),
166 Nk = (contract_over_rows ? n_rows : n_columns),
167 Nq = (contract_over_rows ? n_columns : n_rows);
174 Kokkos::TeamThreadMDRange<Kokkos::Rank<2>, TeamType>(team_member,
177 Kokkos::parallel_for(thread_policy, [&](
const int j,
const int q) {
178 const int base_shape = contract_over_rows ? q : q * n_columns;
179 const int stride_shape = contract_over_rows ? n_columns : 1;
181 const int base_in = (direction == 0 ? j * Nk : j);
184 Number sum = shape_data(base_shape) * in(base_in);
185 for (
int k = 1; k < Nk; ++k)
186 sum += shape_data(base_shape + k * stride_shape) *
187 in(base_in + k * stride_in);
189 const int index_out = (direction == 0 ? j * Nq + q : j + q * Nj);
192 Kokkos::atomic_add(&out(index_out),
sum);
194 out(index_out) =
sum;
197 team_member.team_barrier();
205 template <
int n_rows,
209 typename ShapeDataMemorySpace,
210 bool contract_over_rows,
213 typename ViewTypeOut>
215 apply_3d(
const Kokkos::TeamPolicy<
216 MemorySpace::Default::kokkos_space::execution_space>::member_type
218 const Kokkos::View<Number *, ShapeDataMemorySpace> shape_data,
222 using TeamType = Kokkos::TeamPolicy<
223 MemorySpace::Default::kokkos_space::execution_space>::member_type;
246 constexpr int Ni = (direction < 1 ? n_rows : n_columns),
247 Nj = (direction < 2 ? n_rows : n_columns),
248 Nk = (contract_over_rows ? n_rows : n_columns),
249 Nq = (contract_over_rows ? n_columns : n_rows);
255 auto thread_policy = Kokkos::TeamThreadMDRange<Kokkos::Rank<3>, TeamType>(
256 team_member, Ni, Nj, Nq);
257 Kokkos::parallel_for(
258 thread_policy, [&](
const int i,
const int j,
const int q) {
259 const int base_shape = contract_over_rows ? q : q * n_columns;
260 const int stride_shape = contract_over_rows ? n_columns : 1;
263 (direction == 0 ? (i * Nj + j) * Nk :
264 (direction == 1 ? i + j * Ni * Nk : i * Nj + j));
267 Number sum = shape_data(base_shape) * in(base_in);
268 for (
int k = 1; k < Nk; ++k)
269 sum += shape_data(base_shape + k * stride_shape) *
270 in(base_in + k * stride_in);
272 const int index_out =
273 (direction == 0 ? (i * Nj + j) * Nq + q :
274 (direction == 1 ? i + (j * Nq + q) * Ni :
275 (i + q * Ni) * Nj + j));
278 Kokkos::atomic_add(&out(index_out),
sum);
280 out(index_out) =
sum;
283 team_member.team_barrier();
293 typename ShapeDataMemorySpace,
295 bool contract_over_rows,
298 typename ViewTypeOut>
301 MemorySpace::Default::kokkos_space::execution_space>::member_type
303 const Kokkos::View<Number *, ShapeDataMemorySpace> shape_data,
318 if constexpr (dim == 1)
323 ShapeDataMemorySpace,
325 add>(team_member, shape_data, in, out);
326 if constexpr (dim == 2)
331 ShapeDataMemorySpace,
333 add>(team_member, shape_data, in, out);
334 if constexpr (dim == 3)
339 ShapeDataMemorySpace,
341 add>(team_member, shape_data, in, out);
348 constexpr int Nk = contract_over_rows ? n_rows : n_columns;
349 constexpr int Nq = contract_over_rows ? n_columns : n_rows;
355 constexpr int N = NI * NJ * Nq;
358 Kokkos::parallel_for(
359 Kokkos::TeamThreadRange(team_member, N), [&](
const int index_out) {
362 const int q = (index_out / stride) % Nq;
363 const int I = (index_out / stride) / Nq;
364 const int J = index_out % stride;
366 const int base_shape = contract_over_rows ? q : q * n_columns;
367 const int stride_shape = contract_over_rows ? n_columns : 1;
368 const int base_in = I * Nk * stride + J;
370 Number sum = shape_data(base_shape) * in(base_in);
371 for (
int k = 1; k < Nk; ++k)
373 const int index_in = (I * Nk + k) * stride + J;
374 sum += shape_data(base_shape + k * stride_shape) * in(index_in);
378 Kokkos::atomic_add(&out(index_out), sum);
380 out(index_out) = sum;
383 team_member.team_barrier();
397 typename ShapeDataMemorySpace =
412 typename ShapeDataMemorySpace>
418 ShapeDataMemorySpace>
422 MemorySpace::Default::kokkos_space::execution_space>::member_type;
425 MemorySpace::Default::kokkos_space::
426 execution_space::scratch_memory_space,
427 Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
432 Kokkos::View<Number *, ShapeDataMemorySpace> shape_values,
433 Kokkos::View<Number *, ShapeDataMemorySpace> shape_gradients,
434 Kokkos::View<Number *, ShapeDataMemorySpace> co_shape_gradients,
441 template <
int direction,
446 typename ViewTypeOut>
448 values(
const ViewTypeIn in, ViewTypeOut out)
const;
454 template <
int direction,
459 typename ViewTypeOut>
461 gradients(
const ViewTypeIn in, ViewTypeOut out)
const;
467 template <
int direction,
472 typename ViewTypeOut>
474 co_gradients(
const ViewTypeIn in, ViewTypeOut out)
const;
508 typename ShapeDataMemorySpace>
515 ShapeDataMemorySpace>::
516 EvaluatorTensorProduct(
518 Kokkos::View<Number *, ShapeDataMemorySpace> shape_values,
519 Kokkos::View<Number *, ShapeDataMemorySpace> shape_gradients,
520 Kokkos::View<Number *, ShapeDataMemorySpace> co_shape_gradients,
522 : team_member(team_member)
523 , shape_values(shape_values)
524 , shape_gradients(shape_gradients)
525 , co_shape_gradients(co_shape_gradients)
535 typename ShapeDataMemorySpace>
536 template <
int direction,
541 typename ViewTypeOut>
548 ShapeDataMemorySpace>::values(
const ViewTypeIn in,
549 ViewTypeOut out)
const
551 if constexpr (in_place)
557 ShapeDataMemorySpace,
560 false>(team_member, shape_values, in, temp);
562 populate_view<add>(team_member, out, temp, out.extent(0));
569 ShapeDataMemorySpace,
572 add>(team_member, shape_values, in, out);
581 typename ShapeDataMemorySpace>
582 template <
int direction,
587 typename ViewTypeOut>
594 ShapeDataMemorySpace>::gradients(
const ViewTypeIn in,
598 if constexpr (in_place)
604 ShapeDataMemorySpace,
607 false>(team_member, shape_gradients, in, temp);
609 populate_view<add>(team_member, out, temp, out.extent(0));
616 ShapeDataMemorySpace,
619 add>(team_member, shape_gradients, in, out);
628 typename ShapeDataMemorySpace>
629 template <
int direction,
634 typename ViewTypeOut>
642 ShapeDataMemorySpace>::co_gradients(
const ViewTypeIn in,
643 ViewTypeOut out)
const
645 if constexpr (in_place)
651 ShapeDataMemorySpace,
654 false>(team_member, co_shape_gradients, in, temp);
656 populate_view<add>(team_member, out, temp, out.extent(0));
663 ShapeDataMemorySpace,
666 add>(team_member, co_shape_gradients, in, out);
683 template <
int n_rows,
685 bool contract_over_rows,
697 constexpr int mm = contract_over_rows ? n_rows : n_columns;
698 constexpr int nn = contract_over_rows ? n_columns : n_rows;
703 std::remove_cv_t<std::remove_reference_t<
decltype(out[0])>>;
708 for (
int k = 0; k < mm; ++k)
709 r_in[k] = in[k * stride_in];
711 for (
int q = 0; q < nn; ++q)
714 for (
int k = 0; k < mm; ++k)
716 const int row = contract_over_rows ? k : q;
717 const int col = contract_over_rows ? q : k;
718 sum += matrix[row * n_columns + col] * r_in[k];
722 out[q * stride_out] += sum;
724 out[q * stride_out] = sum;
732 template <
int n_rows,
734 bool contract_over_rows,
744 const int stride_out)
746 constexpr int mm = contract_over_rows ? n_rows : n_columns;
747 constexpr int nn = contract_over_rows ? n_columns : n_rows;
752 std::remove_cv_t<std::remove_reference_t<
decltype(out[0])>>;
757 for (
int k = 0; k < mm; ++k)
758 r_in[k] = in[k * stride_in];
760 for (
int q = 0; q < nn; ++q)
763 for (
int k = 0; k < mm; ++k)
765 const int row = contract_over_rows ? k : q;
766 const int col = contract_over_rows ? q : k;
767 sum += matrix[row * n_columns + col] * r_in[k];
771 out[q * stride_out] += sum;
773 out[q * stride_out] = sum;
813 bool contract_over_rows,
815 typename ViewTypeMatrix,
817 typename ViewTypeOut,
818 typename = std::enable_if_t<Kokkos::is_view<ViewTypeOut>::value>>
821 MemorySpace::Default::kokkos_space::execution_space>::member_type
823 const ViewTypeMatrix shape_data,
826 const int batch_size = 1)
828 static_assert(direction >= 0 && direction < dim,
829 "direction must be in [0, dim)");
832 constexpr int mm = contract_over_rows ? n_rows : n_columns;
833 constexpr int nn = contract_over_rows ? n_columns : n_rows;
841 constexpr int n_blocks2 =
Utilities::pow(n_rows, dim - direction - 1);
843 constexpr int n_in_per_elmt = n_blocks1 * mm * n_blocks2;
844 constexpr int n_out_per_elmt = n_blocks1 * nn * n_blocks2;
851 static_cast<std::size_t
>(batch_size) * n_in_per_elmt,
854 static_cast<std::size_t
>(batch_size) * n_out_per_elmt,
857 Kokkos::parallel_for(
858 Kokkos::TeamVectorRange(team_member,
859 batch_size * n_blocks1 * n_blocks2),
861 const int e = tid / (n_blocks1 * n_blocks2);
862 const int rem = tid % (n_blocks1 * n_blocks2);
863 const int i2 = rem / n_blocks1;
864 const int i1 = rem % n_blocks1;
866 const int in_offset = e * n_in_per_elmt + i2 * n_blocks1 * mm + i1;
867 const int out_offset =
868 e * n_out_per_elmt + i2 * n_blocks1 * nn + i1;
879 Kokkos::make_pair(in_offset,
static_cast<int>(in.extent(0)))),
882 out_offset,
static_cast<int>(out.extent(0)))));
885 team_member.team_barrier();
894 typename ViewTypeOut,
896 typename = std::enable_if_t<Kokkos::is_view<ViewTypeOut>::value>>
899 const Kokkos::TeamPolicy<
900 MemorySpace::Default::kokkos_space::execution_space>::member_type
903 const ViewTypeIn src,
906 Kokkos::parallel_for(Kokkos::TeamVectorRange(team_member, N),
909 dst(tid) += src(tid);
914 team_member.team_barrier();
934 template <
int dim,
int n_rows,
int n_columns,
typename Number>
943 MemorySpace::Default::kokkos_space::execution_space>::member_type;
946 Kokkos::View<Number *,
947 MemorySpace::Default::kokkos_space::execution_space::
948 scratch_memory_space,
949 Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
952 Kokkos::View<Number *,
953 MemorySpace::Default::kokkos_space::execution_space::
954 scratch_memory_space,
955 Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
964 const int batch_size = 1);
970 template <
int direction,
975 typename ViewTypeOut>
977 value(
const ViewTypeIn in, ViewTypeOut out)
const;
983 template <
int direction,
988 typename ViewTypeOut>
990 derivative(
const ViewTypeIn in, ViewTypeOut out)
const;
996 template <
int direction,
1000 typename ViewTypeIn,
1001 typename ViewTypeOut>
1003 co_derivative(
const ViewTypeIn in, ViewTypeOut out)
const;
1022 typename ViewTypeIn,
1023 typename ViewTypeOut>
1025 co_gradient(
const ViewTypeIn in, ViewTypeOut out)
const;
1036 template <
int dim,
int n_rows,
int n_columns,
typename Number>
1044 const int batch_size)
1045 : team_member(team_member)
1046 , shape_values(shape_values)
1047 , shape_gradients(shape_gradients)
1048 , co_shape_gradients(co_shape_gradients)
1050 , batch_size(batch_size)
1053 template <
int dim,
int n_rows,
int n_columns,
typename Number>
1054 template <
int direction,
1058 typename ViewTypeIn,
1059 typename ViewTypeOut>
1062 value(
const ViewTypeIn in, ViewTypeOut out)
const
1064 if constexpr (in_place)
1066 apply<dim, direction, n_rows, n_columns, dof_to_quad, false>(
1067 team_member, shape_values, in, temp, batch_size);
1069 constexpr int nn = dof_to_quad ? n_columns : n_rows;
1071 constexpr int n_blocks2 =
1074 populate_view<add>(team_member,
1077 batch_size * n_blocks1 * nn * n_blocks2);
1081 apply<dim, direction, n_rows, n_columns, dof_to_quad, add>(
1082 team_member, shape_values, in, out, batch_size);
1086 template <
int dim,
int n_rows,
int n_columns,
typename Number>
1087 template <
int direction,
1091 typename ViewTypeIn,
1092 typename ViewTypeOut>
1095 derivative(
const ViewTypeIn in, ViewTypeOut out)
const
1097 if constexpr (in_place)
1099 apply<dim, direction, n_rows, n_columns, dof_to_quad, false>(
1100 team_member, shape_gradients, in, temp, batch_size);
1102 constexpr int nn = dof_to_quad ? n_columns : n_rows;
1104 constexpr int n_blocks2 =
1107 populate_view<add>(team_member,
1110 batch_size * n_blocks1 * nn * n_blocks2);
1114 apply<dim, direction, n_rows, n_columns, dof_to_quad, add>(
1115 team_member, shape_gradients, in, out, batch_size);
1119 template <
int dim,
int n_rows,
int n_columns,
typename Number>
1120 template <
int direction,
1124 typename ViewTypeIn,
1125 typename ViewTypeOut>
1130 if constexpr (in_place)
1132 apply<dim, direction, n_columns, n_columns, dof_to_quad, false>(
1133 team_member, co_shape_gradients, in, temp, batch_size);
1136 constexpr int n_blocks2 =
1139 populate_view<add>(team_member,
1142 batch_size * n_blocks1 * n_columns * n_blocks2);
1146 apply<dim, direction, n_columns, n_columns, dof_to_quad, add>(
1147 team_member, co_shape_gradients, in, out, batch_size);
1151 template <
int dim,
int n_rows,
int n_columns,
typename Number>
1154 typename ViewTypeIn,
1155 typename ViewTypeOut>
1158 co_gradient(
const ViewTypeIn in, ViewTypeOut out)
const
1160 static_assert(dim >= 1,
"dim must be at least 1");
1162 ViewTypeIn::rank == (
transpose ? 2 : 1),
1163 "in must be the values (1D view) for evaluate_gradients (transpose = "
1164 "false), or the gradients (2D view) for integrate_gradients (transpose "
1167 ViewTypeOut::rank == (
transpose ? 1 : 2),
1168 "out must be the gradients (2D view) for evaluate_gradients (transpose "
1169 "= false), or the values (1D view) for integrate_gradients (transpose "
1173 constexpr int co_dimension_size =
Utilities::pow(n_columns, dim - 1);
1175 Kokkos::parallel_for(
1176 Kokkos::TeamVectorRange(team_member, batch_size * co_dimension_size),
1177 [&](
const int tid) {
1178 const int elmnt_idx = tid / co_dimension_size;
1179 const int reminder = tid % co_dimension_size;
1187 Kokkos::Array<
int, dim - 1> idx_d, stride_d;
1188 Number reg[dim][n_columns];
1190 for (
int d = 0; d < dim - 1; ++d)
1195 idx_d[d] = (reminder / stride_d[d]) % n_columns;
1198 for (
int n = 0; n < n_columns; ++n)
1201 reg[d][n] = co_shape_gradients(n * n_columns + idx_d[d]);
1203 reg[d][n] = co_shape_gradients(idx_d[d] * n_columns + n);
1208 for (
int n = 0; n < n_columns; ++n)
1211 reg[dim - 1][n] = in(elmnt_idx * n_q_points + reminder +
1212 n * co_dimension_size);
1214 reg[dim - 1][n] = in(elmnt_idx * n_q_points + reminder +
1215 n * co_dimension_size,
1221 for (
int last = 0; last < n_columns; ++last)
1223 const int q_point = reminder + last * co_dimension_size;
1228 for (
int d = 0; d < dim - 1; ++d)
1230 const int q_point_base =
1231 q_point - idx_d[d] * stride_d[d];
1233 elmnt_idx * n_q_points + q_point_base;
1238 for (
int n = 0; n < n_columns; ++n)
1239 res_d += reg[d][n] * in(in_base + n * stride_d[d]);
1247 for (
int n = 0; n < n_columns; ++n)
1248 res_d += co_shape_gradients(n * n_columns + last) *
1250 result[dim - 1] = res_d;
1253 for (
int d = 0; d < dim; ++d)
1256 out(elmnt_idx * n_q_points + q_point, d) += result[d];
1258 out(elmnt_idx * n_q_points + q_point, d) = result[d];
1265 for (
int d = 0; d < dim - 1; ++d)
1267 const int point_base = q_point - idx_d[d] * stride_d[d];
1268 const int grad_row =
1269 elmnt_idx * n_q_points + point_base;
1273 for (
int n = 0; n < n_columns; ++n)
1275 in(grad_row + n * stride_d[d], d) * reg[d][n];
1280 for (
int n = 0; n < n_columns; ++n)
1281 result += reg[dim - 1][n] *
1282 co_shape_gradients(last * n_columns + n);
1285 out(elmnt_idx * n_q_points + q_point) += result;
1287 out(elmnt_idx * n_q_points + q_point) = result;
1292 team_member.team_barrier();
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_HOST_DEVICE
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
static ::ExceptionBase & ExcInternalError()
* * * RotationFunction< dim, Number >::RotationFunction Number(dim)
void populate_view(const Kokkos::TeamPolicy< MemorySpace::Default::kokkos_space::execution_space >::member_type &team_member, ViewTypeOut dst, const ViewTypeIn src, const int N)
void apply_matrix_vector_product(const TypeMatrix matrix, const TypeIn in, TypeOut out)
void populate_view(const Kokkos::TeamPolicy< MemorySpace::Default::kokkos_space::execution_space >::member_type &team_member, ViewTypeOut dst, const ViewTypeIn src, const int N)
void apply(const Kokkos::TeamPolicy< MemorySpace::Default::kokkos_space::execution_space >::member_type &team_member, const Kokkos::View< Number *, ShapeDataMemorySpace > shape_data, const ViewTypeIn in, ViewTypeOut out)
T sum(const T &t, const MPI_Comm mpi_communicator)
constexpr T pow(const T base, const int iexp)
::Kokkos::DefaultExecutionSpace::memory_space kokkos_space
Kokkos::TeamPolicy< MemorySpace::Default::kokkos_space::execution_space >::member_type TeamHandle
Kokkos::View< Number *, MemorySpace::Default::kokkos_space::execution_space::scratch_memory_space, Kokkos::MemoryTraits< Kokkos::Unmanaged > > SharedView
Kokkos::View< Number *, ShapeDataMemorySpace > shape_values
const TeamHandle & team_member
Kokkos::View< Number *, ShapeDataMemorySpace > co_shape_gradients
Kokkos::View< Number *, ShapeDataMemorySpace > shape_gradients
Kokkos::TeamPolicy< MemorySpace::Default::kokkos_space::execution_space >::member_type TeamHandle
ShapeDataType shape_gradients
const TeamHandle & team_member
Kokkos::View< Number *, MemorySpace::Default::kokkos_space::execution_space::scratch_memory_space, Kokkos::MemoryTraits< Kokkos::Unmanaged > > ShapeDataType
ShapeDataType shape_values
ShapeDataType co_shape_gradients
Kokkos::View< Number *, MemorySpace::Default::kokkos_space::execution_space::scratch_memory_space, Kokkos::MemoryTraits< Kokkos::Unmanaged > > SharedView