12#ifndef MFEM_BILININTEG_HDIV_KERNELS_HPP
13#define MFEM_BILININTEG_HDIV_KERNELS_HPP
32void PAHdivMassSetup2D(
const int Q1D,
35 const Array<real_t> &w,
41void PAHdivMassSetup3D(
const int Q1D,
44 const Array<real_t> &w,
50void PAHdivMassAssembleDiagonal2D(
const int D1D,
54 const Array<real_t> &Bo_,
55 const Array<real_t> &Bc_,
60void PAHdivMassAssembleDiagonal3D(
const int D1D,
64 const Array<real_t> &Bo_,
65 const Array<real_t> &Bc_,
70void PAHdivMassApply2D(
const int NE,
const bool symmetric,
71 const bool scalar_coeff,
const Array<real_t> &Bo_,
72 const Array<real_t> &Bc_,
const Array<real_t> &Bot_,
73 const Array<real_t> &Bct_,
const Vector &op_,
74 const Vector &x_, Vector &y_,
const int D1D,
75 const int TestD1D,
const int Q1D);
78void PAHdivMassApply3D(
const int NE,
const bool symmetric,
79 const bool scalar_coeff,
const Array<real_t> &Bo_,
80 const Array<real_t> &Bc_,
const Array<real_t> &Bot_,
81 const Array<real_t> &Bct_,
const Vector &op_,
82 const Vector &x_, Vector &y_,
const int D1D,
83 const int TestD1D,
const int Q1D);
86template <
int T_D1D = 0,
int T_Q1D = 0>
87inline void SmemPAHdivMassApply2D(
88 const int NE,
const bool symmetric,
const bool,
const Array<real_t> &Bo_,
89 const Array<real_t> &Bc_,
const Array<real_t> &Bot_,
90 const Array<real_t> &Bct_,
const Vector &op_,
const Vector &x_, Vector &y_,
91 const int d1d = 0,
const int = 0,
const int q1d = 0)
93 MFEM_CONTRACT_VAR(Bot_);
94 MFEM_CONTRACT_VAR(Bct_);
96 static constexpr int VDIM = 2;
98 const int D1D = T_D1D ? T_D1D : d1d;
99 const int Q1D = T_Q1D ? T_Q1D : q1d;
101 const auto bo =
Reshape(Bo_.Read(), Q1D, D1D-1);
102 const auto bc =
Reshape(Bc_.Read(), Q1D, D1D);
103 const auto D =
Reshape(op_.Read(), Q1D, Q1D, symmetric ? 3 : 4, NE);
104 const auto x =
Reshape(x_.Read(), D1D*(D1D-1), VDIM, NE);
105 auto y = y_.ReadWrite();
109 const int tidz = MFEM_THREAD_ID(z);
111 const int D1D = T_D1D ? T_D1D : d1d;
112 const int Q1D = T_Q1D ? T_Q1D : q1d;
114 constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::HDIV_MAX_Q1D;
115 constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::HDIV_MAX_D1D;
116 constexpr int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
118 MFEM_SHARED
real_t smo[MQ1*(MD1-1)];
121 MFEM_SHARED
real_t smc[MQ1*MD1];
124 MFEM_SHARED
real_t sm0[VDIM*MDQ*MDQ];
125 MFEM_SHARED
real_t sm1[VDIM*MDQ*MDQ];
132 MFEM_FOREACH_THREAD(vd,z,VDIM)
134 MFEM_FOREACH_THREAD(dy,y,D1D)
136 MFEM_FOREACH_THREAD(qx,x,Q1D)
138 if (qx < D1D && dy < (D1D-1))
140 X(qx + dy*D1D,vd) = x(qx+dy*D1D,vd,e);
144 if (dy < (D1D-1)) { Bo(dy,qx) = bo(qx,dy); }
145 Bc(dy,qx) = bc(qx,dy);
152 MFEM_FOREACH_THREAD(vd,z,VDIM)
154 const int nx = (vd == 0) ? D1D : D1D-1;
155 const int ny = (vd == 1) ? D1D : D1D-1;
158 MFEM_FOREACH_THREAD(dy,y,ny)
160 MFEM_FOREACH_THREAD(qx,x,Q1D)
163 for (
int dx = 0; dx < nx; ++dx)
165 dq += Xxy(dx,dy,vd) * Bx(dx,qx);
172 MFEM_FOREACH_THREAD(vd,z,VDIM)
174 const int ny = (vd == 1) ? D1D : D1D-1;
176 MFEM_FOREACH_THREAD(qy,y,Q1D)
178 MFEM_FOREACH_THREAD(qx,x,Q1D)
181 for (
int dy = 0; dy < ny; ++dy)
183 qq += QD(qx,dy,vd) * By(dy,qy);
193 MFEM_FOREACH_THREAD(qy,y,Q1D)
195 MFEM_FOREACH_THREAD(qx,x,Q1D)
197 const real_t Qx = QQ(qx,qy,0);
198 const real_t Qy = QQ(qx,qy,1);
200 const real_t D11 = D(qx,qy,0,e);
201 const real_t D12 = D(qx,qy,1,e);
202 const real_t D21 = symmetric ? D12 : D(qx,qy,2,e);
203 const real_t D22 = symmetric ? D(qx,qy,2,e) : D(qx,qy,3,e);
205 QQ(qx,qy,0) = D11*Qx + D12*Qy;
206 QQ(qx,qy,1) = D21*Qx + D22*Qy;
212 MFEM_FOREACH_THREAD(vd,z,VDIM)
214 const int nx = (vd == 0) ? D1D : D1D-1;
216 MFEM_FOREACH_THREAD(qy,y,Q1D)
218 MFEM_FOREACH_THREAD(dx,x,nx)
221 for (
int qx = 0; qx < Q1D; ++qx)
223 qd += QQ(qx,qy,vd) * Btx(dx,qx);
230 MFEM_FOREACH_THREAD(vd,z,VDIM)
232 const int nx = (vd == 0) ? D1D : D1D-1;
233 const int ny = (vd == 1) ? D1D : D1D-1;
235 DeviceTensor<4> Yxy(y, nx, ny, VDIM, NE);
236 MFEM_FOREACH_THREAD(dy,y,ny)
238 MFEM_FOREACH_THREAD(dx,x,nx)
241 for (
int qy = 0; qy < Q1D; ++qy)
243 dd += DQ(dx,qy,vd) * Bty(dy,qy);
245 Yxy(dx,dy,vd,e) += dd;
254template <
int T_D1D = 0,
int T_Q1D = 0>
256SmemPAHdivMassApply3D(
const int NE,
const bool symmetric,
const bool,
257 const Array<real_t> &Bo_,
const Array<real_t> &Bc_,
258 const Array<real_t> &Bot_,
const Array<real_t> &Bct_,
259 const Vector &op_,
const Vector &x_, Vector &y_,
260 const int d1d = 0,
const int = 0,
const int q1d = 0)
262 MFEM_CONTRACT_VAR(Bot_);
263 MFEM_CONTRACT_VAR(Bct_);
265 static constexpr int VDIM = 3;
267 const int D1D = T_D1D ? T_D1D : d1d;
268 const int Q1D = T_Q1D ? T_Q1D : q1d;
270 const auto bo =
Reshape(Bo_.Read(), Q1D, D1D-1);
271 const auto bc =
Reshape(Bc_.Read(), Q1D, D1D);
272 const auto D =
Reshape(op_.Read(), Q1D, Q1D, Q1D, symmetric ? 6 : 9, NE);
273 const auto x =
Reshape(x_.Read(), D1D*(D1D-1)*(D1D-1), VDIM, NE);
274 auto y = y_.ReadWrite();
278 const int tidz = MFEM_THREAD_ID(z);
280 const int D1D = T_D1D ? T_D1D : d1d;
281 const int Q1D = T_Q1D ? T_Q1D : q1d;
283 constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::HDIV_MAX_Q1D;
284 constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::HDIV_MAX_D1D;
285 constexpr int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
287 MFEM_SHARED
real_t smo[MQ1*(MD1-1)];
290 MFEM_SHARED
real_t smc[MQ1*MD1];
293 MFEM_SHARED
real_t sm0[VDIM*MDQ*MDQ*MDQ];
294 MFEM_SHARED
real_t sm1[VDIM*MDQ*MDQ*MDQ];
296 DeviceTensor<4> QDD(sm1, Q1D, D1D, D1D, VDIM);
297 DeviceTensor<4> QQD(sm0, Q1D, Q1D, D1D, VDIM);
298 DeviceTensor<4> QQQ(sm1, Q1D, Q1D, Q1D, VDIM);
299 DeviceTensor<4> DQQ(sm0, D1D, Q1D, Q1D, VDIM);
300 DeviceTensor<4> DDQ(sm1, D1D, D1D, Q1D, VDIM);
303 MFEM_FOREACH_THREAD(vd,z,VDIM)
305 MFEM_FOREACH_THREAD(dz,y,D1D-1)
307 MFEM_FOREACH_THREAD(dy,x,D1D-1)
310 for (
int dx = 0; dx < D1D; ++dx)
312 X(dx+(dy+dz*(D1D-1))*D1D,vd) = x(dx+(dy+dz*(D1D-1))*D1D,vd,e);
320 MFEM_FOREACH_THREAD(d,y,D1D-1)
322 MFEM_FOREACH_THREAD(q,x,Q1D)
327 MFEM_FOREACH_THREAD(d,y,D1D)
329 MFEM_FOREACH_THREAD(q,x,Q1D)
337 MFEM_FOREACH_THREAD(vd,z,VDIM)
339 const int nx = (vd == 0) ? D1D : D1D-1;
340 const int ny = (vd == 1) ? D1D : D1D-1;
341 const int nz = (vd == 2) ? D1D : D1D-1;
342 DeviceTensor<4> Xxyz(X, nx, ny, nz, VDIM);
344 MFEM_FOREACH_THREAD(dy,y,ny)
346 MFEM_FOREACH_THREAD(qx,x,Q1D)
350 for (
int dz = 0; dz < nz; ++dz) {
u[dz] = 0.0; }
352 for (
int dx = 0; dx < nx; ++dx)
355 for (
int dz = 0; dz < nz; ++dz)
357 u[dz] += Xxyz(dx,dy,dz,vd) * Bx(dx,qx);
361 for (
int dz = 0; dz < nz; ++dz) { QDD(qx,dy,dz,vd) =
u[dz]; }
366 MFEM_FOREACH_THREAD(vd,z,VDIM)
368 const int ny = (vd == 1) ? D1D : D1D-1;
369 const int nz = (vd == 2) ? D1D : D1D-1;
371 MFEM_FOREACH_THREAD(qy,y,Q1D)
373 MFEM_FOREACH_THREAD(qx,x,Q1D)
377 for (
int dz = 0; dz < nz; ++dz) {
u[dz] = 0.0; }
379 for (
int dy = 0; dy < ny; ++dy)
382 for (
int dz = 0; dz < nz; ++dz)
384 u[dz] += QDD(qx,dy,dz,vd) * By(dy,qy);
388 for (
int dz = 0; dz < nz; ++dz) { QQD(qx,qy,dz,vd) =
u[dz]; }
393 MFEM_FOREACH_THREAD(vd,z,VDIM)
395 const int nz = (vd == 2) ? D1D : D1D-1;
397 MFEM_FOREACH_THREAD(qy,y,Q1D)
399 MFEM_FOREACH_THREAD(qx,x,Q1D)
403 for (
int qz = 0; qz < Q1D; ++qz) {
u[qz] = 0.0; }
405 for (
int dz = 0; dz < nz; ++dz)
408 for (
int qz = 0; qz < Q1D; ++qz)
410 u[qz] += QQD(qx,qy,dz,vd) * Bz(dz,qz);
414 for (
int qz = 0; qz < Q1D; ++qz) { QQQ(qx,qy,qz,vd) =
u[qz]; }
422 MFEM_FOREACH_THREAD(qy,y,Q1D)
424 MFEM_FOREACH_THREAD(qx,x,Q1D)
427 for (
int qz = 0; qz < Q1D; ++qz)
429 const real_t Qx = QQQ(qx,qy,qz,0);
430 const real_t Qy = QQQ(qx,qy,qz,1);
431 const real_t Qz = QQQ(qx,qy,qz,2);
433 const real_t D11 = D(qx,qy,qz,0,e);
434 const real_t D12 = D(qx,qy,qz,1,e);
435 const real_t D13 = D(qx,qy,qz,2,e);
436 const real_t D21 = symmetric ? D12 : D(qx,qy,qz,3,e);
437 const real_t D22 = symmetric ? D(qx,qy,qz,3,e) : D(qx,qy,qz,4,e);
438 const real_t D23 = symmetric ? D(qx,qy,qz,4,e) : D(qx,qy,qz,5,e);
439 const real_t D31 = symmetric ? D13 : D(qx,qy,qz,6,e);
440 const real_t D32 = symmetric ? D23 : D(qx,qy,qz,7,e);
441 const real_t D33 = symmetric ? D(qx,qy,qz,5,e) : D(qx,qy,qz,8,e);
443 QQQ(qx,qy,qz,0) = D11*Qx + D12*Qy + D13*Qz;
444 QQQ(qx,qy,qz,1) = D21*Qx + D22*Qy + D23*Qz;
445 QQQ(qx,qy,qz,2) = D31*Qx + D32*Qy + D33*Qz;
452 MFEM_FOREACH_THREAD(vd,z,VDIM)
454 const int nx = (vd == 0) ? D1D : D1D-1;
456 MFEM_FOREACH_THREAD(qy,y,Q1D)
458 MFEM_FOREACH_THREAD(dx,x,nx)
462 for (
int qz = 0; qz < Q1D; ++qz) {
u[qz] = 0.0; }
464 for (
int qx = 0; qx < Q1D; ++qx)
467 for (
int qz = 0; qz < Q1D; ++qz)
469 u[qz] += QQQ(qx,qy,qz,vd) * Btx(dx,qx);
473 for (
int qz = 0; qz < Q1D; ++qz) { DQQ(dx,qy,qz,vd) =
u[qz]; }
478 MFEM_FOREACH_THREAD(vd,z,VDIM)
480 const int nx = (vd == 0) ? D1D : D1D-1;
481 const int ny = (vd == 1) ? D1D : D1D-1;
483 MFEM_FOREACH_THREAD(dy,y,ny)
485 MFEM_FOREACH_THREAD(dx,x,nx)
489 for (
int qz = 0; qz < Q1D; ++qz) {
u[qz] = 0.0; }
491 for (
int qy = 0; qy < Q1D; ++qy)
494 for (
int qz = 0; qz < Q1D; ++qz)
496 u[qz] += DQQ(dx,qy,qz,vd) * Bty(dy,qy);
500 for (
int qz = 0; qz < Q1D; ++qz) { DDQ(dx,dy,qz,vd) =
u[qz]; }
505 MFEM_FOREACH_THREAD(vd,z,VDIM)
507 const int nx = (vd == 0) ? D1D : D1D-1;
508 const int ny = (vd == 1) ? D1D : D1D-1;
509 const int nz = (vd == 2) ? D1D : D1D-1;
510 DeviceTensor<5> Yxyz(y, nx, ny, nz, VDIM, NE);
512 MFEM_FOREACH_THREAD(dy,y,ny)
514 MFEM_FOREACH_THREAD(dx,x,nx)
518 for (
int dz = 0; dz < nz; ++dz) {
u[dz] = 0.0; }
520 for (
int qz = 0; qz < Q1D; ++qz)
523 for (
int dz = 0; dz < nz; ++dz)
525 u[dz] += DDQ(dx,dy,qz,vd) * Btz(dz,qz);
529 for (
int dz = 0; dz < nz; ++dz) { Yxyz(dx,dy,dz,vd,e) +=
u[dz]; }
538void PADivDivSetup2D(
const int Q1D,
540 const Array<real_t> &w,
546void PADivDivSetup3D(
const int Q1D,
548 const Array<real_t> &w,
554void PADivDivAssembleDiagonal2D(
const int D1D,
557 const Array<real_t> &Bo_,
558 const Array<real_t> &Gc_,
563void PADivDivAssembleDiagonal3D(
const int D1D,
566 const Array<real_t> &Bo_,
567 const Array<real_t> &Gc_,
572void PADivDivApply2D(
const int D1D,
575 const Array<real_t> &Bo_,
576 const Array<real_t> &Gc_,
577 const Array<real_t> &Bot_,
578 const Array<real_t> &Gct_,
584void PADivDivApply3D(
const int D1D,
587 const Array<real_t> &Bo_,
588 const Array<real_t> &Gc_,
589 const Array<real_t> &Bot_,
590 const Array<real_t> &Gct_,
597void PAHdivL2Setup2D(
const int Q1D,
const int NE,
const Array<real_t> &w,
598 Vector &coeff_, Vector &op,
const GeometricFactors *geom);
602void PAHdivL2Setup3D(
const int Q1D,
const int NE,
const Array<real_t> &w,
603 Vector &coeff_, Vector &op,
const GeometricFactors *geom);
606void PAHdivL2AssembleDiagonal_ADAt_2D(
const int D1D,
610 const Array<real_t> &L2Bo_,
611 const Array<real_t> &Gct_,
612 const Array<real_t> &Bot_,
618void PAHdivL2AssembleDiagonal_ADAt_3D(
const int D1D,
622 const Array<real_t> &L2Bo_,
623 const Array<real_t> &Gct_,
624 const Array<real_t> &Bot_,
630void PAHdivL2Apply2D(
const int D1D,
634 const Array<real_t> &Bo_,
635 const Array<real_t> &Gc_,
636 const Array<real_t> &L2Bot_,
642void PAHdivL2ApplyTranspose2D(
const int D1D,
646 const Array<real_t> &L2Bo_,
647 const Array<real_t> &Gct_,
648 const Array<real_t> &Bot_,
654void PAHdivL2Apply3D(
const int D1D,
658 const Array<real_t> &Bo_,
659 const Array<real_t> &Gc_,
660 const Array<real_t> &L2Bot_,
666void PAHdivL2ApplyTranspose3D(
const int D1D,
670 const Array<real_t> &L2Bo_,
671 const Array<real_t> &Gct_,
672 const Array<real_t> &Bot_,
DeviceTensor< 3, real_t > DeviceCube
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_3D(int N, int X, int Y, int Z, lambda &&body)
DeviceTensor< 2, real_t > DeviceMatrix