30template<
int T_TR_D1D = 0,
int T_TE_D1D = 0,
int T_Q1D = 0>
31inline void SmemPADivergenceApply2D(
const int NE,
32 const Array<real_t> &b_,
33 const Array<real_t> &g_,
34 const Array<real_t> &bt_,
42 const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
43 const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
44 const int Q1D = T_Q1D ? T_Q1D : q1d;
50 const auto B = b_.Read(), G = g_.Read(), Bt = bt_.Read();
51 const auto Q =
Reshape(q_.Read(), Q1D, Q1D, 2, 2, NE);
52 const auto X =
Reshape(x_.Read(), TR_D1D, TR_D1D, 2, NE);
53 auto Y =
Reshape(y_.ReadWrite(), TE_D1D, TE_D1D, 1, NE);
57 constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
59 MFEM_SHARED
real_t smem[MQ1][MQ1];
60 MFEM_SHARED
real_t sB[MQ1][MQ1], sG[MQ1][MQ1];
62 kernels::internal::vd_regs2d_t<2, 2, MQ1> g0, g1;
63 kernels::internal::v_regs2d_t<1, MQ1> r0, r1;
65 kernels::internal::LoadMatrix(TR_D1D, Q1D, B, sB);
66 kernels::internal::LoadMatrix(TR_D1D, Q1D, G, sG);
68 kernels::internal::LoadDofs2d(e, TR_D1D, X, g0);
69 kernels::internal::Grad2d(TR_D1D, Q1D, smem, sB, sG, g0, g1);
71 MFEM_FOREACH_THREAD_DIRECT(qy, y, Q1D)
73 MFEM_FOREACH_THREAD_DIRECT(qx, x, Q1D)
76 g1[0][0][qy][qx] * Q(qx, qy, 0, 0, e) +
77 g1[0][1][qy][qx] * Q(qx, qy, 1, 0, e) +
78 g1[1][0][qy][qx] * Q(qx, qy, 0, 1, e) +
79 g1[1][1][qy][qx] * Q(qx, qy, 1, 1, e);
84 kernels::internal::LoadMatrix<MQ1,true>(TE_D1D, Q1D, Bt, sB);
85 kernels::internal::EvalTranspose2d(TE_D1D, Q1D, smem, sB, r0, r1);
86 kernels::internal::WriteDofs2d(e, TE_D1D, r1, Y);
91template<
int T_TR_D1D = 0,
int T_TE_D1D = 0,
int T_Q1D = 0>
92inline void SmemPADivergenceApplyTranspose2D(
const int NE,
93 const Array<real_t> &bt,
94 const Array<real_t> >,
95 const Array<real_t> &
b,
100 const int te_d1d = 0,
103 const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
104 const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
105 const int Q1D = T_Q1D ? T_Q1D : q1d;
111 const auto Bt = bt.Read(), Gt = gt.Read(), B =
b.Read();
112 const auto Q =
Reshape(q_.Read(), Q1D, Q1D, 2, 2, NE);
113 const auto X =
Reshape(x_.Read(), TE_D1D, TE_D1D, 1, NE);
114 auto Y =
Reshape(y_.ReadWrite(), TR_D1D, TR_D1D, 2, NE);
118 constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
120 MFEM_SHARED
real_t smem[MQ1][MQ1];
121 MFEM_SHARED
real_t sB[MQ1][MQ1], sG[MQ1][MQ1];
123 kernels::internal::v_regs2d_t<1, MQ1> r0, r1;
124 kernels::internal::vd_regs2d_t<2, 2, MQ1> g0, g1;
126 kernels::internal::LoadMatrix(TE_D1D, Q1D, B, sB);
127 kernels::internal::LoadDofs2d(e, TE_D1D, X, r0);
128 kernels::internal::Eval2d(TE_D1D, Q1D, smem, sB, r0, r1);
130 MFEM_FOREACH_THREAD_DIRECT(qy, y, Q1D)
132 MFEM_FOREACH_THREAD_DIRECT(qx, x, Q1D)
134 g0[0][0][qy][qx] = r1[0][qy][qx] * Q(qx, qy, 0, 0, e);
135 g0[0][1][qy][qx] = r1[0][qy][qx] * Q(qx, qy, 1, 0, e);
136 g0[1][0][qy][qx] = r1[0][qy][qx] * Q(qx, qy, 0, 1, e);
137 g0[1][1][qy][qx] = r1[0][qy][qx] * Q(qx, qy, 1, 1, e);
142 kernels::internal::LoadMatrix<MQ1,true>(TR_D1D, Q1D, Bt, sB);
143 kernels::internal::LoadMatrix<MQ1,true>(TR_D1D, Q1D, Gt, sG);
144 kernels::internal::GradTranspose2d(TR_D1D, Q1D, smem, sB, sG, g0, g1);
145 kernels::internal::WriteDofs2d(e, TR_D1D, g1, Y);
150template<
int T_TR_D1D = 0,
int T_TE_D1D = 0,
int T_Q1D = 0>
151inline void SmemPADivergenceApplyTranspose3D(
const int NE,
152 const Array<real_t> &bt,
153 const Array<real_t> >,
154 const Array<real_t> &
b,
162 const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
163 const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
164 const int Q1D = T_Q1D ? T_Q1D : q1d;
170 const auto Bt = bt.Read(), Gt = gt.Read(), B =
b.Read();
171 const auto Q =
Reshape(q_.Read(), Q1D, Q1D, Q1D, 3, 3, NE);
172 const auto X =
Reshape(x_.Read(), TE_D1D, TE_D1D, TE_D1D, 1, NE);
173 auto Y =
Reshape(y_.ReadWrite(), TR_D1D, TR_D1D, TR_D1D, 3, NE);
177 constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
179 MFEM_SHARED
real_t smem[MQ1][MQ1];
180 MFEM_SHARED
real_t sB[MQ1][MQ1], sG[MQ1][MQ1];
182 kernels::internal::v_regs3d_t<1, MQ1> r0, r1;
183 kernels::internal::vd_regs3d_t<3, 3, MQ1> g0, g1;
185 kernels::internal::LoadMatrix(TE_D1D, Q1D, B, sB);
186 kernels::internal::LoadDofs3d(e, TE_D1D, X, r0);
187 kernels::internal::Eval3d(TE_D1D, Q1D, smem, sB, r0, r1);
189 for (
int qz = 0; qz < Q1D; qz++)
191 MFEM_FOREACH_THREAD_DIRECT(qy, y, Q1D)
193 MFEM_FOREACH_THREAD_DIRECT(qx, x, Q1D)
195 const auto r = r1[0][qz][qy][qx];
196 g0[0][0][qz][qy][qx] = r * Q(qx, qy, qz, 0, 0, e);
197 g0[0][1][qz][qy][qx] = r * Q(qx, qy, qz, 1, 0, e);
198 g0[0][2][qz][qy][qx] = r * Q(qx, qy, qz, 2, 0, e);
200 g0[1][0][qz][qy][qx] = r * Q(qx, qy, qz, 0, 1, e);
201 g0[1][1][qz][qy][qx] = r * Q(qx, qy, qz, 1, 1, e);
202 g0[1][2][qz][qy][qx] = r * Q(qx, qy, qz, 2, 1, e);
204 g0[2][0][qz][qy][qx] = r * Q(qx, qy, qz, 0, 2, e);
205 g0[2][1][qz][qy][qx] = r * Q(qx, qy, qz, 1, 2, e);
206 g0[2][2][qz][qy][qx] = r * Q(qx, qy, qz, 2, 2, e);
212 kernels::internal::LoadMatrix<MQ1,true>(TR_D1D, Q1D, Bt, sB);
213 kernels::internal::LoadMatrix<MQ1,true>(TR_D1D, Q1D, Gt, sG);
214 kernels::internal::GradTranspose3d(TR_D1D, Q1D, smem, sB, sG, g0, g1);
215 kernels::internal::WriteDofs3d(e, TR_D1D, g1, Y);
220template<
int T_TR_D1D = 0,
int T_TE_D1D = 0,
int T_Q1D = 0>
221inline void SmemPADivergenceApply3D(
const int NE,
222 const Array<real_t> &b_,
223 const Array<real_t> &g_,
224 const Array<real_t> &bt_,
228 const int tr_d1d = 0,
229 const int te_d1d = 0,
232 const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
233 const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
234 const int Q1D = T_Q1D ? T_Q1D : q1d;
240 const auto B = b_.Read(), G = g_.Read(), Bt = bt_.Read();
241 const auto Q =
Reshape(q_.Read(), Q1D, Q1D, Q1D, 3,3, NE);
242 const auto X =
Reshape(x_.Read(), TR_D1D, TR_D1D, TR_D1D, 3, NE);
243 auto Y =
Reshape(y_.ReadWrite(), TE_D1D, TE_D1D, TE_D1D, 1, NE);
247 constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
249 MFEM_SHARED
real_t smem[MQ1][MQ1];
250 MFEM_SHARED
real_t sB[MQ1][MQ1], sG[MQ1][MQ1];
252 kernels::internal::vd_regs3d_t<3, 3, MQ1> g0, g1;
253 kernels::internal::v_regs3d_t<1, MQ1> r0, r1;
255 kernels::internal::LoadMatrix(TR_D1D, Q1D, B, sB);
256 kernels::internal::LoadMatrix(TR_D1D, Q1D, G, sG);
258 kernels::internal::LoadDofs3d(e, TR_D1D, X, g0);
259 kernels::internal::Grad3d(TR_D1D, Q1D, smem, sB, sG, g0, g1);
261 for (
int qz = 0; qz < Q1D; qz++)
263 MFEM_FOREACH_THREAD_DIRECT(qy, y, Q1D)
265 MFEM_FOREACH_THREAD_DIRECT(qx, x, Q1D)
269 g1[0][0][qz][qy][qx] * Q(qx, qy, qz, 0, 0, e) +
270 g1[0][1][qz][qy][qx] * Q(qx, qy, qz, 1, 0, e) +
271 g1[0][2][qz][qy][qx] * Q(qx, qy, qz, 2, 0, e) +
273 g1[1][0][qz][qy][qx] * Q(qx, qy, qz, 0, 1, e) +
274 g1[1][1][qz][qy][qx] * Q(qx, qy, qz, 1, 1, e) +
275 g1[1][2][qz][qy][qx] * Q(qx, qy, qz, 2, 1, e) +
277 g1[2][0][qz][qy][qx] * Q(qx, qy, qz, 0, 2, e) +
278 g1[2][1][qz][qy][qx] * Q(qx, qy, qz, 1, 2, e) +
279 g1[2][2][qz][qy][qx] * Q(qx, qy, qz, 2, 2, e);
285 kernels::internal::LoadMatrix<MQ1, true>(TE_D1D, Q1D, Bt, sB);
286 kernels::internal::EvalTranspose3d(TE_D1D, Q1D, smem, sB, r0, r1);
287 kernels::internal::WriteDofs3d(e, TE_D1D, r1, Y);
293template<
int DIM,
int T_TR_D1D,
int T_TE_D1D,
int T_Q1D>
295VectorDivergenceIntegrator::VectorDivergenceAddMultPA::Kernel()
297 static_assert(T_TR_D1D <= T_Q1D && T_TE_D1D <= T_Q1D);
298 if constexpr (
DIM == 2)
300 return internal::SmemPADivergenceApply2D<T_TR_D1D, T_TE_D1D, T_Q1D>;
302 else if constexpr (
DIM == 3)
304 return internal::SmemPADivergenceApply3D<T_TR_D1D, T_TE_D1D, T_Q1D>;
306 MFEM_ABORT(
"Unsupported kernel");
310VectorDivergenceIntegrator::VectorDivergenceAddMultPA::Fallback
311(
int dim,
int tr_d1d,
int te_d1d,
int q1d)
313 MFEM_VERIFY(tr_d1d <= q1d && te_d1d <= q1d,
"");
319 return internal::SmemPADivergenceApply2D;
323 return internal::SmemPADivergenceApply3D;
325 MFEM_ABORT(
"Unsupported kernel");
328template<
int DIM,
int T_TR_D1D,
int T_TE_D1D,
int T_Q1D>
330VectorDivergenceIntegrator::VectorDivergenceAddMultTransposePA::Kernel()
332 static_assert(T_TR_D1D <= T_Q1D && T_TE_D1D <= T_Q1D);
333 if constexpr (
DIM == 2)
335 return internal::SmemPADivergenceApplyTranspose2D<T_TR_D1D, T_TE_D1D, T_Q1D>;
337 else if constexpr (
DIM == 3)
339 return internal::SmemPADivergenceApplyTranspose3D<T_TR_D1D, T_TE_D1D, T_Q1D>;
341 MFEM_ABORT(
"Unsupported kernel");
345VectorDivergenceIntegrator::VectorDivergenceAddMultTransposePA::Fallback
346(
int dim,
int tr_d1d,
int te_d1d,
int q1d)
348 MFEM_VERIFY(tr_d1d <= q1d && te_d1d <= q1d,
"");
354 return internal::SmemPADivergenceApplyTranspose2D;
358 return internal::SmemPADivergenceApplyTranspose3D;
360 MFEM_ABORT(
"Unsupported kernel");
void(*)(const int ne, const Array< real_t > &bt, const Array< real_t > >, const Array< real_t > &b, const Vector &q, const Vector &x, Vector &y, const int tr_d1d, const int te_d1d, const int q1d) VectorDivergenceAddMultTransposePAType
void(*)(const int ne, const Array< real_t > &b, const Array< real_t > &g, const Array< real_t > &bt, const Vector &op, const Vector &x, Vector &y, const int tr_d1d, const int te_d1d, const int q1d) VectorDivergenceAddMultPAType
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
void forall_2D(int N, int X, int Y, lambda &&body)
static const DeviceDofQuadLimits & Get()
Return a const reference to the DeviceDofQuadLimits singleton.