21using mfem::kernels::internal::SetMaxOf;
31template <
int T_D1D = 0,
int T_Q1D = 0>
32void SmemPAVectorMassApply2D(
const int NE,
34 const Array<real_t> &
b,
41 static constexpr int DIM = 2, VDIM = 2;
42 const int D1D = T_D1D ? T_D1D : d1d;
43 const int Q1D = T_Q1D ? T_Q1D : q1d;
45 const bool const_coeff = coeff_vdim == 1;
46 const bool vector_coeff = coeff_vdim ==
DIM;
47 const bool matrix_coeff = coeff_vdim ==
DIM*
DIM;
49 const auto B =
b.Read();
50 const auto D =
Reshape(d.Read(), Q1D, Q1D, coeff_vdim, NE);
51 const auto X =
Reshape(x.Read(), D1D, D1D, VDIM, NE);
52 auto Y =
Reshape(y.ReadWrite(), D1D, D1D, VDIM, NE);
56 constexpr int MD1 = T_D1D > 0 ? SetMaxOf(T_D1D) :
DofQuadLimits::MAX_T1D;
57 constexpr int MQ1 = T_Q1D > 0 ? SetMaxOf(T_Q1D) :
DofQuadLimits::MAX_T1D;
59 MFEM_SHARED
real_t sB[MD1][MQ1], smem[MQ1][MQ1];
60 kernels::internal::v_regs2d_t<VDIM, MQ1> r0, r1;
61 kernels::internal::LoadMatrix(D1D, Q1D, B, sB);
62 kernels::internal::LoadDofs2d(e, D1D, X, r0);
63 kernels::internal::Eval2d(D1D, Q1D, smem, sB, r0, r1);
65 MFEM_FOREACH_THREAD_DIRECT(qy, y, Q1D)
67 MFEM_FOREACH_THREAD_DIRECT(qx, x, Q1D)
69 const real_t Qx = r1[0][qy][qx];
70 const real_t Qy = r1[1][qy][qx];
71 const real_t D0 = D(qx, qy, 0, e);
75 r0[0][qy][qx] = D0 * Qx;
76 r0[1][qy][qx] = D0 * Qy;
80 const real_t D1 = D(qx, qy, 1, e);
81 r0[0][qy][qx] = D0 * Qx;
82 r0[1][qy][qx] = D1 * Qy;
86 const real_t D1 = D(qx, qy, 1, e);
87 const real_t D2 = D(qx, qy, 2, e);
88 const real_t D3 = D(qx, qy, 3, e);
89 r0[0][qy][qx] = D0 * Qx + D1 * Qy;
90 r0[1][qy][qx] = D2 * Qx + D3 * Qy;
94 kernels::internal::EvalTranspose2d(D1D, Q1D, smem, sB, r0, r1);
95 kernels::internal::WriteDofs2d(e, D1D, r1, Y);
99template <
int T_D1D = 0,
int T_Q1D = 0>
100void SmemPAVectorMassApply3D(
const int NE,
101 const int coeff_vdim,
102 const Array<real_t> &
b,
109 static constexpr int VDIM = 3;
110 const int D1D = T_D1D ? T_D1D : d1d;
111 const int Q1D = T_Q1D ? T_Q1D : q1d;
113 const bool const_coeff = coeff_vdim == 1;
114 const bool vector_coeff = coeff_vdim == VDIM;
115 const bool matrix_coeff = coeff_vdim == VDIM*VDIM;
117 const auto B =
b.Read();
118 const auto D =
Reshape(d.Read(), Q1D, Q1D, Q1D, coeff_vdim, NE);
119 const auto X =
Reshape(x.Read(), D1D, D1D, D1D, VDIM, NE);
120 auto Y =
Reshape(y.ReadWrite(), D1D, D1D, D1D, VDIM, NE);
124 constexpr int MD1 = T_D1D > 0 ? SetMaxOf(T_D1D) :
DofQuadLimits::MAX_T1D;
125 constexpr int MQ1 = T_Q1D > 0 ? SetMaxOf(T_Q1D) :
DofQuadLimits::MAX_T1D;
127 MFEM_SHARED
real_t sB[MD1][MQ1], smem[MQ1][MQ1];
128 kernels::internal::v_regs3d_t<VDIM, MQ1> r0, r1;
129 kernels::internal::LoadMatrix(D1D, Q1D, B, sB);
130 kernels::internal::LoadDofs3d(e, D1D, X, r0);
131 kernels::internal::Eval3d(D1D, Q1D, smem, sB, r0, r1);
133 for (
int qz = 0; qz < Q1D; qz++)
135 MFEM_FOREACH_THREAD_DIRECT(qy, y, Q1D)
137 MFEM_FOREACH_THREAD_DIRECT(qx, x, Q1D)
139 const real_t Qx = r1[0][qz][qy][qx];
140 const real_t Qy = r1[1][qz][qy][qx];
141 const real_t Qz = r1[2][qz][qy][qx];
142 const real_t D0 = D(qx, qy, qz, 0, e);
145 r0[0][qz][qy][qx] = D0 * Qx;
146 r0[1][qz][qy][qx] = D0 * Qy;
147 r0[2][qz][qy][qx] = D0 * Qz;
151 const real_t D1 = D(qx, qy, qz, 1, e);
152 const real_t D2 = D(qx, qy, qz, 2, e);
153 r0[0][qz][qy][qx] = D0 * Qx;
154 r0[1][qz][qy][qx] = D1 * Qy;
155 r0[2][qz][qy][qx] = D2 * Qz;
159 const real_t D1 = D(qx, qy, qz, 1, e);
160 const real_t D2 = D(qx, qy, qz, 2, e);
161 const real_t D3 = D(qx, qy, qz, 3, e);
162 const real_t D4 = D(qx, qy, qz, 4, e);
163 const real_t D5 = D(qx, qy, qz, 5, e);
164 const real_t D6 = D(qx, qy, qz, 6, e);
165 const real_t D7 = D(qx, qy, qz, 7, e);
166 const real_t D8 = D(qx, qy, qz, 8, e);
167 r0[0][qz][qy][qx] = D0 * Qx + D1 * Qy + D2 * Qz;
168 r0[1][qz][qy][qx] = D3 * Qx + D4 * Qy + D5 * Qz;
169 r0[2][qz][qy][qx] = D6 * Qx + D7 * Qy + D8 * Qz;
174 kernels::internal::EvalTranspose3d(D1D, Q1D, smem, sB, r0, r1);
175 kernels::internal::WriteDofs3d(e, D1D, r1, Y);
179template <
int T_Q1D = 0,
int T_MDQ = 16>
180void SmemPAVectorMassAssembleDiagonal2D(
const int ne,
const int d1d,
181 const int q1d,
const real_t *b_r,
184 constexpr int VDIM = 2;
187 const int Q1D = T_Q1D ? T_Q1D : q1d;
189 MFEM_VERIFY(Q1D <= T_MDQ && D1D <= Q1D,
"");
191 const auto B =
Reshape(b_r, Q1D, D1D);
192 const auto D =
Reshape(d_r, Q1D, Q1D, ne);
193 auto Y =
Reshape(y_rw, D1D, D1D, VDIM, ne);
196 ne, Q1D, Q1D, [=] MFEM_HOST_DEVICE(
int e)
198 constexpr int MQ1 = T_Q1D ? T_Q1D : T_MDQ;
200 MFEM_SHARED
real_t sm[MQ1][MQ1];
202 MFEM_FOREACH_THREAD_DIRECT(qx, x, Q1D)
204 MFEM_FOREACH_THREAD_DIRECT(dy, y, D1D)
207 for (
int qy = 0; qy < Q1D; ++qy)
209 u += B(qy, dy) * B(qy, dy) * D(qx, qy, e);
216 MFEM_FOREACH_THREAD_DIRECT(dy, y, D1D)
218 MFEM_FOREACH_THREAD_DIRECT(dx, x, D1D)
221 for (
int qx = 0; qx < Q1D; ++qx)
223 u += B(qx, dx) * B(qx, dx) * sm[qx][dy];
225 Y(dx, dy, 0, e) +=
u;
226 Y(dx, dy, 1, e) +=
u;
233template <
int T_Q1D = 0,
int T_MDQ = 10>
234void SmemPAVectorMassAssembleDiagonal3D(
const int ne,
const int d1d,
235 const int q1d,
const real_t *b_r,
238 constexpr int VDIM = 3;
241 const int Q1D = T_Q1D ? T_Q1D : q1d;
243 MFEM_VERIFY(Q1D <= T_MDQ && D1D <= Q1D,
"");
245 const auto B =
Reshape(b_r, Q1D, D1D);
246 const auto D =
Reshape(d_r, Q1D, Q1D, Q1D, ne);
247 auto Y =
Reshape(y_rw, D1D, D1D, D1D, VDIM, ne);
250 ne, Q1D, Q1D, Q1D, [=] MFEM_HOST_DEVICE(
int e)
252 constexpr int MQ1 = T_Q1D ? T_Q1D : T_MDQ;
254 MFEM_SHARED
real_t sm[2][MQ1][MQ1][MQ1];
256 MFEM_FOREACH_THREAD_DIRECT(dz, z, D1D)
258 MFEM_FOREACH_THREAD_DIRECT(qy, y, Q1D)
260 MFEM_FOREACH_THREAD_DIRECT(qx, x, Q1D)
263 for (
int qz = 0; qz < Q1D; ++qz)
265 u += B(qz, dz) * B(qz, dz) * D(qx, qy, qz, e);
267 sm[0][dz][qy][qx] =
u;
273 MFEM_FOREACH_THREAD_DIRECT(dz, z, D1D)
275 MFEM_FOREACH_THREAD_DIRECT(qx, x, Q1D)
277 MFEM_FOREACH_THREAD_DIRECT(dy, y, D1D)
280 for (
int qy = 0; qy < Q1D; ++qy)
282 u += B(qy, dy) * B(qy, dy) * sm[0][dz][qy][qx];
284 sm[1][dz][dy][qx] =
u;
290 MFEM_FOREACH_THREAD_DIRECT(dz, z, D1D)
292 MFEM_FOREACH_THREAD_DIRECT(dy, y, D1D)
294 MFEM_FOREACH_THREAD_DIRECT(dx, x, D1D)
297 for (
int qx = 0; qx < Q1D; ++qx)
299 u += B(qx, dx) * B(qx, dx) * sm[1][dz][dy][qx];
301 Y(dx, dy, dz, 0, e) +=
u;
302 Y(dx, dy, dz, 1, e) +=
u;
303 Y(dx, dy, dz, 2, e) +=
u;
313template<
int DIM,
int T_D1D,
int T_Q1D>
315VectorMassIntegrator::VectorMassAddMultPA::Kernel()
317 if constexpr (
DIM == 2)
319 return internal::SmemPAVectorMassApply2D<T_D1D,T_Q1D>;
321 else if constexpr (
DIM == 3)
323 return internal::SmemPAVectorMassApply3D<T_D1D, T_Q1D>;
325 MFEM_ABORT(
"Unsupported kernel");
329VectorMassIntegrator::VectorMassAddMultPA::Fallback(
int dim,
int,
int)
333 return internal::SmemPAVectorMassApply2D;
337 return internal::SmemPAVectorMassApply3D;
339 MFEM_ABORT(
"Unsupported kernel");
343template<
int DIM,
int T_Q1D>
345VectorMassIntegrator::VectorMassAssembleDiagonalPA::Kernel()
347 if constexpr (
DIM == 2)
349 return internal::SmemPAVectorMassAssembleDiagonal2D<T_Q1D>;
351 else if constexpr (
DIM == 3)
353 return internal::SmemPAVectorMassAssembleDiagonal3D<T_Q1D>;
355 MFEM_ABORT(
"Unsupported kernel");
359VectorMassIntegrator::VectorMassAssembleDiagonalPA::Fallback(
int dim,
int)
363 return internal::SmemPAVectorMassAssembleDiagonal2D;
367 return internal::SmemPAVectorMassAssembleDiagonal3D;
369 MFEM_ABORT(
"Unsupported kernel");
void(*)(const int, const int, const int, const real_t *, const real_t *, real_t *) VectorMassAssembleDiagonalPAType
void(*)(const int, const int, const Array< real_t > &, const Vector &, const Vector &, Vector &, const int, const int) VectorMassAddMultPAType
real_t u(const Vector &xvec)
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
internal::DofQuadLimits_CUDA DofQuadLimits
Maximum number of 1D DOFs or quadrature points for the architecture currently being compiled for (use...
void forall_2D(int N, int X, int Y, lambda &&body)
void forall_3D(int N, int X, int Y, int Z, lambda &&body)