15#ifndef MFEM_QUADINTERP_GRAD
16#define MFEM_QUADINTERP_GRAD
30namespace quadrature_interpolator
33template <QVectorLayout Q_LAYOUT,
bool GRAD_PHYS>
34void Derivatives1D(
const int NE,
const real_t *b_,
const real_t *g_,
36 const int sdim,
const int vdim,
const int d1d,
const int q1d)
38 MFEM_CONTRACT_VAR(b_);
39 const int SDIM = GRAD_PHYS ? sdim : 1;
40 const auto g =
Reshape(g_, q1d, d1d);
42 const auto x =
Reshape(x_, d1d, vdim, NE);
49 for (
int c = 0; c < vdim; c++)
51 for (
int q = 0; q < q1d; q++)
53 real_t du[3] = {0.0, 0.0, 0.0};
54 for (
int d = 0; d < d1d; d++)
56 du[0] += g(q, d) * x(d, c, e);
60 if (
SDIM == 1) { du[0] /= j(q, 0, e); }
63 const real_t Jloc[2] = {j(q,0,e), j(q,1,e)};
66 const real_t U = Jinv[0]*du[0];
67 const real_t V = Jinv[1]*du[0];
73 const real_t Jloc[3] = {j(q,0,e), j(q,1,e), j(q,2,e)};
76 const real_t U = Jinv[0]*du[0];
77 const real_t V = Jinv[1]*du[0];
78 const real_t W = Jinv[2]*du[0];
84 for (
int d = 0; d <
SDIM; ++d)
95template <
QVectorLayout Q_LAYOUT,
bool GRAD_PHYS,
int T_VDIM = 0,
int T_D1D = 0,
96 int T_Q1D = 0,
int T_NBZ = 1>
97void Derivatives2D(
const int NE,
const real_t *b_,
const real_t *g_,
99 const int sdim = 2,
const int vdim = 0,
const int d1d = 0,
102 const int D1D = T_D1D ? T_D1D : d1d;
103 const int Q1D = T_Q1D ? T_Q1D : q1d;
104 const int VDIM = T_VDIM ? T_VDIM : vdim;
105 const int SDIM = GRAD_PHYS ? sdim : 2;
106 static constexpr int NBZ = T_NBZ ? T_NBZ : 1;
108 const auto b =
Reshape(b_, Q1D, D1D);
109 const auto g =
Reshape(g_, Q1D, D1D);
111 const auto x =
Reshape(x_, D1D, D1D, VDIM, NE);
118 const int D1D = T_D1D ? T_D1D : d1d;
119 const int Q1D = T_Q1D ? T_Q1D : q1d;
120 const int VDIM = T_VDIM ? T_VDIM : vdim;
121 constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
122 constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
124 const int tidz = MFEM_THREAD_ID(z);
125 MFEM_SHARED
real_t BG[2][MQ1*MD1];
126 kernels::internal::LoadBG<MD1,MQ1>(D1D,Q1D,
b,g,BG);
130 MFEM_SHARED
real_t XY[NBZ][MD1*MD1];
131 DeviceTensor<2> X((
real_t*)(XY+tidz), D1D, D1D);
133 MFEM_SHARED
real_t s_DQ[2][NBZ][MD1*MQ1];
134 DeviceTensor<2> DQ0(s_DQ[0][tidz], D1D, Q1D);
135 DeviceTensor<2> DQ1(s_DQ[1][tidz], D1D, Q1D);
137 for (
int c = 0; c < VDIM; ++c)
139 kernels::internal::LoadX<MD1,NBZ>(e,D1D,c,x,XY);
140 MFEM_FOREACH_THREAD(dy,y,D1D)
142 MFEM_FOREACH_THREAD(qx,x,Q1D)
146 for (
int dx = 0; dx < D1D; ++dx)
148 const real_t input = X(dx,dy);
149 u += input * B(dx,qx);
150 v += input * G(dx,qx);
157 MFEM_FOREACH_THREAD(qy,y,Q1D)
159 MFEM_FOREACH_THREAD(qx,x,Q1D)
161 real_t du[3] = {0.0, 0.0, 0.0};
162 for (
int dy = 0; dy < D1D; ++dy)
164 du[0] += DQ1(dy,qx) * B(dy,qy);
165 du[1] += DQ0(dy,qx) * G(dy,qy);
172 Jloc[0] = j(qx,qy,0,0,e);
173 Jloc[1] = j(qx,qy,1,0,e);
174 Jloc[2] = j(qx,qy,0,1,e);
175 Jloc[3] = j(qx,qy,1,1,e);
177 const real_t U = Jinv[0]*du[0] + Jinv[1]*du[1];
178 const real_t V = Jinv[2]*du[0] + Jinv[3]*du[1];
185 Jloc[0] = j(qx,qy,0,0,e);
186 Jloc[1] = j(qx,qy,1,0,e);
187 Jloc[2] = j(qx,qy,2,0,e);
188 Jloc[3] = j(qx,qy,0,1,e);
189 Jloc[4] = j(qx,qy,1,1,e);
190 Jloc[5] = j(qx,qy,2,1,e);
192 const real_t U = Jinv[0]*du[0] + Jinv[1]*du[1];
193 const real_t V = Jinv[2]*du[0] + Jinv[3]*du[1];
194 const real_t W = Jinv[4]*du[0] + Jinv[5]*du[1];
200 for (
int d = 0; d <
SDIM; ++d)
204 y(c,d,qx,qy,e) = du[d];
208 y(qx,qy,c,d,e) = du[d];
219template <
QVectorLayout Q_LAYOUT,
bool GRAD_PHYS,
int T_VDIM = 0,
int T_D1D = 0,
221void Derivatives3D(
const int NE,
const real_t *b_,
const real_t *g_,
223 const int sdim = 3,
const int vdim = 0,
const int d1d = 0,
226 const int D1D = T_D1D ? T_D1D : d1d;
227 const int Q1D = T_Q1D ? T_Q1D : q1d;
228 const int VDIM = T_VDIM ? T_VDIM : vdim;
230 const auto b =
Reshape(b_, Q1D, D1D);
231 const auto g =
Reshape(g_, Q1D, D1D);
232 const auto j =
Reshape(j_, Q1D, Q1D, Q1D, 3, 3, NE);
233 const auto x =
Reshape(x_, D1D, D1D, D1D, VDIM, NE);
235 Reshape(y_, Q1D, Q1D, Q1D, VDIM, 3, NE):
236 Reshape(y_, VDIM, 3, Q1D, Q1D, Q1D, NE);
240 const int D1D = T_D1D ? T_D1D : d1d;
241 const int Q1D = T_Q1D ? T_Q1D : q1d;
242 const int VDIM = T_VDIM ? T_VDIM : vdim;
243 constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_INTERP_1D;
244 constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_INTERP_1D;
246 MFEM_SHARED
real_t BG[2][MQ1*MD1];
247 kernels::internal::LoadBG<MD1,MQ1>(D1D,Q1D,
b,g,BG);
251 constexpr int MDQ = MD1 > MQ1 ? MD1 : MQ1;
252 MFEM_SHARED
real_t sm0[3][MD1*MD1*MDQ];
253 MFEM_SHARED
real_t sm1[3][MD1*MQ1*MQ1];
254 DeviceTensor<3> X(sm0[2], D1D, D1D, D1D);
255 DeviceTensor<3> DDQ0(sm0[0], D1D, D1D, Q1D);
256 DeviceTensor<3> DDQ1(sm0[1], D1D, D1D, Q1D);
257 DeviceTensor<3> DQQ0(sm1[0], D1D, Q1D, Q1D);
258 DeviceTensor<3> DQQ1(sm1[1], D1D, Q1D, Q1D);
259 DeviceTensor<3> DQQ2(sm1[2], D1D, Q1D, Q1D);
261 for (
int c = 0; c < VDIM; ++c)
263 kernels::internal::LoadX(e,D1D,c,x,X);
264 MFEM_FOREACH_THREAD(dz,z,D1D)
266 MFEM_FOREACH_THREAD(dy,y,D1D)
268 MFEM_FOREACH_THREAD(qx,x,Q1D)
272 for (
int dx = 0; dx < D1D; ++dx)
274 const real_t input = X(dx,dy,dz);
275 u += input * B(dx,qx);
276 v += input * G(dx,qx);
284 MFEM_FOREACH_THREAD(dz,z,D1D)
286 MFEM_FOREACH_THREAD(qy,y,Q1D)
288 MFEM_FOREACH_THREAD(qx,x,Q1D)
293 for (
int dy = 0; dy < D1D; ++dy)
295 u += DDQ1(dz,dy,qx) * B(dy,qy);
296 v += DDQ0(dz,dy,qx) * G(dy,qy);
297 w += DDQ0(dz,dy,qx) * B(dy,qy);
306 MFEM_FOREACH_THREAD(qz,z,Q1D)
308 MFEM_FOREACH_THREAD(qy,y,Q1D)
310 MFEM_FOREACH_THREAD(qx,x,Q1D)
315 for (
int dz = 0; dz < D1D; ++dz)
317 u += DQQ0(dz,qy,qx) * B(dz,qz);
318 v += DQQ1(dz,qy,qx) * B(dz,qz);
319 w += DQQ2(dz,qy,qx) * G(dz,qz);
324 for (
int col = 0; col < 3; col++)
326 for (
int row = 0; row < 3; row++)
328 Jloc[row+3*col] = j(qx,qy,qz,row,col,e);
332 const real_t U = Jinv[0]*
u + Jinv[1]*v + Jinv[2]*w;
333 const real_t V = Jinv[3]*
u + Jinv[4]*v + Jinv[5]*w;
334 const real_t W = Jinv[6]*
u + Jinv[7]*v + Jinv[8]*w;
339 y(c,0,qx,qy,qz,e) =
u;
340 y(c,1,qx,qy,qz,e) = v;
341 y(c,2,qx,qy,qz,e) = w;
345 y(qx,qy,qz,c,0,e) =
u;
346 y(qx,qy,qz,c,1,e) = v;
347 y(qx,qy,qz,c,2,e) = w;
357template <QVectorLayout Q_LAYOUT,
bool GRAD_PHYS>
358void CollocatedDerivatives1D(
const int NE,
const real_t *g_,
const real_t *j_,
360 const int vdim,
const int d1d)
362 Derivatives1D<Q_LAYOUT, GRAD_PHYS>(
363 NE,
nullptr, g_, j_, x_, y_, sdim, vdim, d1d, d1d);
367template <
QVectorLayout Q_LAYOUT,
bool GRAD_PHYS,
int T_VDIM = 0,
int T_D1D = 0,
369void CollocatedDerivatives2D(
const int NE,
const real_t *g_,
const real_t *j_,
371 const int vdim = 0,
const int d1d = 0)
373 const int D1D = T_D1D ? T_D1D : d1d;
374 const int VDIM = T_VDIM ? T_VDIM : vdim;
375 const int SDIM = GRAD_PHYS ? sdim : 2;
376 static constexpr int NBZ = T_NBZ ? T_NBZ : 1;
378 const auto g =
Reshape(g_, D1D, D1D);
380 const auto x =
Reshape(x_, D1D, D1D, VDIM, NE);
387 const int D1D = T_D1D ? T_D1D : d1d;
388 const int VDIM = T_VDIM ? T_VDIM : vdim;
389 constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
391 const int tidz = MFEM_THREAD_ID(z);
393 MFEM_SHARED
real_t XY[NBZ][MD1*MD1];
394 DeviceTensor<2> X((
real_t*)(XY+tidz), D1D, D1D);
396 for (
int c = 0; c < VDIM; ++c)
398 kernels::internal::LoadX<MD1,NBZ>(e,D1D,c,x,XY);
399 MFEM_FOREACH_THREAD(dy,y,D1D)
401 MFEM_FOREACH_THREAD(dx,x,D1D)
406 for (
int dxy = 0; dxy < D1D; ++dxy)
408 u += X(dxy, dy) * g(dx,dxy);
409 v += X(dx, dxy) * g(dy,dxy);
417 Jloc[0] = j(dx,dy,0,0,e);
418 Jloc[1] = j(dx,dy,1,0,e);
419 Jloc[2] = j(dx,dy,0,1,e);
420 Jloc[3] = j(dx,dy,1,1,e);
422 const real_t U = Jinv[0]*
u + Jinv[1]*v;
423 const real_t V = Jinv[2]*
u + Jinv[3]*v;
430 Jloc[0] = j(dx,dy,0,0,e);
431 Jloc[1] = j(dx,dy,1,0,e);
432 Jloc[2] = j(dx,dy,2,0,e);
433 Jloc[3] = j(dx,dy,0,1,e);
434 Jloc[4] = j(dx,dy,1,1,e);
435 Jloc[5] = j(dx,dy,2,1,e);
437 const real_t U = Jinv[0]*
u + Jinv[1]*v;
438 const real_t V = Jinv[2]*
u + Jinv[3]*v;
439 const real_t W = Jinv[4]*
u + Jinv[5]*v;
450 if (
SDIM == 3) { y(c,2,dx,dy,e) = w; }
456 if (
SDIM == 3) { y(dx,dy,c,2,e) = w; }
466template <QVectorLayout Q_LAYOUT,
bool GRAD_PHYS,
int T_VDIM = 0,
int T_D1D = 0>
467void CollocatedDerivatives3D(
const int NE,
const real_t *g_,
const real_t *j_,
469 const int vdim = 0,
const int d1d = 0)
471 MFEM_VERIFY(sdim == 3,
"");
473 const int D1D = T_D1D ? T_D1D : d1d;
474 const int VDIM = T_VDIM ? T_VDIM : vdim;
476 const auto g =
Reshape(g_, D1D, D1D);
477 const auto j =
Reshape(j_, D1D, D1D, D1D, 3, 3, NE);
478 const auto x =
Reshape(x_, D1D, D1D, D1D, VDIM, NE);
480 Reshape(y_, D1D, D1D, D1D, VDIM, 3, NE):
481 Reshape(y_, VDIM, 3, D1D, D1D, D1D, NE);
485 const int D1D = T_D1D ? T_D1D : d1d;
486 const int VDIM = T_VDIM ? T_VDIM : vdim;
487 constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_INTERP_1D;
489 MFEM_SHARED
real_t uvw[MD1*MD1*MD1];
490 DeviceTensor<3> X(uvw, D1D, D1D, D1D);
492 for (
int c = 0; c < VDIM; ++c)
494 kernels::internal::LoadX(e,D1D,c,x,X);
495 MFEM_FOREACH_THREAD(dz,z,D1D)
497 MFEM_FOREACH_THREAD(dy,y,D1D)
499 MFEM_FOREACH_THREAD(dx,x,D1D)
504 for (
int dxyz = 0; dxyz < D1D; ++dxyz)
506 u += X(dxyz, dy, dz) * g(dx,dxyz);
507 v += X(dx, dxyz, dz) * g(dy,dxyz);
508 w += X(dx, dy, dxyz) * g(dz,dxyz);
514 for (
int col = 0; col < 3; col++)
516 for (
int row = 0; row < 3; row++)
518 Jloc[row+3*col] = j(dx,dy,dz,row,col,e);
522 const real_t U = Jinv[0]*
u + Jinv[1]*v + Jinv[2]*w;
523 const real_t V = Jinv[3]*
u + Jinv[4]*v + Jinv[5]*w;
524 const real_t W = Jinv[6]*
u + Jinv[7]*v + Jinv[8]*w;
529 y(c,0,dx,dy,dz,e) =
u;
530 y(c,1,dx,dy,dz,e) = v;
531 y(c,2,dx,dy,dz,e) = w;
535 y(dx,dy,dz,c,0,e) =
u;
536 y(dx,dy,dz,c,1,e) = v;
537 y(dx,dy,dz,c,2,e) = w;
557QuadratureInterpolator::GradKernels::Kernel()
559 if constexpr (
DIM == 1) {
return internal::quadrature_interpolator::Derivatives1D<Q_LAYOUT, GRAD_PHYS>; }
560 else if constexpr (
DIM == 2) {
return internal::quadrature_interpolator::Derivatives2D<Q_LAYOUT, GRAD_PHYS, VDIM, D1D, Q1D, NBZ>; }
561 else if constexpr (
DIM == 3) {
return internal::quadrature_interpolator::Derivatives3D<Q_LAYOUT, GRAD_PHYS, VDIM, D1D, Q1D>; }
568QuadratureInterpolator::CollocatedGradKernels::Kernel()
570 if constexpr (
DIM == 1) {
return internal::quadrature_interpolator::CollocatedDerivatives1D<Q_LAYOUT, GRAD_PHYS>; }
571 else if constexpr (
DIM == 2) {
return internal::quadrature_interpolator::CollocatedDerivatives2D<Q_LAYOUT, GRAD_PHYS, VDIM, D1D, NBZ>; }
572 else if constexpr (
DIM == 3) {
return internal::quadrature_interpolator::CollocatedDerivatives3D<Q_LAYOUT, GRAD_PHYS, VDIM, D1D>; }
void(*)(const int ne, const real_t *B, const real_t *G, const real_t *J, const real_t *e_vec, real_t *q_der, const int s_dim, const int v_dim, const int nd, const int nq) GradKernelType
void(*)(const int ne, const real_t *G, const real_t *J, const real_t *e_vec, real_t *q_der, const int sdim, const int vdim, const int d1d) CollocatedGradKernelType
MFEM_HOST_DEVICE void CalcInverse(const T *data, T *inv_data)
Return the inverse of a matrix with given size and data into the matrix with data inv_data.
MFEM_HOST_DEVICE void CalcLeftInverse< 2, 1 >(const real_t *d, real_t *left_inv)
MFEM_HOST_DEVICE void CalcLeftInverse< 3, 2 >(const real_t *d, real_t *left_inv)
MFEM_HOST_DEVICE void CalcLeftInverse< 3, 1 >(const real_t *d, real_t *left_inv)
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.
void forall_2D_batch(int N, int X, int Y, int BZ, lambda &&body)
void forall_3D(int N, int X, int Y, int Z, lambda &&body)
QVectorLayout
Type describing possible layouts for Q-vectors.
void forall(int N, lambda &&body)
DeviceTensor< 2, real_t > DeviceMatrix