28template<
int T_D1D = 0,
int T_Q1D = 0>
29inline void SmemPAConvectionNLApply2D(
const int NE,
38 static constexpr int VDIM = 2,
DIM = 2;
39 const int D1D = T_D1D ? T_D1D : d1d;
40 const int Q1D = T_Q1D ? T_Q1D : q1d;
43 const auto G =
Reshape(g, Q1D, D1D);
45 const auto X =
Reshape(x, D1D, D1D, VDIM, NE);
46 auto Y =
Reshape(y, D1D, D1D, VDIM, NE);
50 constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
51 constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
53 MFEM_SHARED
real_t smem[MQ1][MQ1], sB[MD1][MQ1], sG[MD1][MQ1];
55 kernels::internal::vd_regs2d_t<VDIM, DIM, MQ1> g0, g1;
56 kernels::internal::v_regs2d_t<VDIM, MQ1> r0, r1;
57 kernels::internal::v_regs2d_t<VDIM, MQ1> s0, s1;
59 kernels::internal::LoadMatrix(D1D, Q1D, B, sB);
60 kernels::internal::LoadMatrix(D1D, Q1D, G, sG);
62 kernels::internal::LoadDofs2d(e, D1D, X, r0);
63 kernels::internal::Eval2d(D1D, Q1D, smem, sB, r0, r1);
64 kernels::internal::LoadDofs2d(e, D1D, X, g0);
65 kernels::internal::Grad2d(D1D, Q1D, smem, sB, sG, g0, g1);
67 MFEM_FOREACH_THREAD_DIRECT(qy, y, Q1D)
69 MFEM_FOREACH_THREAD_DIRECT(qx, x, Q1D)
71 const future::tensor<real_t, 2> U =
73 r1[0][qy][qx], r1[1][qy][qx]
75 const future::tensor<real_t, 2,2> gradU = {{
76 {g1[0][0][qy][qx], g1[1][0][qy][qx]},
77 {g1[0][1][qy][qx], g1[1][1][qy][qx]},
80 const future::tensor<real_t, 2,2> Q = {{
81 {A(0,0,qx,qy,e), A(1,0,qx,qy,e)},
82 {A(0,1,qx,qy,e), A(1,1,qx,qy,e)},
85 const future::tensor<real_t, 2> conv =
transpose(gradU) * (Q * U);
86 s0[0][qy][qx] = conv[0];
87 s0[1][qy][qx] = conv[1];
91 kernels::internal::EvalTranspose2d(D1D, Q1D, smem, sB, s0, s1);
92 kernels::internal::WriteDofs2d(e, D1D, s1, Y);
97template<
int T_D1D = 0,
int T_Q1D = 0>
98inline void SmemPAConvectionNLApply3D(
const int NE,
107 static constexpr int VDIM = 3,
DIM = 3;
108 const int D1D = T_D1D ? T_D1D : d1d;
109 const int Q1D = T_Q1D ? T_Q1D : q1d;
111 const auto B =
Reshape(
b, Q1D, D1D);
112 const auto G =
Reshape(g, Q1D, D1D);
113 const auto A =
Reshape(
a, VDIM,
DIM, Q1D, Q1D, Q1D, NE);
114 const auto X =
Reshape(x, D1D, D1D, D1D, VDIM, NE);
115 auto Y =
Reshape(y, D1D, D1D, D1D, VDIM, NE);
119 constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
120 constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
122 MFEM_SHARED
real_t smem[MQ1][MQ1], sB[MD1][MQ1], sG[MD1][MQ1];
124 kernels::internal::vd_regs3d_t<VDIM, DIM, MQ1> g0, g1;
125 kernels::internal::v_regs3d_t<VDIM, MQ1> r0, r1;
126 kernels::internal::v_regs3d_t<VDIM, MQ1> s0, s1;
128 kernels::internal::LoadMatrix(D1D, Q1D, B, sB);
129 kernels::internal::LoadMatrix(D1D, Q1D, G, sG);
131 kernels::internal::LoadDofs3d(e, D1D, X, r0);
132 kernels::internal::Eval3d(D1D, Q1D, smem, sB, r0, r1);
133 kernels::internal::LoadDofs3d(e, D1D, X, g0);
134 kernels::internal::Grad3d(D1D, Q1D, smem, sB, sG, g0, g1);
136 for (
int qz = 0; qz < Q1D; qz++)
138 MFEM_FOREACH_THREAD_DIRECT(qy, y, Q1D)
140 MFEM_FOREACH_THREAD_DIRECT(qx, x, Q1D)
142 const future::tensor<real_t, 3> U =
144 r1[0][qz][qy][qx], r1[1][qz][qy][qx], r1[2][qz][qy][qx]
146 const future::tensor<real_t, 3,3> gradU = {{
147 {g1[0][0][qz][qy][qx], g1[1][0][qz][qy][qx], g1[2][0][qz][qy][qx]},
148 {g1[0][1][qz][qy][qx], g1[1][1][qz][qy][qx], g1[2][1][qz][qy][qx]},
149 {g1[0][2][qz][qy][qx], g1[1][2][qz][qy][qx], g1[2][2][qz][qy][qx]}
152 const future::tensor<real_t, 3,3> Q = {{
153 {A(0,0,qx,qy,qz,e), A(1,0,qx,qy,qz,e), A(2,0,qx,qy,qz,e)},
154 {A(0,1,qx,qy,qz,e), A(1,1,qx,qy,qz,e), A(2,1,qx,qy,qz,e)},
155 {A(0,2,qx,qy,qz,e), A(1,2,qx,qy,qz,e), A(2,2,qx,qy,qz,e)}
158 const future::tensor<real_t, 3> conv =
transpose(gradU) * (Q * U);
159 s0[0][qz][qy][qx] = conv[0];
160 s0[1][qz][qy][qx] = conv[1];
161 s0[2][qz][qy][qx] = conv[2];
166 kernels::internal::EvalTranspose3d(D1D, Q1D, smem, sB, s0, s1);
167 kernels::internal::WriteDofs3d(e, D1D, s1, Y);
173template<
int DIM,
int T_D1D,
int T_Q1D>
175VectorConvectionNLFIntegrator::AddMultPAKernels::Kernel()
177 static_assert(T_D1D <= T_Q1D,
"d1d > q1d is not supported");
178 if constexpr (
DIM == 2)
180 return internal::SmemPAConvectionNLApply2D<T_D1D, T_Q1D>;
182 else if constexpr (
DIM == 3)
184 return internal::SmemPAConvectionNLApply3D<T_D1D, T_Q1D>;
186 MFEM_ABORT(
"Unsupported kernel");
190VectorConvectionNLFIntegrator::AddMultPAKernels::Fallback
191(
int dim,
int d1d,
int q1d)
193 MFEM_VERIFY(d1d <= q1d, "d1d > q1d is not supported
");
194 MFEM_VERIFY(d1d <= DeviceDofQuadLimits::Get().MAX_D1D, "");
195 MFEM_VERIFY(q1d <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
198 return internal::SmemPAConvectionNLApply2D<>;
202 return internal::SmemPAConvectionNLApply3D<>;
204 MFEM_ABORT("Unsupported kernel
");
void(*)(const int ne, const real_t *B, const real_t *G, const real_t *A, const real_t *x, real_t *y, const int d1d, const int q1d) AddMultPAType
MFEM_HOST_DEVICE tensor< T, n, m > transpose(const tensor< T, m, n > &A)
Returns the transpose of the matrix.
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)