12#ifndef MFEM_BILININTEG_HCURL_KERNELS_HPP
13#define MFEM_BILININTEG_HCURL_KERNELS_HPP
32void PAHcurlMassAssembleDiagonal2D(
const int D1D,
36 const Array<real_t> &bo,
37 const Array<real_t> &bc,
38 const Vector &pa_data,
42void PAHcurlMassAssembleDiagonal3D(
const int D1D,
46 const Array<real_t> &bo,
47 const Array<real_t> &bc,
48 const Vector &pa_data,
52template<
int T_D1D = 0,
int T_Q1D = 0>
53inline void SmemPAHcurlMassAssembleDiagonal3D(
const int d1d,
57 const Array<real_t> &bo,
58 const Array<real_t> &bc,
59 const Vector &pa_data,
63 "Error: d1d > HCURL_MAX_D1D");
65 "Error: q1d > HCURL_MAX_Q1D");
66 const int D1D = T_D1D ? T_D1D : d1d;
67 const int Q1D = T_Q1D ? T_Q1D : q1d;
69 auto Bo =
Reshape(bo.Read(), Q1D, D1D-1);
70 auto Bc =
Reshape(bc.Read(), Q1D, D1D);
71 auto op =
Reshape(pa_data.Read(), Q1D, Q1D, Q1D, symmetric ? 6 : 9, NE);
72 auto D =
Reshape(diag.ReadWrite(), 3*(D1D-1)*D1D*D1D, NE);
76 constexpr int VDIM = 3;
77 constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
78 constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
79 const int D1D = T_D1D ? T_D1D : d1d;
80 const int Q1D = T_Q1D ? T_Q1D : q1d;
82 MFEM_SHARED
real_t sBo[MQ1D][MD1D];
83 MFEM_SHARED
real_t sBc[MQ1D][MD1D];
86 MFEM_SHARED
real_t sop[3][MQ1D][MQ1D];
88 MFEM_FOREACH_THREAD(qx,x,Q1D)
90 MFEM_FOREACH_THREAD(qy,y,Q1D)
92 MFEM_FOREACH_THREAD(qz,z,Q1D)
94 op3[0] = op(qx,qy,qz,0,e);
95 op3[1] = op(qx,qy,qz,symmetric ? 3 : 4,e);
96 op3[2] = op(qx,qy,qz,symmetric ? 5 : 8,e);
101 const int tidx = MFEM_THREAD_ID(x);
102 const int tidy = MFEM_THREAD_ID(y);
103 const int tidz = MFEM_THREAD_ID(z);
107 MFEM_FOREACH_THREAD(d,y,D1D)
109 MFEM_FOREACH_THREAD(q,x,Q1D)
122 for (
int c = 0; c < VDIM; ++c)
124 const int D1Dz = (c == 2) ? D1D - 1 : D1D;
125 const int D1Dy = (c == 1) ? D1D - 1 : D1D;
126 const int D1Dx = (c == 0) ? D1D - 1 : D1D;
130 for (
int qz=0; qz < Q1D; ++qz)
134 for (
int i=0; i<3; ++i)
136 sop[i][tidx][tidy] = op3[i];
142 MFEM_FOREACH_THREAD(dz,z,D1Dz)
144 const real_t wz = ((c == 2) ? sBo[qz][dz] : sBc[qz][dz]);
146 MFEM_FOREACH_THREAD(dy,y,D1Dy)
148 MFEM_FOREACH_THREAD(dx,x,D1Dx)
150 for (
int qy = 0; qy < Q1D; ++qy)
152 const real_t wy = ((c == 1) ? sBo[qy][dy] : sBc[qy][dy]);
154 for (
int qx = 0; qx < Q1D; ++qx)
156 const real_t wx = ((c == 0) ? sBo[qx][dx] : sBc[qx][dx]);
157 dxyz += sop[c][qx][qy] * wx * wx * wy * wy * wz * wz;
167 MFEM_FOREACH_THREAD(dz,z,D1Dz)
169 MFEM_FOREACH_THREAD(dy,y,D1Dy)
171 MFEM_FOREACH_THREAD(dx,x,D1Dx)
173 D(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e) += dxyz;
178 osc += D1Dx * D1Dy * D1Dz;
184void PAHcurlMassApply2D(
const int NE,
const bool symmetric,
185 const bool scalar_coeff,
const Array<real_t> &bo,
186 const Array<real_t> &bc,
const Array<real_t> &bot,
187 const Array<real_t> &bct,
const Vector &pa_data,
188 const Vector &x, Vector &y,
const int TrialD1D,
189 const int TestD1D,
const int Q1D);
192void PAHcurlMassApply3D(
const int NE,
const bool symmetric,
193 [[maybe_unused]]
const bool scalar_coeff,
194 const Array<real_t> &bo,
const Array<real_t> &bc,
195 const Array<real_t> &bot,
const Array<real_t> &bct,
196 const Vector &pa_data,
const Vector &x, Vector &y,
197 const int TrialD1D, [[maybe_unused]]
const int TestD1D,
201template <
int T_D1D = 0,
int T_Q1D = 0,
int TBATCH = 0,
bool ACCUMULATE = true>
202inline void SmemPAHcurlMassApply3D(
203 const int NE,
const bool symmetric, [[maybe_unused]]
const bool scalar_coeff,
204 const Array<real_t> &bo,
const Array<real_t> &bc,
205 [[maybe_unused]]
const Array<real_t> &bot,
206 [[maybe_unused]]
const Array<real_t> &bct,
const Vector &pa_data,
207 const Vector &x, Vector &y,
const int d1d = 0,
208 [[maybe_unused]]
const int test_d1d = 0,
const int q1d = 0)
210 const int D1D = T_D1D ? T_D1D : d1d;
211 const int Q1D = T_Q1D ? T_Q1D : q1d;
214 "Error: d1d > HCURL_MAX_D1D");
216 "Error: q1d > HCURL_MAX_Q1D");
217 MFEM_ASSERT(Q1D >= D1D,
"Expected Q1D >= D1D");
218 const int dataSize = symmetric ? 6 : 9;
224 Reshape(pa_data.Read(), Q1D, Q1D, Q1D, dataSize, NE);
225 auto X_ =
Reshape(x.Read(), 3 * (D1D - 1) * D1D * D1D, NE);
226 auto y_ = y.ReadWrite();
228 constexpr int MD_ = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
229 constexpr int MQ_ = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
230 constexpr int MDQ_ = std::max(MD_, MQ_);
231 constexpr int MB_ = TBATCH ? TBATCH : 1;
234 NE, MDQ_ * MDQ_ * MDQ_, 1, MB_, [=] MFEM_HOST_DEVICE(
int e)
236#if defined(__CUDA_ARCH__) || defined(__HIP_DEVICE_COMPILE__)
237 constexpr int nbz = TBATCH ? TBATCH : 1;
238 int tidz = MFEM_THREAD_ID(z);
240 constexpr int nbz = 1;
241 constexpr int tidz = 0;
244 constexpr int VDIM = 3;
245 constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
246 constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
247 constexpr int MDQ = std::max(MD1D, MQ1D);
252 auto Y =
Reshape(y_, VDIM * (D1D - 1) * D1D * D1D, NE);
254 MFEM_SHARED
real_t sBo[MDQ * (MD1D - 1)];
255 MFEM_SHARED
real_t sBc[MDQ * MD1D];
256 auto BO =
Reshape(sBo, Q1D, D1D - 1);
257 auto BC =
Reshape(sBc, Q1D, D1D);
259 MFEM_SHARED
real_t sX[nbz * VDIM * (MD1D - 1) * MD1D * MD1D];
260 MFEM_SHARED
real_t sm0[nbz * VDIM * MDQ * MDQ * MDQ];
261 MFEM_SHARED
real_t sm1[nbz * VDIM * MDQ * MDQ * MDQ];
263 real_t(*X)[nbz][(MD1D - 1) * MD1D * MD1D] =
264 (
real_t(*)[nbz][(MD1D - 1) * MD1D * MD1D])(sX);
267 real_t(*DDQ)[nbz][MQ1D][MQ1D][MQ1D] =
268 (
real_t(*)[nbz][MQ1D][MQ1D][MQ1D])(sm0);
269 real_t(*DQQ)[nbz][MQ1D][MQ1D][MQ1D] =
270 (
real_t(*)[nbz][MQ1D][MQ1D][MQ1D])(sm1);
271 real_t(*QQQ)[nbz][MQ1D][MQ1D][MQ1D] =
272 (
real_t(*)[nbz][MQ1D][MQ1D][MQ1D])(sm0);
273 real_t(*QQD)[nbz][MQ1D][MQ1D][MQ1D] =
274 (
real_t(*)[nbz][MQ1D][MQ1D][MQ1D])(sm1);
275 real_t(*QDD)[nbz][MQ1D][MQ1D][MQ1D] =
276 (
real_t(*)[nbz][MQ1D][MQ1D][MQ1D])(sm0);
279 const int offset = (D1D - 1) * D1D * D1D;
280 MFEM_FOREACH_THREAD_DIRECT(ix, x, offset)
284 X[
dim][tidz][ix] = X_(ix +
dim * offset, e);
290 MFEM_FOREACH_THREAD_DIRECT(ix, x, D1D * Q1D) { sBc[ix] = Bc[ix]; }
291 MFEM_FOREACH_THREAD_DIRECT(ix, x, (D1D - 1) * Q1D)
297 for (
int dim0 = 0; dim0 < VDIM; ++dim0)
301 for (
int dim1 = 0; dim1 < VDIM; ++dim1)
303 const int D1Dz = (dim1 == 2) ? D1D - 1 : D1D;
304 const int D1Dy = (dim1 == 1) ? D1D - 1 : D1D;
305 const int D1Dx = (dim1 == 0) ? D1D - 1 : D1D;
308 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, dy, dz, x, Q1D, D1Dy, D1Dz,
312 for (
int dx = 0; dx < D1Dx; ++dx)
323 u += X[dim1][tidz][dx + (dy + dz * D1Dy) * D1Dx] *
b;
325 DDQ[dim1][tidz][dz][dy][qx] =
u;
329 for (
int dim1 = 0; dim1 < VDIM; ++dim1)
331 const int D1Dz = (dim1 == 2) ? D1D - 1 : D1D;
332 const int D1Dy = (dim1 == 1) ? D1D - 1 : D1D;
335 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, qy, dz, x, Q1D, Q1D, D1Dz,
339 for (
int dy = 0; dy < D1Dy; ++dy)
350 u += DDQ[dim1][tidz][dz][dy][qx] *
b;
352 DQQ[dim1][tidz][dz][qy][qx] =
u;
356 for (
int dim1 = 0; dim1 < VDIM; ++dim1)
358 const int D1Dz = (dim1 == 2) ? D1D - 1 : D1D;
361 MFEM_FOREACH_THREAD_DIRECT_3D(qx, qy, qz, x, Q1D, Q1D, Q1D)
364 for (
int dz = 0; dz < D1Dz; ++dz)
375 u += DQQ[dim1][tidz][dz][qy][qx] *
b;
393 idx = col + VDIM * row - row * (row + 1) / 2;
397 idx = dim0 * VDIM + dim1;
399 QQQ[dim1][tidz][qz][qy][qx] = op(qx, qy, qz, idx, e) *
u;
407 const int D1Dz = (dim0 == 2) ? D1D - 1 : D1D;
408 const int D1Dy = (dim0 == 1) ? D1D - 1 : D1D;
409 const int D1Dx = (dim0 == 0) ? D1D - 1 : D1D;
411 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dz, qx, qy, x, D1Dz, Q1D, Q1D,
414 for (
int dim1 = 0; dim1 < VDIM; ++dim1)
417 for (
int qz = 0; qz < Q1D; ++qz)
428 u += QQQ[dim1][tidz][qz][qy][qx] *
b;
430 QQD[dim1][tidz][qy][qx][dz] =
u;
435 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dy, dz, qx, x, D1Dy, D1Dz, Q1D,
438 for (
int dim1 = 0; dim1 < VDIM; ++dim1)
441 for (
int qy = 0; qy < Q1D; ++qy)
452 u += QQD[dim1][tidz][qy][qx][dz] *
b;
454 QDD[dim1][tidz][qx][dz][dy] =
u;
459 MFEM_FOREACH_THREAD_DIRECT_3D(dx, dy, dz, x, D1Dx, D1Dy, D1Dz)
461 int ix = dx + D1Dx * (dy + D1Dy * dz);
463 for (
int qx = 0; qx < Q1D; ++qx)
474 for (
int dim1 = 0; dim1 < VDIM; ++dim1)
476 u += QDD[dim1][tidz][qx][dz][dy] *
b;
479 if constexpr (ACCUMULATE)
481 Y(ix + dim0 * offset, e) +=
u;
485 Y(ix + dim0 * offset, e) =
u;
494void PACurlCurlSetup2D(
const int Q1D,
496 const Array<real_t> &w,
502void PACurlCurlSetup3D(
const int Q1D,
505 const Array<real_t> &w,
511void PACurlCurlAssembleDiagonal2D(
const int D1D,
513 const bool symmetric,
515 const Array<real_t> &bo,
516 const Array<real_t> &bc,
517 const Array<real_t> &go,
518 const Array<real_t> &gc,
519 const Vector &pa_data,
523template<
int T_D1D = 0,
int T_Q1D = 0>
524inline void PACurlCurlAssembleDiagonal3D(
const int d1d,
526 const bool symmetric,
528 const Array<real_t> &bo,
529 const Array<real_t> &bc,
530 const Array<real_t> &go,
531 const Array<real_t> &gc,
532 const Vector &pa_data,
536 "Error: d1d > HCURL_MAX_D1D");
538 "Error: q1d > HCURL_MAX_Q1D");
539 const int D1D = T_D1D ? T_D1D : d1d;
540 const int Q1D = T_Q1D ? T_Q1D : q1d;
542 auto Bo =
Reshape(bo.Read(), Q1D, D1D-1);
543 auto Bc =
Reshape(bc.Read(), Q1D, D1D);
544 auto Go =
Reshape(go.Read(), Q1D, D1D-1);
545 auto Gc =
Reshape(gc.Read(), Q1D, D1D);
546 auto op =
Reshape(pa_data.Read(), Q1D, Q1D, Q1D, (symmetric ? 6 : 9), NE);
547 auto D =
Reshape(diag.ReadWrite(), 3*(D1D-1)*D1D*D1D, NE);
549 const int s = symmetric ? 6 : 9;
553 const int i21 = symmetric ? i12 : 3;
554 const int i22 = symmetric ? 3 : 4;
555 const int i23 = symmetric ? 4 : 5;
556 const int i31 = symmetric ? i13 : 6;
557 const int i32 = symmetric ? i23 : 7;
558 const int i33 = symmetric ? 5 : 8;
571 constexpr int VDIM = 3;
572 constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
573 constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
574 const int D1D = T_D1D ? T_D1D : d1d;
575 const int Q1D = T_Q1D ? T_Q1D : q1d;
579 for (
int c = 0; c < VDIM; ++c)
581 const int D1Dz = (c == 2) ? D1D - 1 : D1D;
582 const int D1Dy = (c == 1) ? D1D - 1 : D1D;
583 const int D1Dx = (c == 0) ? D1D - 1 : D1D;
585 real_t zt[MQ1D][MQ1D][MD1D][9][3];
588 for (
int qx = 0; qx < Q1D; ++qx)
590 for (
int qy = 0; qy < Q1D; ++qy)
592 for (
int dz = 0; dz < D1Dz; ++dz)
594 for (
int i=0; i<s; ++i)
596 for (
int d=0; d<3; ++d)
598 zt[qx][qy][dz][i][d] = 0.0;
602 for (
int qz = 0; qz < Q1D; ++qz)
604 const real_t wz = ((c == 2) ? Bo(qz,dz) : Bc(qz,dz));
605 const real_t wDz = ((c == 2) ? Go(qz,dz) : Gc(qz,dz));
607 for (
int i=0; i<s; ++i)
609 zt[qx][qy][dz][i][0] += wz * wz * op(qx,qy,qz,i,e);
610 zt[qx][qy][dz][i][1] += wDz * wz * op(qx,qy,qz,i,e);
611 zt[qx][qy][dz][i][2] += wDz * wDz * op(qx,qy,qz,i,e);
618 real_t yt[MQ1D][MD1D][MD1D][9][3][3];
621 for (
int qx = 0; qx < Q1D; ++qx)
623 for (
int dz = 0; dz < D1Dz; ++dz)
625 for (
int dy = 0; dy < D1Dy; ++dy)
627 for (
int i=0; i<s; ++i)
629 for (
int d=0; d<3; ++d)
630 for (
int j=0; j<3; ++j)
632 yt[qx][dy][dz][i][d][j] = 0.0;
636 for (
int qy = 0; qy < Q1D; ++qy)
638 const real_t wy = ((c == 1) ? Bo(qy,dy) : Bc(qy,dy));
639 const real_t wDy = ((c == 1) ? Go(qy,dy) : Gc(qy,dy));
641 for (
int i=0; i<s; ++i)
643 for (
int d=0; d<3; ++d)
645 yt[qx][dy][dz][i][d][0] += wy * wy * zt[qx][qy][dz][i][d];
646 yt[qx][dy][dz][i][d][1] += wDy * wy * zt[qx][qy][dz][i][d];
647 yt[qx][dy][dz][i][d][2] += wDy * wDy * zt[qx][qy][dz][i][d];
656 for (
int dz = 0; dz < D1Dz; ++dz)
658 for (
int dy = 0; dy < D1Dy; ++dy)
660 for (
int dx = 0; dx < D1Dx; ++dx)
662 for (
int qx = 0; qx < Q1D; ++qx)
664 const real_t wx = ((c == 0) ? Bo(qx,dx) : Bc(qx,dx));
665 const real_t wDx = ((c == 0) ? Go(qx,dx) : Gc(qx,dx));
685 const real_t sumy = yt[qx][dy][dz][i22][2][0] - yt[qx][dy][dz][i23][1][1]
686 - yt[qx][dy][dz][i32][1][1] + yt[qx][dy][dz][i33][0][2];
688 D(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e) += sumy * wx * wx;
693 const real_t d = (yt[qx][dy][dz][i11][2][0] * wx * wx)
694 - ((yt[qx][dy][dz][i13][1][0] + yt[qx][dy][dz][i31][1][0]) * wDx * wx)
695 + (yt[qx][dy][dz][i33][0][0] * wDx * wDx);
697 D(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e) += d;
702 const real_t d = (yt[qx][dy][dz][i11][0][2] * wx * wx)
703 - ((yt[qx][dy][dz][i12][0][1] + yt[qx][dy][dz][i21][0][1]) * wDx * wx)
704 + (yt[qx][dy][dz][i22][0][0] * wDx * wDx);
706 D(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e) += d;
713 osc += D1Dx * D1Dy * D1Dz;
719template<
int T_D1D = 0,
int T_Q1D = 0>
720inline void SmemPACurlCurlAssembleDiagonal3D(
const int d1d,
722 const bool symmetric,
724 const Array<real_t> &bo,
725 const Array<real_t> &bc,
726 const Array<real_t> &go,
727 const Array<real_t> &gc,
728 const Vector &pa_data,
732 "Error: d1d > HCURL_MAX_D1D");
734 "Error: q1d > HCURL_MAX_Q1D");
735 const int D1D = T_D1D ? T_D1D : d1d;
736 const int Q1D = T_Q1D ? T_Q1D : q1d;
738 auto Bo =
Reshape(bo.Read(), Q1D, D1D-1);
739 auto Bc =
Reshape(bc.Read(), Q1D, D1D);
740 auto Go =
Reshape(go.Read(), Q1D, D1D-1);
741 auto Gc =
Reshape(gc.Read(), Q1D, D1D);
742 auto op =
Reshape(pa_data.Read(), Q1D, Q1D, Q1D, (symmetric ? 6 : 9), NE);
743 auto D =
Reshape(diag.ReadWrite(), 3*(D1D-1)*D1D*D1D, NE);
745 const int s = symmetric ? 6 : 9;
749 const int i21 = symmetric ? i12 : 3;
750 const int i22 = symmetric ? 3 : 4;
751 const int i23 = symmetric ? 4 : 5;
752 const int i31 = symmetric ? i13 : 6;
753 const int i32 = symmetric ? i23 : 7;
754 const int i33 = symmetric ? 5 : 8;
764 constexpr int VDIM = 3;
765 constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
766 constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
767 const int D1D = T_D1D ? T_D1D : d1d;
768 const int Q1D = T_Q1D ? T_Q1D : q1d;
770 MFEM_SHARED
real_t sBo[MQ1D][MD1D];
771 MFEM_SHARED
real_t sBc[MQ1D][MD1D];
772 MFEM_SHARED
real_t sGo[MQ1D][MD1D];
773 MFEM_SHARED
real_t sGc[MQ1D][MD1D];
776 MFEM_SHARED
real_t sop[9][MQ1D][MQ1D];
778 MFEM_FOREACH_THREAD(qx,x,Q1D)
780 MFEM_FOREACH_THREAD(qy,y,Q1D)
782 MFEM_FOREACH_THREAD(qz,z,Q1D)
784 for (
int i=0; i<s; ++i)
786 ope[i] = op(qx,qy,qz,i,e);
792 const int tidx = MFEM_THREAD_ID(x);
793 const int tidy = MFEM_THREAD_ID(y);
794 const int tidz = MFEM_THREAD_ID(z);
798 MFEM_FOREACH_THREAD(d,y,D1D)
800 MFEM_FOREACH_THREAD(q,x,Q1D)
815 for (
int c = 0; c < VDIM; ++c)
817 const int D1Dz = (c == 2) ? D1D - 1 : D1D;
818 const int D1Dy = (c == 1) ? D1D - 1 : D1D;
819 const int D1Dx = (c == 0) ? D1D - 1 : D1D;
823 for (
int qz=0; qz < Q1D; ++qz)
827 for (
int i=0; i<s; ++i)
829 sop[i][tidx][tidy] = ope[i];
835 MFEM_FOREACH_THREAD(dz,z,D1Dz)
837 const real_t wz = ((c == 2) ? sBo[qz][dz] : sBc[qz][dz]);
838 const real_t wDz = ((c == 2) ? sGo[qz][dz] : sGc[qz][dz]);
840 MFEM_FOREACH_THREAD(dy,y,D1Dy)
842 MFEM_FOREACH_THREAD(dx,x,D1Dx)
844 for (
int qy = 0; qy < Q1D; ++qy)
846 const real_t wy = ((c == 1) ? sBo[qy][dy] : sBc[qy][dy]);
847 const real_t wDy = ((c == 1) ? sGo[qy][dy] : sGc[qy][dy]);
849 for (
int qx = 0; qx < Q1D; ++qx)
851 const real_t wx = ((c == 0) ? sBo[qx][dx] : sBc[qx][dx]);
852 const real_t wDx = ((c == 0) ? sGo[qx][dx] : sGc[qx][dx]);
859 dxyz += sop[i22][qx][qy] * wx * wx * wy * wy * wDz * wDz;
862 dxyz += -(sop[i23][qx][qy] + sop[i32][qx][qy]) * wx * wx * wDy * wy * wDz * wz;
865 dxyz += sop[i33][qx][qy] * wx * wx * wDy * wDy * wz * wz;
872 dxyz += sop[i11][qx][qy] * wx * wx * wy * wy * wDz * wDz;
875 dxyz += -(sop[i13][qx][qy] + sop[i31][qx][qy]) * wDx * wx * wy * wy * wDz * wz;
878 dxyz += sop[i33][qx][qy] * wDx * wDx * wy * wy * wz * wz;
885 dxyz += sop[i11][qx][qy] * wx * wx * wDy * wDy * wz * wz;
888 dxyz += -(sop[i12][qx][qy] + sop[i21][qx][qy]) * wDx * wx * wDy * wy * wz * wz;
891 dxyz += sop[i22][qx][qy] * wDx * wDx * wy * wy * wz * wz;
902 MFEM_FOREACH_THREAD(dz,z,D1Dz)
904 MFEM_FOREACH_THREAD(dy,y,D1Dy)
906 MFEM_FOREACH_THREAD(dx,x,D1Dx)
908 D(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e) += dxyz;
913 osc += D1Dx * D1Dy * D1Dz;
919void PACurlCurlApply2D(
const int D1D,
921 const bool symmetric,
923 const Array<real_t> &bo,
924 const Array<real_t> &bc,
925 const Array<real_t> &bot,
926 const Array<real_t> &bct,
927 const Array<real_t> &gc,
928 const Array<real_t> &gct,
929 const Vector &pa_data,
932 const bool useAbs =
false);
935template<
int T_D1D = 0,
int T_Q1D = 0>
936inline void PACurlCurlApply3D(
const int d1d,
938 const bool symmetric,
940 const Array<real_t> &bo,
941 const Array<real_t> &bc,
942 const Array<real_t> &bot,
943 const Array<real_t> &bct,
944 const Array<real_t> &gc,
945 const Array<real_t> &gct,
946 const Vector &pa_data,
949 const bool useAbs =
false)
952 "Error: d1d > HCURL_MAX_D1D");
954 "Error: q1d > HCURL_MAX_Q1D");
955 const int D1D = T_D1D ? T_D1D : d1d;
956 const int Q1D = T_Q1D ? T_Q1D : q1d;
958 auto Bo =
Reshape(bo.Read(), Q1D, D1D-1);
959 auto Bc =
Reshape(bc.Read(), Q1D, D1D);
960 auto Bot =
Reshape(bot.Read(), D1D-1, Q1D);
961 auto Bct =
Reshape(bct.Read(), D1D, Q1D);
962 auto Gc =
Reshape(gc.Read(), Q1D, D1D);
963 auto Gct =
Reshape(gct.Read(), D1D, Q1D);
964 auto op =
Reshape(pa_data.Read(), Q1D, Q1D, Q1D, (symmetric ? 6 : 9), NE);
965 auto X =
Reshape(x.Read(), 3*(D1D-1)*D1D*D1D, NE);
966 auto Y =
Reshape(y.ReadWrite(), 3*(D1D-1)*D1D*D1D, NE);
978 constexpr int VDIM = 3;
979 constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
980 constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
981 const int D1D = T_D1D ? T_D1D : d1d;
982 const int Q1D = T_Q1D ? T_Q1D : q1d;
984 real_t curl[MQ1D][MQ1D][MQ1D][VDIM];
987 for (
int qz = 0; qz < Q1D; ++qz)
989 for (
int qy = 0; qy < Q1D; ++qy)
991 for (
int qx = 0; qx < Q1D; ++qx)
993 for (
int c = 0; c < VDIM; ++c)
995 curl[qz][qy][qx][c] = 0.0;
1007 const int D1Dz = D1D;
1008 const int D1Dy = D1D;
1009 const int D1Dx = D1D - 1;
1011 for (
int dz = 0; dz < D1Dz; ++dz)
1013 real_t gradXY[MQ1D][MQ1D][2];
1014 for (
int qy = 0; qy < Q1D; ++qy)
1016 for (
int qx = 0; qx < Q1D; ++qx)
1018 for (
int d = 0; d < 2; ++d)
1020 gradXY[qy][qx][d] = 0.0;
1025 for (
int dy = 0; dy < D1Dy; ++dy)
1028 for (
int qx = 0; qx < Q1D; ++qx)
1033 for (
int dx = 0; dx < D1Dx; ++dx)
1035 const real_t t = X(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
1036 for (
int qx = 0; qx < Q1D; ++qx)
1038 massX[qx] += t * Bo(qx,dx);
1042 for (
int qy = 0; qy < Q1D; ++qy)
1044 const real_t wy = Bc(qy,dy);
1045 const real_t wDy = Gc(qy,dy);
1046 for (
int qx = 0; qx < Q1D; ++qx)
1048 const real_t wx = massX[qx];
1049 gradXY[qy][qx][0] += wx * wDy;
1050 gradXY[qy][qx][1] += wx * wy;
1055 for (
int qz = 0; qz < Q1D; ++qz)
1057 const real_t wz = Bc(qz,dz);
1058 const real_t wDz = Gc(qz,dz);
1059 for (
int qy = 0; qy < Q1D; ++qy)
1061 for (
int qx = 0; qx < Q1D; ++qx)
1064 curl[qz][qy][qx][1] += gradXY[qy][qx][1] * wDz;
1068 curl[qz][qy][qx][2] += gradXY[qy][qx][0] * wz;
1073 curl[qz][qy][qx][2] -= gradXY[qy][qx][0] * wz;
1080 osc += D1Dx * D1Dy * D1Dz;
1085 const int D1Dz = D1D;
1086 const int D1Dy = D1D - 1;
1087 const int D1Dx = D1D;
1089 for (
int dz = 0; dz < D1Dz; ++dz)
1091 real_t gradXY[MQ1D][MQ1D][2];
1092 for (
int qy = 0; qy < Q1D; ++qy)
1094 for (
int qx = 0; qx < Q1D; ++qx)
1096 for (
int d = 0; d < 2; ++d)
1098 gradXY[qy][qx][d] = 0.0;
1103 for (
int dx = 0; dx < D1Dx; ++dx)
1106 for (
int qy = 0; qy < Q1D; ++qy)
1111 for (
int dy = 0; dy < D1Dy; ++dy)
1113 const real_t t = X(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
1114 for (
int qy = 0; qy < Q1D; ++qy)
1116 massY[qy] += t * Bo(qy,dy);
1120 for (
int qx = 0; qx < Q1D; ++qx)
1122 const real_t wx = Bc(qx,dx);
1123 const real_t wDx = Gc(qx,dx);
1124 for (
int qy = 0; qy < Q1D; ++qy)
1126 const real_t wy = massY[qy];
1127 gradXY[qy][qx][0] += wDx * wy;
1128 gradXY[qy][qx][1] += wx * wy;
1133 for (
int qz = 0; qz < Q1D; ++qz)
1135 const real_t wz = Bc(qz,dz);
1136 const real_t wDz = Gc(qz,dz);
1137 for (
int qy = 0; qy < Q1D; ++qy)
1139 for (
int qx = 0; qx < Q1D; ++qx)
1145 curl[qz][qy][qx][0] += gradXY[qy][qx][1] * wDz;
1150 curl[qz][qy][qx][0] -= gradXY[qy][qx][1] * wDz;
1152 curl[qz][qy][qx][2] += gradXY[qy][qx][0] * wz;
1158 osc += D1Dx * D1Dy * D1Dz;
1163 const int D1Dz = D1D - 1;
1164 const int D1Dy = D1D;
1165 const int D1Dx = D1D;
1167 for (
int dx = 0; dx < D1Dx; ++dx)
1169 real_t gradYZ[MQ1D][MQ1D][2];
1170 for (
int qz = 0; qz < Q1D; ++qz)
1172 for (
int qy = 0; qy < Q1D; ++qy)
1174 for (
int d = 0; d < 2; ++d)
1176 gradYZ[qz][qy][d] = 0.0;
1181 for (
int dy = 0; dy < D1Dy; ++dy)
1184 for (
int qz = 0; qz < Q1D; ++qz)
1189 for (
int dz = 0; dz < D1Dz; ++dz)
1191 const real_t t = X(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
1192 for (
int qz = 0; qz < Q1D; ++qz)
1194 massZ[qz] += t * Bo(qz,dz);
1198 for (
int qy = 0; qy < Q1D; ++qy)
1200 const real_t wy = Bc(qy,dy);
1201 const real_t wDy = Gc(qy,dy);
1202 for (
int qz = 0; qz < Q1D; ++qz)
1204 const real_t wz = massZ[qz];
1205 gradYZ[qz][qy][0] += wz * wy;
1206 gradYZ[qz][qy][1] += wz * wDy;
1211 for (
int qx = 0; qx < Q1D; ++qx)
1213 const real_t wx = Bc(qx,dx);
1214 const real_t wDx = Gc(qx,dx);
1216 for (
int qy = 0; qy < Q1D; ++qy)
1218 for (
int qz = 0; qz < Q1D; ++qz)
1221 curl[qz][qy][qx][0] += gradYZ[qz][qy][1] * wx;
1225 curl[qz][qy][qx][1] += gradYZ[qz][qy][0] * wDx;
1230 curl[qz][qy][qx][1] -= gradYZ[qz][qy][0] * wDx;
1239 for (
int qz = 0; qz < Q1D; ++qz)
1241 for (
int qy = 0; qy < Q1D; ++qy)
1243 for (
int qx = 0; qx < Q1D; ++qx)
1245 const real_t O11 = op(qx,qy,qz,0,e);
1246 const real_t O12 = op(qx,qy,qz,1,e);
1247 const real_t O13 = op(qx,qy,qz,2,e);
1248 const real_t O21 = symmetric ? O12 : op(qx,qy,qz,3,e);
1249 const real_t O22 = symmetric ? op(qx,qy,qz,3,e) : op(qx,qy,qz,4,e);
1250 const real_t O23 = symmetric ? op(qx,qy,qz,4,e) : op(qx,qy,qz,5,e);
1251 const real_t O31 = symmetric ? O13 : op(qx,qy,qz,6,e);
1252 const real_t O32 = symmetric ? O23 : op(qx,qy,qz,7,e);
1253 const real_t O33 = symmetric ? op(qx,qy,qz,5,e) : op(qx,qy,qz,8,e);
1255 const real_t c1 = (O11 * curl[qz][qy][qx][0]) + (O12 * curl[qz][qy][qx][1]) +
1256 (O13 * curl[qz][qy][qx][2]);
1257 const real_t c2 = (O21 * curl[qz][qy][qx][0]) + (O22 * curl[qz][qy][qx][1]) +
1258 (O23 * curl[qz][qy][qx][2]);
1259 const real_t c3 = (O31 * curl[qz][qy][qx][0]) + (O32 * curl[qz][qy][qx][1]) +
1260 (O33 * curl[qz][qy][qx][2]);
1262 curl[qz][qy][qx][0] = c1;
1263 curl[qz][qy][qx][1] = c2;
1264 curl[qz][qy][qx][2] = c3;
1272 const int D1Dz = D1D;
1273 const int D1Dy = D1D;
1274 const int D1Dx = D1D - 1;
1276 for (
int qz = 0; qz < Q1D; ++qz)
1278 real_t gradXY12[MD1D][MD1D];
1279 real_t gradXY21[MD1D][MD1D];
1281 for (
int dy = 0; dy < D1Dy; ++dy)
1283 for (
int dx = 0; dx < D1Dx; ++dx)
1285 gradXY12[dy][dx] = 0.0;
1286 gradXY21[dy][dx] = 0.0;
1289 for (
int qy = 0; qy < Q1D; ++qy)
1292 for (
int dx = 0; dx < D1Dx; ++dx)
1294 for (
int n = 0; n < 2; ++n)
1299 for (
int qx = 0; qx < Q1D; ++qx)
1301 for (
int dx = 0; dx < D1Dx; ++dx)
1303 const real_t wx = Bot(dx,qx);
1305 massX[dx][0] += wx * curl[qz][qy][qx][1];
1306 massX[dx][1] += wx * curl[qz][qy][qx][2];
1309 for (
int dy = 0; dy < D1Dy; ++dy)
1311 const real_t wy = Bct(dy,qy);
1312 const real_t wDy = Gct(dy,qy);
1314 for (
int dx = 0; dx < D1Dx; ++dx)
1316 gradXY21[dy][dx] += massX[dx][0] * wy;
1317 gradXY12[dy][dx] += massX[dx][1] * wDy;
1322 for (
int dz = 0; dz < D1Dz; ++dz)
1324 const real_t wz = Bct(dz,qz);
1325 const real_t wDz = Gct(dz,qz);
1326 for (
int dy = 0; dy < D1Dy; ++dy)
1328 for (
int dx = 0; dx < D1Dx; ++dx)
1331 const int idx = dx + ((dy + (dz * D1Dy)) * D1Dx) + osc;
1336 Y(idx, e) += (gradXY21[dy][dx] * wDz) +
1337 (gradXY12[dy][dx] * wz);
1343 Y(idx, e) += (gradXY21[dy][dx] * wDz) -
1344 (gradXY12[dy][dx] * wz);
1351 osc += D1Dx * D1Dy * D1Dz;
1356 const int D1Dz = D1D;
1357 const int D1Dy = D1D - 1;
1358 const int D1Dx = D1D;
1360 for (
int qz = 0; qz < Q1D; ++qz)
1362 real_t gradXY02[MD1D][MD1D];
1363 real_t gradXY20[MD1D][MD1D];
1365 for (
int dy = 0; dy < D1Dy; ++dy)
1367 for (
int dx = 0; dx < D1Dx; ++dx)
1369 gradXY02[dy][dx] = 0.0;
1370 gradXY20[dy][dx] = 0.0;
1373 for (
int qx = 0; qx < Q1D; ++qx)
1376 for (
int dy = 0; dy < D1Dy; ++dy)
1381 for (
int qy = 0; qy < Q1D; ++qy)
1383 for (
int dy = 0; dy < D1Dy; ++dy)
1385 const real_t wy = Bot(dy,qy);
1387 massY[dy][0] += wy * curl[qz][qy][qx][2];
1388 massY[dy][1] += wy * curl[qz][qy][qx][0];
1391 for (
int dx = 0; dx < D1Dx; ++dx)
1393 const real_t wx = Bct(dx,qx);
1394 const real_t wDx = Gct(dx,qx);
1396 for (
int dy = 0; dy < D1Dy; ++dy)
1398 gradXY02[dy][dx] += massY[dy][0] * wDx;
1399 gradXY20[dy][dx] += massY[dy][1] * wx;
1404 for (
int dz = 0; dz < D1Dz; ++dz)
1406 const real_t wz = Bct(dz,qz);
1407 const real_t wDz = Gct(dz,qz);
1408 for (
int dy = 0; dy < D1Dy; ++dy)
1410 for (
int dx = 0; dx < D1Dx; ++dx)
1412 const int idx = dx + ((dy + (dz * D1Dy)) * D1Dx) + osc;
1418 Y(idx, e) += (gradXY20[dy][dx] * wDz) +
1419 (gradXY02[dy][dx] * wz);
1425 Y(idx, e) += (-gradXY20[dy][dx] * wDz) +
1426 (gradXY02[dy][dx] * wz);
1433 osc += D1Dx * D1Dy * D1Dz;
1438 const int D1Dz = D1D - 1;
1439 const int D1Dy = D1D;
1440 const int D1Dx = D1D;
1442 for (
int qx = 0; qx < Q1D; ++qx)
1444 real_t gradYZ01[MD1D][MD1D];
1445 real_t gradYZ10[MD1D][MD1D];
1447 for (
int dy = 0; dy < D1Dy; ++dy)
1449 for (
int dz = 0; dz < D1Dz; ++dz)
1451 gradYZ01[dz][dy] = 0.0;
1452 gradYZ10[dz][dy] = 0.0;
1455 for (
int qy = 0; qy < Q1D; ++qy)
1458 for (
int dz = 0; dz < D1Dz; ++dz)
1460 for (
int n = 0; n < 2; ++n)
1465 for (
int qz = 0; qz < Q1D; ++qz)
1467 for (
int dz = 0; dz < D1Dz; ++dz)
1469 const real_t wz = Bot(dz,qz);
1471 massZ[dz][0] += wz * curl[qz][qy][qx][0];
1472 massZ[dz][1] += wz * curl[qz][qy][qx][1];
1475 for (
int dy = 0; dy < D1Dy; ++dy)
1477 const real_t wy = Bct(dy,qy);
1478 const real_t wDy = Gct(dy,qy);
1480 for (
int dz = 0; dz < D1Dz; ++dz)
1482 gradYZ01[dz][dy] += wy * massZ[dz][1];
1483 gradYZ10[dz][dy] += wDy * massZ[dz][0];
1488 for (
int dx = 0; dx < D1Dx; ++dx)
1490 const real_t wx = Bct(dx,qx);
1491 const real_t wDx = Gct(dx,qx);
1493 for (
int dy = 0; dy < D1Dy; ++dy)
1495 for (
int dz = 0; dz < D1Dz; ++dz)
1497 const int idx = dx + ((dy + (dz * D1Dy)) * D1Dx) + osc;
1503 Y(idx, e) += (gradYZ10[dz][dy] * wx) +
1504 (gradYZ01[dz][dy] * wDx);
1510 Y(idx, e) += (gradYZ10[dz][dy] * wx) -
1511 (gradYZ01[dz][dy] * wDx);
1522template<
int T_D1D = 0,
int T_Q1D = 0>
1523inline void SmemPACurlCurlApply3D(
const int d1d,
1525 const bool symmetric,
1527 const Array<real_t> &bo,
1528 const Array<real_t> &bc,
1529 const Array<real_t> &bot,
1530 const Array<real_t> &bct,
1531 const Array<real_t> &gc,
1532 const Array<real_t> &gct,
1533 const Vector &pa_data,
1536 const bool useAbs =
false)
1539 "Error: d1d > HCURL_MAX_D1D");
1541 "Error: q1d > HCURL_MAX_Q1D");
1542 const int D1D = T_D1D ? T_D1D : d1d;
1543 const int Q1D = T_Q1D ? T_Q1D : q1d;
1551 auto Bo =
Reshape(bo.Read(), Q1D, D1D-1);
1552 auto Bc =
Reshape(bc.Read(), Q1D, D1D);
1553 auto Gc =
Reshape(gc.Read(), Q1D, D1D);
1554 auto op =
Reshape(pa_data.Read(), Q1D, Q1D, Q1D, symmetric ? 6 : 9, NE);
1555 auto X =
Reshape(x.Read(), 3*(D1D-1)*D1D*D1D, NE);
1556 auto Y =
Reshape(y.ReadWrite(), 3*(D1D-1)*D1D*D1D, NE);
1558 const int s = symmetric ? 6 : 9;
1560 auto device_kernel = [=] MFEM_DEVICE (
int e)
1562 constexpr int VDIM = 3;
1563 constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
1564 constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
1565 const int D1D = T_D1D ? T_D1D : d1d;
1566 const int Q1D = T_Q1D ? T_Q1D : q1d;
1568 MFEM_SHARED
real_t sBo[MD1D][MQ1D];
1569 MFEM_SHARED
real_t sBc[MD1D][MQ1D];
1570 MFEM_SHARED
real_t sGc[MD1D][MQ1D];
1573 MFEM_SHARED
real_t sop[9][MQ1D][MQ1D];
1574 MFEM_SHARED
real_t curl[MQ1D][MQ1D][3];
1576 MFEM_SHARED
real_t sX[MD1D][MD1D][MD1D];
1578 MFEM_FOREACH_THREAD(qx,x,Q1D)
1580 MFEM_FOREACH_THREAD(qy,y,Q1D)
1582 MFEM_FOREACH_THREAD(qz,z,Q1D)
1584 for (
int i=0; i<s; ++i)
1586 ope[i] = op(qx,qy,qz,i,e);
1592 const int tidx = MFEM_THREAD_ID(x);
1593 const int tidy = MFEM_THREAD_ID(y);
1594 const int tidz = MFEM_THREAD_ID(z);
1598 MFEM_FOREACH_THREAD(d,y,D1D)
1600 MFEM_FOREACH_THREAD(q,x,Q1D)
1602 sBc[d][q] = Bc(q,d);
1603 sGc[d][q] = Gc(q,d);
1606 sBo[d][q] = Bo(q,d);
1613 for (
int qz=0; qz < Q1D; ++qz)
1617 MFEM_FOREACH_THREAD(qy,y,Q1D)
1619 MFEM_FOREACH_THREAD(qx,x,Q1D)
1621 for (
int i=0; i<3; ++i)
1623 curl[qy][qx][i] = 0.0;
1630 for (
int c = 0; c < VDIM; ++c)
1632 const int D1Dz = (c == 2) ? D1D - 1 : D1D;
1633 const int D1Dy = (c == 1) ? D1D - 1 : D1D;
1634 const int D1Dx = (c == 0) ? D1D - 1 : D1D;
1636 MFEM_FOREACH_THREAD(dz,z,D1Dz)
1638 MFEM_FOREACH_THREAD(dy,y,D1Dy)
1640 MFEM_FOREACH_THREAD(dx,x,D1Dx)
1642 sX[dz][dy][dx] = X(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
1652 for (
int i=0; i<s; ++i)
1654 sop[i][tidx][tidy] = ope[i];
1658 MFEM_FOREACH_THREAD(qy,y,Q1D)
1660 MFEM_FOREACH_THREAD(qx,x,Q1D)
1670 for (
int dz = 0; dz < D1Dz; ++dz)
1672 const real_t wz = sBc[dz][qz];
1673 const real_t wDz = sGc[dz][qz];
1675 for (
int dy = 0; dy < D1Dy; ++dy)
1677 const real_t wy = sBc[dy][qy];
1678 const real_t wDy = sGc[dy][qy];
1680 for (
int dx = 0; dx < D1Dx; ++dx)
1682 const real_t wx = sX[dz][dy][dx] * sBo[dx][qx];
1689 curl[qy][qx][1] += v;
1690 if (useAbs) { curl[qy][qx][2] +=
u; }
1691 else { curl[qy][qx][2] -=
u; }
1697 for (
int dz = 0; dz < D1Dz; ++dz)
1699 const real_t wz = sBc[dz][qz];
1700 const real_t wDz = sGc[dz][qz];
1702 for (
int dy = 0; dy < D1Dy; ++dy)
1704 const real_t wy = sBo[dy][qy];
1706 for (
int dx = 0; dx < D1Dx; ++dx)
1708 const real_t t = sX[dz][dy][dx];
1709 const real_t wx = t * sBc[dx][qx];
1710 const real_t wDx = t * sGc[dx][qx];
1718 if (useAbs) { curl[qy][qx][0] += v; }
1719 else { curl[qy][qx][0] -= v; }
1720 curl[qy][qx][2] +=
u;
1726 for (
int dz = 0; dz < D1Dz; ++dz)
1728 const real_t wz = sBo[dz][qz];
1730 for (
int dy = 0; dy < D1Dy; ++dy)
1732 const real_t wy = sBc[dy][qy];
1733 const real_t wDy = sGc[dy][qy];
1735 for (
int dx = 0; dx < D1Dx; ++dx)
1737 const real_t t = sX[dz][dy][dx];
1738 const real_t wx = t * sBc[dx][qx];
1739 const real_t wDx = t * sGc[dx][qx];
1747 curl[qy][qx][0] += v;
1748 if (useAbs) { curl[qy][qx][1] +=
u; }
1749 else { curl[qy][qx][1] -=
u; }
1755 osc += D1Dx * D1Dy * D1Dz;
1763 MFEM_FOREACH_THREAD(dz,z,D1D)
1765 const real_t wcz = sBc[dz][qz];
1766 const real_t wcDz = sGc[dz][qz];
1767 const real_t wz = (dz < D1D-1) ? sBo[dz][qz] : 0.0;
1769 MFEM_FOREACH_THREAD(dy,y,D1D)
1771 MFEM_FOREACH_THREAD(dx,x,D1D)
1773 for (
int qy = 0; qy < Q1D; ++qy)
1775 const real_t wcy = sBc[dy][qy];
1776 const real_t wcDy = sGc[dy][qy];
1777 const real_t wy = (dy < D1D-1) ? sBo[dy][qy] : 0.0;
1779 for (
int qx = 0; qx < Q1D; ++qx)
1781 const real_t O11 = sop[0][qx][qy];
1782 const real_t O12 = sop[1][qx][qy];
1783 const real_t O13 = sop[2][qx][qy];
1784 const real_t O21 = symmetric ? O12 : sop[3][qx][qy];
1785 const real_t O22 = symmetric ? sop[3][qx][qy] : sop[4][qx][qy];
1786 const real_t O23 = symmetric ? sop[4][qx][qy] : sop[5][qx][qy];
1787 const real_t O31 = symmetric ? O13 : sop[6][qx][qy];
1788 const real_t O32 = symmetric ? O23 : sop[7][qx][qy];
1789 const real_t O33 = symmetric ? sop[5][qx][qy] : sop[8][qx][qy];
1791 const real_t c1 = (O11 * curl[qy][qx][0]) + (O12 * curl[qy][qx][1]) +
1792 (O13 * curl[qy][qx][2]);
1793 const real_t c2 = (O21 * curl[qy][qx][0]) + (O22 * curl[qy][qx][1]) +
1794 (O23 * curl[qy][qx][2]);
1795 const real_t c3 = (O31 * curl[qy][qx][0]) + (O32 * curl[qy][qx][1]) +
1796 (O33 * curl[qy][qx][2]);
1798 const real_t wcx = sBc[dx][qx];
1799 const real_t wDx = sGc[dx][qx];
1804 const real_t wx = sBo[dx][qx];
1809 dxyz1 += (wx * c2 * wcy * wcDz) +
1810 (wx * c3 * wcDy * wcz);
1816 dxyz1 += (wx * c2 * wcy * wcDz) -
1817 (wx * c3 * wcDy * wcz);
1826 dxyz2 += (wy * c1 * wcx * wcDz) +
1827 (wy * c3 * wDx * wcz);
1833 dxyz2 += (-wy * c1 * wcx * wcDz) +
1834 (wy * c3 * wDx * wcz);
1842 dxyz3 += (wcDy * wz * c1 * wcx) +
1843 (wcy * wz * c2 * wDx);
1849 dxyz3 += (wcDy * wz * c1 * wcx) -
1850 (wcy * wz * c2 * wDx);
1860 MFEM_FOREACH_THREAD(dz,z,D1D)
1862 MFEM_FOREACH_THREAD(dy,y,D1D)
1864 MFEM_FOREACH_THREAD(dx,x,D1D)
1868 Y(dx + ((dy + (dz * D1D)) * (D1D-1)), e) += dxyz1;
1872 Y(dx + ((dy + (dz * (D1D-1))) * D1D) + ((D1D-1)*D1D*D1D), e) += dxyz2;
1876 Y(dx + ((dy + (dz * D1D)) * D1D) + (2*(D1D-1)*D1D*D1D), e) += dxyz3;
1884 auto host_kernel = [&] MFEM_LAMBDA (
int)
1886 MFEM_ABORT_KERNEL(
"This kernel should only be used on GPU.");
1889 ForallWrap<3>(
true, NE, device_kernel, host_kernel, Q1D, Q1D, Q1D);
1893void PAHcurlL2Setup2D(
const int Q1D,
1895 const Array<real_t> &w,
1900void PAHcurlL2IntSetup2D(
const int Q1D,
const int NE,
const Array<real_t> &w,
1901 Vector &coeff,
const Vector &detJ, Vector &op);
1904void PAHcurlL2Setup3D(
const int NQ,
1907 const Array<real_t> &w,
1912void PAHcurlL2Apply2D(
const int D1D,
1916 const Array<real_t> &bo,
1917 const Array<real_t> &bot,
1918 const Array<real_t> &bt,
1919 const Array<real_t> &gc,
1920 const Vector &pa_data,
1925void PAHcurlL2ApplyTranspose2D(
const int D1D,
1929 const Array<real_t> &bo,
1930 const Array<real_t> &bot,
1931 const Array<real_t> &
b,
1932 const Array<real_t> &gct,
1933 const Vector &pa_data,
1938template<
int T_D1D = 0,
int T_Q1D = 0>
1939inline void PAHcurlL2Apply3D(
const int d1d,
1943 const Array<real_t> &bo,
1944 const Array<real_t> &bc,
1945 const Array<real_t> &bot,
1946 const Array<real_t> &bct,
1947 const Array<real_t> &gc,
1948 const Vector &pa_data,
1953 "Error: d1d > HCURL_MAX_D1D");
1955 "Error: q1d > HCURL_MAX_Q1D");
1956 const int D1D = T_D1D ? T_D1D : d1d;
1957 const int Q1D = T_Q1D ? T_Q1D : q1d;
1959 auto Bo =
Reshape(bo.Read(), Q1D, D1D-1);
1960 auto Bc =
Reshape(bc.Read(), Q1D, D1D);
1961 auto Bot =
Reshape(bot.Read(), D1D-1, Q1D);
1962 auto Bct =
Reshape(bct.Read(), D1D, Q1D);
1963 auto Gc =
Reshape(gc.Read(), Q1D, D1D);
1964 auto op =
Reshape(pa_data.Read(), coeffDim, Q1D, Q1D, Q1D, NE);
1965 auto X =
Reshape(x.Read(), 3*(D1D-1)*D1D*D1D, NE);
1966 auto Y =
Reshape(y.ReadWrite(), 3*(D1D-1)*D1D*D1D, NE);
1979 constexpr int VDIM = 3;
1980 constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
1981 constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
1982 const int D1D = T_D1D ? T_D1D : d1d;
1983 const int Q1D = T_Q1D ? T_Q1D : q1d;
1985 real_t curl[MQ1D][MQ1D][MQ1D][VDIM];
1988 for (
int qz = 0; qz < Q1D; ++qz)
1990 for (
int qy = 0; qy < Q1D; ++qy)
1992 for (
int qx = 0; qx < Q1D; ++qx)
1994 for (
int c = 0; c < VDIM; ++c)
1996 curl[qz][qy][qx][c] = 0.0;
2008 const int D1Dz = D1D;
2009 const int D1Dy = D1D;
2010 const int D1Dx = D1D - 1;
2012 for (
int dz = 0; dz < D1Dz; ++dz)
2014 real_t gradXY[MQ1D][MQ1D][2];
2015 for (
int qy = 0; qy < Q1D; ++qy)
2017 for (
int qx = 0; qx < Q1D; ++qx)
2019 for (
int d = 0; d < 2; ++d)
2021 gradXY[qy][qx][d] = 0.0;
2026 for (
int dy = 0; dy < D1Dy; ++dy)
2029 for (
int qx = 0; qx < Q1D; ++qx)
2034 for (
int dx = 0; dx < D1Dx; ++dx)
2036 const real_t t = X(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
2037 for (
int qx = 0; qx < Q1D; ++qx)
2039 massX[qx] += t * Bo(qx,dx);
2043 for (
int qy = 0; qy < Q1D; ++qy)
2045 const real_t wy = Bc(qy,dy);
2046 const real_t wDy = Gc(qy,dy);
2047 for (
int qx = 0; qx < Q1D; ++qx)
2049 const real_t wx = massX[qx];
2050 gradXY[qy][qx][0] += wx * wDy;
2051 gradXY[qy][qx][1] += wx * wy;
2056 for (
int qz = 0; qz < Q1D; ++qz)
2058 const real_t wz = Bc(qz,dz);
2059 const real_t wDz = Gc(qz,dz);
2060 for (
int qy = 0; qy < Q1D; ++qy)
2062 for (
int qx = 0; qx < Q1D; ++qx)
2065 curl[qz][qy][qx][1] += gradXY[qy][qx][1] * wDz;
2066 curl[qz][qy][qx][2] -= gradXY[qy][qx][0] * wz;
2072 osc += D1Dx * D1Dy * D1Dz;
2077 const int D1Dz = D1D;
2078 const int D1Dy = D1D - 1;
2079 const int D1Dx = D1D;
2081 for (
int dz = 0; dz < D1Dz; ++dz)
2083 real_t gradXY[MQ1D][MQ1D][2];
2084 for (
int qy = 0; qy < Q1D; ++qy)
2086 for (
int qx = 0; qx < Q1D; ++qx)
2088 for (
int d = 0; d < 2; ++d)
2090 gradXY[qy][qx][d] = 0.0;
2095 for (
int dx = 0; dx < D1Dx; ++dx)
2098 for (
int qy = 0; qy < Q1D; ++qy)
2103 for (
int dy = 0; dy < D1Dy; ++dy)
2105 const real_t t = X(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
2106 for (
int qy = 0; qy < Q1D; ++qy)
2108 massY[qy] += t * Bo(qy,dy);
2112 for (
int qx = 0; qx < Q1D; ++qx)
2114 const real_t wx = Bc(qx,dx);
2115 const real_t wDx = Gc(qx,dx);
2116 for (
int qy = 0; qy < Q1D; ++qy)
2118 const real_t wy = massY[qy];
2119 gradXY[qy][qx][0] += wDx * wy;
2120 gradXY[qy][qx][1] += wx * wy;
2125 for (
int qz = 0; qz < Q1D; ++qz)
2127 const real_t wz = Bc(qz,dz);
2128 const real_t wDz = Gc(qz,dz);
2129 for (
int qy = 0; qy < Q1D; ++qy)
2131 for (
int qx = 0; qx < Q1D; ++qx)
2134 curl[qz][qy][qx][0] -= gradXY[qy][qx][1] * wDz;
2135 curl[qz][qy][qx][2] += gradXY[qy][qx][0] * wz;
2141 osc += D1Dx * D1Dy * D1Dz;
2146 const int D1Dz = D1D - 1;
2147 const int D1Dy = D1D;
2148 const int D1Dx = D1D;
2150 for (
int dx = 0; dx < D1Dx; ++dx)
2152 real_t gradYZ[MQ1D][MQ1D][2];
2153 for (
int qz = 0; qz < Q1D; ++qz)
2155 for (
int qy = 0; qy < Q1D; ++qy)
2157 for (
int d = 0; d < 2; ++d)
2159 gradYZ[qz][qy][d] = 0.0;
2164 for (
int dy = 0; dy < D1Dy; ++dy)
2167 for (
int qz = 0; qz < Q1D; ++qz)
2172 for (
int dz = 0; dz < D1Dz; ++dz)
2174 const real_t t = X(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
2175 for (
int qz = 0; qz < Q1D; ++qz)
2177 massZ[qz] += t * Bo(qz,dz);
2181 for (
int qy = 0; qy < Q1D; ++qy)
2183 const real_t wy = Bc(qy,dy);
2184 const real_t wDy = Gc(qy,dy);
2185 for (
int qz = 0; qz < Q1D; ++qz)
2187 const real_t wz = massZ[qz];
2188 gradYZ[qz][qy][0] += wz * wy;
2189 gradYZ[qz][qy][1] += wz * wDy;
2194 for (
int qx = 0; qx < Q1D; ++qx)
2196 const real_t wx = Bc(qx,dx);
2197 const real_t wDx = Gc(qx,dx);
2199 for (
int qy = 0; qy < Q1D; ++qy)
2201 for (
int qz = 0; qz < Q1D; ++qz)
2204 curl[qz][qy][qx][0] += gradYZ[qz][qy][1] * wx;
2205 curl[qz][qy][qx][1] -= gradYZ[qz][qy][0] * wDx;
2213 for (
int qz = 0; qz < Q1D; ++qz)
2215 for (
int qy = 0; qy < Q1D; ++qy)
2217 for (
int qx = 0; qx < Q1D; ++qx)
2219 const real_t O11 = op(0,qx,qy,qz,e);
2222 for (
int c = 0; c < VDIM; ++c)
2224 curl[qz][qy][qx][c] *= O11;
2229 const real_t O21 = op(1,qx,qy,qz,e);
2230 const real_t O31 = op(2,qx,qy,qz,e);
2231 const real_t O12 = op(3,qx,qy,qz,e);
2232 const real_t O22 = op(4,qx,qy,qz,e);
2233 const real_t O32 = op(5,qx,qy,qz,e);
2234 const real_t O13 = op(6,qx,qy,qz,e);
2235 const real_t O23 = op(7,qx,qy,qz,e);
2236 const real_t O33 = op(8,qx,qy,qz,e);
2237 const real_t curlX = curl[qz][qy][qx][0];
2238 const real_t curlY = curl[qz][qy][qx][1];
2239 const real_t curlZ = curl[qz][qy][qx][2];
2240 curl[qz][qy][qx][0] = (O11*curlX)+(O12*curlY)+(O13*curlZ);
2241 curl[qz][qy][qx][1] = (O21*curlX)+(O22*curlY)+(O23*curlZ);
2242 curl[qz][qy][qx][2] = (O31*curlX)+(O32*curlY)+(O33*curlZ);
2248 for (
int qz = 0; qz < Q1D; ++qz)
2250 real_t massXY[MD1D][MD1D];
2254 for (
int c = 0; c < VDIM; ++c)
2256 const int D1Dz = (c == 2) ? D1D - 1 : D1D;
2257 const int D1Dy = (c == 1) ? D1D - 1 : D1D;
2258 const int D1Dx = (c == 0) ? D1D - 1 : D1D;
2260 for (
int dy = 0; dy < D1Dy; ++dy)
2262 for (
int dx = 0; dx < D1Dx; ++dx)
2267 for (
int qy = 0; qy < Q1D; ++qy)
2270 for (
int dx = 0; dx < D1Dx; ++dx)
2274 for (
int qx = 0; qx < Q1D; ++qx)
2276 for (
int dx = 0; dx < D1Dx; ++dx)
2278 massX[dx] += curl[qz][qy][qx][c] * ((c == 0) ? Bot(dx,qx) : Bct(dx,qx));
2282 for (
int dy = 0; dy < D1Dy; ++dy)
2284 const real_t wy = (c == 1) ? Bot(dy,qy) : Bct(dy,qy);
2285 for (
int dx = 0; dx < D1Dx; ++dx)
2287 massXY[dy][dx] += massX[dx] * wy;
2292 for (
int dz = 0; dz < D1Dz; ++dz)
2294 const real_t wz = (c == 2) ? Bot(dz,qz) : Bct(dz,qz);
2295 for (
int dy = 0; dy < D1Dy; ++dy)
2297 for (
int dx = 0; dx < D1Dx; ++dx)
2299 Y(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e) += massXY[dy][dx] * wz;
2304 osc += D1Dx * D1Dy * D1Dz;
2311template<
int T_D1D = 0,
int T_Q1D = 0>
2312inline void SmemPAHcurlL2Apply3D(
const int d1d,
2316 const Array<real_t> &bo,
2317 const Array<real_t> &bc,
2318 const Array<real_t> &gc,
2319 const Vector &pa_data,
2324 "Error: d1d > HCURL_MAX_D1D");
2326 "Error: q1d > HCURL_MAX_Q1D");
2327 const int D1D = T_D1D ? T_D1D : d1d;
2328 const int Q1D = T_Q1D ? T_Q1D : q1d;
2330 auto Bo =
Reshape(bo.Read(), Q1D, D1D-1);
2331 auto Bc =
Reshape(bc.Read(), Q1D, D1D);
2332 auto Gc =
Reshape(gc.Read(), Q1D, D1D);
2333 auto op =
Reshape(pa_data.Read(), coeffDim, Q1D, Q1D, Q1D, NE);
2334 auto X =
Reshape(x.Read(), 3*(D1D-1)*D1D*D1D, NE);
2335 auto Y =
Reshape(y.ReadWrite(), 3*(D1D-1)*D1D*D1D, NE);
2337 auto device_kernel = [=] MFEM_DEVICE (
int e)
2339 constexpr int VDIM = 3;
2340 constexpr int maxCoeffDim = 9;
2341 constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
2342 constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
2343 const int D1D = T_D1D ? T_D1D : d1d;
2344 const int Q1D = T_Q1D ? T_Q1D : q1d;
2346 MFEM_SHARED
real_t sBo[MD1D][MQ1D];
2347 MFEM_SHARED
real_t sBc[MD1D][MQ1D];
2348 MFEM_SHARED
real_t sGc[MD1D][MQ1D];
2351 MFEM_SHARED
real_t sop[maxCoeffDim][MQ1D][MQ1D];
2352 MFEM_SHARED
real_t curl[MQ1D][MQ1D][3];
2354 MFEM_SHARED
real_t sX[MD1D][MD1D][MD1D];
2356 MFEM_FOREACH_THREAD(qx,x,Q1D)
2358 MFEM_FOREACH_THREAD(qy,y,Q1D)
2360 MFEM_FOREACH_THREAD(qz,z,Q1D)
2362 for (
int i=0; i<coeffDim; ++i)
2364 opc[i] = op(i,qx,qy,qz,e);
2370 const int tidx = MFEM_THREAD_ID(x);
2371 const int tidy = MFEM_THREAD_ID(y);
2372 const int tidz = MFEM_THREAD_ID(z);
2376 MFEM_FOREACH_THREAD(d,y,D1D)
2378 MFEM_FOREACH_THREAD(q,x,Q1D)
2380 sBc[d][q] = Bc(q,d);
2381 sGc[d][q] = Gc(q,d);
2384 sBo[d][q] = Bo(q,d);
2391 for (
int qz=0; qz < Q1D; ++qz)
2395 MFEM_FOREACH_THREAD(qy,y,Q1D)
2397 MFEM_FOREACH_THREAD(qx,x,Q1D)
2399 for (
int i=0; i<3; ++i)
2401 curl[qy][qx][i] = 0.0;
2408 for (
int c = 0; c < VDIM; ++c)
2410 const int D1Dz = (c == 2) ? D1D - 1 : D1D;
2411 const int D1Dy = (c == 1) ? D1D - 1 : D1D;
2412 const int D1Dx = (c == 0) ? D1D - 1 : D1D;
2414 MFEM_FOREACH_THREAD(dz,z,D1Dz)
2416 MFEM_FOREACH_THREAD(dy,y,D1Dy)
2418 MFEM_FOREACH_THREAD(dx,x,D1Dx)
2420 sX[dz][dy][dx] = X(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
2430 for (
int i=0; i<coeffDim; ++i)
2432 sop[i][tidx][tidy] = opc[i];
2436 MFEM_FOREACH_THREAD(qy,y,Q1D)
2438 MFEM_FOREACH_THREAD(qx,x,Q1D)
2448 for (
int dz = 0; dz < D1Dz; ++dz)
2450 const real_t wz = sBc[dz][qz];
2451 const real_t wDz = sGc[dz][qz];
2453 for (
int dy = 0; dy < D1Dy; ++dy)
2455 const real_t wy = sBc[dy][qy];
2456 const real_t wDy = sGc[dy][qy];
2458 for (
int dx = 0; dx < D1Dx; ++dx)
2460 const real_t wx = sX[dz][dy][dx] * sBo[dx][qx];
2467 curl[qy][qx][1] += v;
2468 curl[qy][qx][2] -=
u;
2474 for (
int dz = 0; dz < D1Dz; ++dz)
2476 const real_t wz = sBc[dz][qz];
2477 const real_t wDz = sGc[dz][qz];
2479 for (
int dy = 0; dy < D1Dy; ++dy)
2481 const real_t wy = sBo[dy][qy];
2483 for (
int dx = 0; dx < D1Dx; ++dx)
2485 const real_t t = sX[dz][dy][dx];
2486 const real_t wx = t * sBc[dx][qx];
2487 const real_t wDx = t * sGc[dx][qx];
2495 curl[qy][qx][0] -= v;
2496 curl[qy][qx][2] +=
u;
2502 for (
int dz = 0; dz < D1Dz; ++dz)
2504 const real_t wz = sBo[dz][qz];
2506 for (
int dy = 0; dy < D1Dy; ++dy)
2508 const real_t wy = sBc[dy][qy];
2509 const real_t wDy = sGc[dy][qy];
2511 for (
int dx = 0; dx < D1Dx; ++dx)
2513 const real_t t = sX[dz][dy][dx];
2514 const real_t wx = t * sBc[dx][qx];
2515 const real_t wDx = t * sGc[dx][qx];
2523 curl[qy][qx][0] += v;
2524 curl[qy][qx][1] -=
u;
2530 osc += D1Dx * D1Dy * D1Dz;
2538 MFEM_FOREACH_THREAD(dz,z,D1D)
2540 const real_t wcz = sBc[dz][qz];
2541 const real_t wz = (dz < D1D-1) ? sBo[dz][qz] : 0.0;
2543 MFEM_FOREACH_THREAD(dy,y,D1D)
2545 MFEM_FOREACH_THREAD(dx,x,D1D)
2547 for (
int qy = 0; qy < Q1D; ++qy)
2549 const real_t wcy = sBc[dy][qy];
2550 const real_t wy = (dy < D1D-1) ? sBo[dy][qy] : 0.0;
2552 for (
int qx = 0; qx < Q1D; ++qx)
2554 const real_t O11 = sop[0][qx][qy];
2558 c1 = O11 * curl[qy][qx][0];
2559 c2 = O11 * curl[qy][qx][1];
2560 c3 = O11 * curl[qy][qx][2];
2564 const real_t O21 = sop[1][qx][qy];
2565 const real_t O31 = sop[2][qx][qy];
2566 const real_t O12 = sop[3][qx][qy];
2567 const real_t O22 = sop[4][qx][qy];
2568 const real_t O32 = sop[5][qx][qy];
2569 const real_t O13 = sop[6][qx][qy];
2570 const real_t O23 = sop[7][qx][qy];
2571 const real_t O33 = sop[8][qx][qy];
2572 c1 = (O11*curl[qy][qx][0])+(O12*curl[qy][qx][1])+(O13*curl[qy][qx][2]);
2573 c2 = (O21*curl[qy][qx][0])+(O22*curl[qy][qx][1])+(O23*curl[qy][qx][2]);
2574 c3 = (O31*curl[qy][qx][0])+(O32*curl[qy][qx][1])+(O33*curl[qy][qx][2]);
2577 const real_t wcx = sBc[dx][qx];
2581 const real_t wx = sBo[dx][qx];
2582 dxyz1 += c1 * wx * wcy * wcz;
2585 dxyz2 += c2 * wcx * wy * wcz;
2586 dxyz3 += c3 * wcx * wcy * wz;
2595 MFEM_FOREACH_THREAD(dz,z,D1D)
2597 MFEM_FOREACH_THREAD(dy,y,D1D)
2599 MFEM_FOREACH_THREAD(dx,x,D1D)
2603 Y(dx + ((dy + (dz * D1D)) * (D1D-1)), e) += dxyz1;
2607 Y(dx + ((dy + (dz * (D1D-1))) * D1D) + ((D1D-1)*D1D*D1D), e) += dxyz2;
2611 Y(dx + ((dy + (dz * D1D)) * D1D) + (2*(D1D-1)*D1D*D1D), e) += dxyz3;
2619 auto host_kernel = [&] MFEM_LAMBDA (
int)
2621 MFEM_ABORT_KERNEL(
"This kernel should only be used on GPU.");
2624 ForallWrap<3>(
true, NE, device_kernel, host_kernel, Q1D, Q1D, Q1D);
2628template<
int T_D1D = 0,
int T_Q1D = 0>
2629inline void PAHcurlL2ApplyTranspose3D(
const int d1d,
2633 const Array<real_t> &bo,
2634 const Array<real_t> &bc,
2635 const Array<real_t> &bot,
2636 const Array<real_t> &bct,
2637 const Array<real_t> &gct,
2638 const Vector &pa_data,
2644 "Error: d1d > HCURL_MAX_D1D");
2646 "Error: q1d > HCURL_MAX_Q1D");
2647 const int D1D = T_D1D ? T_D1D : d1d;
2648 const int Q1D = T_Q1D ? T_Q1D : q1d;
2650 auto Bo =
Reshape(bo.Read(), Q1D, D1D-1);
2651 auto Bc =
Reshape(bc.Read(), Q1D, D1D);
2652 auto Bot =
Reshape(bot.Read(), D1D-1, Q1D);
2653 auto Bct =
Reshape(bct.Read(), D1D, Q1D);
2654 auto Gct =
Reshape(gct.Read(), D1D, Q1D);
2655 auto op =
Reshape(pa_data.Read(), coeffDim, Q1D, Q1D, Q1D, NE);
2656 auto X =
Reshape(x.Read(), 3*(D1D-1)*D1D*D1D, NE);
2657 auto Y =
Reshape(y.ReadWrite(), 3*(D1D-1)*D1D*D1D, NE);
2661 constexpr int VDIM = 3;
2662 constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
2663 constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
2664 const int D1D = T_D1D ? T_D1D : d1d;
2665 const int Q1D = T_Q1D ? T_Q1D : q1d;
2669 for (
int qz = 0; qz < Q1D; ++qz)
2671 for (
int qy = 0; qy < Q1D; ++qy)
2673 for (
int qx = 0; qx < Q1D; ++qx)
2675 for (
int c = 0; c < VDIM; ++c)
2677 mass[qz][qy][qx][c] = 0.0;
2685 for (
int c = 0; c < VDIM; ++c)
2687 const int D1Dz = (c == 2) ? D1D - 1 : D1D;
2688 const int D1Dy = (c == 1) ? D1D - 1 : D1D;
2689 const int D1Dx = (c == 0) ? D1D - 1 : D1D;
2691 for (
int dz = 0; dz < D1Dz; ++dz)
2693 real_t massXY[MQ1D][MQ1D];
2694 for (
int qy = 0; qy < Q1D; ++qy)
2696 for (
int qx = 0; qx < Q1D; ++qx)
2698 massXY[qy][qx] = 0.0;
2702 for (
int dy = 0; dy < D1Dy; ++dy)
2705 for (
int qx = 0; qx < Q1D; ++qx)
2710 for (
int dx = 0; dx < D1Dx; ++dx)
2712 const real_t t = X(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
2713 for (
int qx = 0; qx < Q1D; ++qx)
2715 massX[qx] += t * ((c == 0) ? Bo(qx,dx) : Bc(qx,dx));
2719 for (
int qy = 0; qy < Q1D; ++qy)
2721 const real_t wy = (c == 1) ? Bo(qy,dy) : Bc(qy,dy);
2722 for (
int qx = 0; qx < Q1D; ++qx)
2724 const real_t wx = massX[qx];
2725 massXY[qy][qx] += wx * wy;
2730 for (
int qz = 0; qz < Q1D; ++qz)
2732 const real_t wz = (c == 2) ? Bo(qz,dz) : Bc(qz,dz);
2733 for (
int qy = 0; qy < Q1D; ++qy)
2735 for (
int qx = 0; qx < Q1D; ++qx)
2737 mass[qz][qy][qx][c] += massXY[qy][qx] * wz;
2743 osc += D1Dx * D1Dy * D1Dz;
2747 for (
int qz = 0; qz < Q1D; ++qz)
2749 for (
int qy = 0; qy < Q1D; ++qy)
2751 for (
int qx = 0; qx < Q1D; ++qx)
2753 const real_t O11 = op(0,qx,qy,qz,e);
2756 for (
int c = 0; c < VDIM; ++c)
2758 mass[qz][qy][qx][c] *= O11;
2763 const real_t O12 = op(1,qx,qy,qz,e);
2764 const real_t O13 = op(2,qx,qy,qz,e);
2765 const real_t O21 = op(3,qx,qy,qz,e);
2766 const real_t O22 = op(4,qx,qy,qz,e);
2767 const real_t O23 = op(5,qx,qy,qz,e);
2768 const real_t O31 = op(6,qx,qy,qz,e);
2769 const real_t O32 = op(7,qx,qy,qz,e);
2770 const real_t O33 = op(8,qx,qy,qz,e);
2774 mass[qz][qy][qx][0] = (O11*massX)+(O12*massY)+(O13*massZ);
2775 mass[qz][qy][qx][1] = (O21*massX)+(O22*massY)+(O23*massZ);
2776 mass[qz][qy][qx][2] = (O31*massX)+(O32*massY)+(O33*massZ);
2785 const int D1Dz = D1D;
2786 const int D1Dy = D1D;
2787 const int D1Dx = D1D - 1;
2789 for (
int qz = 0; qz < Q1D; ++qz)
2791 real_t gradXY12[MD1D][MD1D];
2792 real_t gradXY21[MD1D][MD1D];
2794 for (
int dy = 0; dy < D1Dy; ++dy)
2796 for (
int dx = 0; dx < D1Dx; ++dx)
2798 gradXY12[dy][dx] = 0.0;
2799 gradXY21[dy][dx] = 0.0;
2802 for (
int qy = 0; qy < Q1D; ++qy)
2805 for (
int dx = 0; dx < D1Dx; ++dx)
2807 for (
int n = 0; n < 2; ++n)
2812 for (
int qx = 0; qx < Q1D; ++qx)
2814 for (
int dx = 0; dx < D1Dx; ++dx)
2816 const real_t wx = Bot(dx,qx);
2818 massX[dx][0] += wx *
mass[qz][qy][qx][1];
2819 massX[dx][1] += wx *
mass[qz][qy][qx][2];
2822 for (
int dy = 0; dy < D1Dy; ++dy)
2824 const real_t wy = Bct(dy,qy);
2825 const real_t wDy = Gct(dy,qy);
2827 for (
int dx = 0; dx < D1Dx; ++dx)
2829 gradXY21[dy][dx] += massX[dx][0] * wy;
2830 gradXY12[dy][dx] += massX[dx][1] * wDy;
2835 for (
int dz = 0; dz < D1Dz; ++dz)
2837 const real_t wz = Bct(dz,qz);
2838 const real_t wDz = Gct(dz,qz);
2839 for (
int dy = 0; dy < D1Dy; ++dy)
2841 for (
int dx = 0; dx < D1Dx; ++dx)
2845 Y(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc,
2846 e) += (gradXY21[dy][dx] * wDz) - (gradXY12[dy][dx] * wz);
2852 osc += D1Dx * D1Dy * D1Dz;
2857 const int D1Dz = D1D;
2858 const int D1Dy = D1D - 1;
2859 const int D1Dx = D1D;
2861 for (
int qz = 0; qz < Q1D; ++qz)
2863 real_t gradXY02[MD1D][MD1D];
2864 real_t gradXY20[MD1D][MD1D];
2866 for (
int dy = 0; dy < D1Dy; ++dy)
2868 for (
int dx = 0; dx < D1Dx; ++dx)
2870 gradXY02[dy][dx] = 0.0;
2871 gradXY20[dy][dx] = 0.0;
2874 for (
int qx = 0; qx < Q1D; ++qx)
2877 for (
int dy = 0; dy < D1Dy; ++dy)
2882 for (
int qy = 0; qy < Q1D; ++qy)
2884 for (
int dy = 0; dy < D1Dy; ++dy)
2886 const real_t wy = Bot(dy,qy);
2888 massY[dy][0] += wy *
mass[qz][qy][qx][2];
2889 massY[dy][1] += wy *
mass[qz][qy][qx][0];
2892 for (
int dx = 0; dx < D1Dx; ++dx)
2894 const real_t wx = Bct(dx,qx);
2895 const real_t wDx = Gct(dx,qx);
2897 for (
int dy = 0; dy < D1Dy; ++dy)
2899 gradXY02[dy][dx] += massY[dy][0] * wDx;
2900 gradXY20[dy][dx] += massY[dy][1] * wx;
2905 for (
int dz = 0; dz < D1Dz; ++dz)
2907 const real_t wz = Bct(dz,qz);
2908 const real_t wDz = Gct(dz,qz);
2909 for (
int dy = 0; dy < D1Dy; ++dy)
2911 for (
int dx = 0; dx < D1Dx; ++dx)
2915 Y(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc,
2916 e) += (-gradXY20[dy][dx] * wDz) + (gradXY02[dy][dx] * wz);
2922 osc += D1Dx * D1Dy * D1Dz;
2927 const int D1Dz = D1D - 1;
2928 const int D1Dy = D1D;
2929 const int D1Dx = D1D;
2931 for (
int qx = 0; qx < Q1D; ++qx)
2933 real_t gradYZ01[MD1D][MD1D];
2934 real_t gradYZ10[MD1D][MD1D];
2936 for (
int dy = 0; dy < D1Dy; ++dy)
2938 for (
int dz = 0; dz < D1Dz; ++dz)
2940 gradYZ01[dz][dy] = 0.0;
2941 gradYZ10[dz][dy] = 0.0;
2944 for (
int qy = 0; qy < Q1D; ++qy)
2947 for (
int dz = 0; dz < D1Dz; ++dz)
2949 for (
int n = 0; n < 2; ++n)
2954 for (
int qz = 0; qz < Q1D; ++qz)
2956 for (
int dz = 0; dz < D1Dz; ++dz)
2958 const real_t wz = Bot(dz,qz);
2960 massZ[dz][0] += wz *
mass[qz][qy][qx][0];
2961 massZ[dz][1] += wz *
mass[qz][qy][qx][1];
2964 for (
int dy = 0; dy < D1Dy; ++dy)
2966 const real_t wy = Bct(dy,qy);
2967 const real_t wDy = Gct(dy,qy);
2969 for (
int dz = 0; dz < D1Dz; ++dz)
2971 gradYZ01[dz][dy] += wy * massZ[dz][1];
2972 gradYZ10[dz][dy] += wDy * massZ[dz][0];
2977 for (
int dx = 0; dx < D1Dx; ++dx)
2979 const real_t wx = Bct(dx,qx);
2980 const real_t wDx = Gct(dx,qx);
2982 for (
int dy = 0; dy < D1Dy; ++dy)
2984 for (
int dz = 0; dz < D1Dz; ++dz)
2988 Y(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc,
2989 e) += (gradYZ10[dz][dy] * wx) - (gradYZ01[dz][dy] * wDx);
2999template<
int T_D1D = 0,
int T_Q1D = 0>
3000inline void SmemPAHcurlL2ApplyTranspose3D(
const int d1d,
3004 const Array<real_t> &bo,
3005 const Array<real_t> &bc,
3006 const Array<real_t> &gc,
3007 const Vector &pa_data,
3012 "Error: d1d > HCURL_MAX_D1D");
3014 "Error: q1d > HCURL_MAX_Q1D");
3015 const int D1D = T_D1D ? T_D1D : d1d;
3016 const int Q1D = T_Q1D ? T_Q1D : q1d;
3018 auto Bo =
Reshape(bo.Read(), Q1D, D1D-1);
3019 auto Bc =
Reshape(bc.Read(), Q1D, D1D);
3020 auto Gc =
Reshape(gc.Read(), Q1D, D1D);
3021 auto op =
Reshape(pa_data.Read(), coeffDim, Q1D, Q1D, Q1D, NE);
3022 auto X =
Reshape(x.Read(), 3*(D1D-1)*D1D*D1D, NE);
3023 auto Y =
Reshape(y.ReadWrite(), 3*(D1D-1)*D1D*D1D, NE);
3025 auto device_kernel = [=] MFEM_DEVICE (
int e)
3027 constexpr int VDIM = 3;
3028 constexpr int maxCoeffDim = 9;
3029 constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
3030 constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
3031 const int D1D = T_D1D ? T_D1D : d1d;
3032 const int Q1D = T_Q1D ? T_Q1D : q1d;
3034 MFEM_SHARED
real_t sBo[MD1D][MQ1D];
3035 MFEM_SHARED
real_t sBc[MD1D][MQ1D];
3036 MFEM_SHARED
real_t sGc[MD1D][MQ1D];
3039 MFEM_SHARED
real_t sop[maxCoeffDim][MQ1D][MQ1D];
3042 MFEM_SHARED
real_t sX[MD1D][MD1D][MD1D];
3044 MFEM_FOREACH_THREAD(qx,x,Q1D)
3046 MFEM_FOREACH_THREAD(qy,y,Q1D)
3048 MFEM_FOREACH_THREAD(qz,z,Q1D)
3050 for (
int i=0; i<coeffDim; ++i)
3052 opc[i] = op(i,qx,qy,qz,e);
3058 const int tidx = MFEM_THREAD_ID(x);
3059 const int tidy = MFEM_THREAD_ID(y);
3060 const int tidz = MFEM_THREAD_ID(z);
3064 MFEM_FOREACH_THREAD(d,y,D1D)
3066 MFEM_FOREACH_THREAD(q,x,Q1D)
3068 sBc[d][q] = Bc(q,d);
3069 sGc[d][q] = Gc(q,d);
3072 sBo[d][q] = Bo(q,d);
3079 for (
int qz=0; qz < Q1D; ++qz)
3083 MFEM_FOREACH_THREAD(qy,y,Q1D)
3085 MFEM_FOREACH_THREAD(qx,x,Q1D)
3087 for (
int i=0; i<3; ++i)
3089 mass[qy][qx][i] = 0.0;
3096 for (
int c = 0; c < VDIM; ++c)
3098 const int D1Dz = (c == 2) ? D1D - 1 : D1D;
3099 const int D1Dy = (c == 1) ? D1D - 1 : D1D;
3100 const int D1Dx = (c == 0) ? D1D - 1 : D1D;
3102 MFEM_FOREACH_THREAD(dz,z,D1Dz)
3104 MFEM_FOREACH_THREAD(dy,y,D1Dy)
3106 MFEM_FOREACH_THREAD(dx,x,D1Dx)
3108 sX[dz][dy][dx] = X(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
3118 for (
int i=0; i<coeffDim; ++i)
3120 sop[i][tidx][tidy] = opc[i];
3124 MFEM_FOREACH_THREAD(qy,y,Q1D)
3126 MFEM_FOREACH_THREAD(qx,x,Q1D)
3130 for (
int dz = 0; dz < D1Dz; ++dz)
3132 const real_t wz = (c == 2) ? sBo[dz][qz] : sBc[dz][qz];
3134 for (
int dy = 0; dy < D1Dy; ++dy)
3136 const real_t wy = (c == 1) ? sBo[dy][qy] : sBc[dy][qy];
3138 for (
int dx = 0; dx < D1Dx; ++dx)
3140 const real_t wx = sX[dz][dy][dx] * ((c == 0) ? sBo[dx][qx] : sBc[dx][qx]);
3146 mass[qy][qx][c] +=
u;
3151 osc += D1Dx * D1Dy * D1Dz;
3159 MFEM_FOREACH_THREAD(dz,z,D1D)
3161 const real_t wcz = sBc[dz][qz];
3162 const real_t wcDz = sGc[dz][qz];
3163 const real_t wz = (dz < D1D-1) ? sBo[dz][qz] : 0.0;
3165 MFEM_FOREACH_THREAD(dy,y,D1D)
3167 MFEM_FOREACH_THREAD(dx,x,D1D)
3169 for (
int qy = 0; qy < Q1D; ++qy)
3171 const real_t wcy = sBc[dy][qy];
3172 const real_t wcDy = sGc[dy][qy];
3173 const real_t wy = (dy < D1D-1) ? sBo[dy][qy] : 0.0;
3175 for (
int qx = 0; qx < Q1D; ++qx)
3177 const real_t O11 = sop[0][qx][qy];
3181 c1 = O11 *
mass[qy][qx][0];
3182 c2 = O11 *
mass[qy][qx][1];
3183 c3 = O11 *
mass[qy][qx][2];
3187 const real_t O12 = sop[1][qx][qy];
3188 const real_t O13 = sop[2][qx][qy];
3189 const real_t O21 = sop[3][qx][qy];
3190 const real_t O22 = sop[4][qx][qy];
3191 const real_t O23 = sop[5][qx][qy];
3192 const real_t O31 = sop[6][qx][qy];
3193 const real_t O32 = sop[7][qx][qy];
3194 const real_t O33 = sop[8][qx][qy];
3196 c1 = (O11*
mass[qy][qx][0])+(O12*mass[qy][qx][1])+(O13*
mass[qy][qx][2]);
3197 c2 = (O21*
mass[qy][qx][0])+(O22*mass[qy][qx][1])+(O23*
mass[qy][qx][2]);
3198 c3 = (O31*
mass[qy][qx][0])+(O32*mass[qy][qx][1])+(O33*
mass[qy][qx][2]);
3201 const real_t wcx = sBc[dx][qx];
3202 const real_t wDx = sGc[dx][qx];
3206 const real_t wx = sBo[dx][qx];
3207 dxyz1 += (wx * c2 * wcy * wcDz) - (wx * c3 * wcDy * wcz);
3210 dxyz2 += (-wy * c1 * wcx * wcDz) + (wy * c3 * wDx * wcz);
3212 dxyz3 += (wcDy * wz * c1 * wcx) - (wcy * wz * c2 * wDx);
3221 MFEM_FOREACH_THREAD(dz,z,D1D)
3223 MFEM_FOREACH_THREAD(dy,y,D1D)
3225 MFEM_FOREACH_THREAD(dx,x,D1D)
3229 Y(dx + ((dy + (dz * D1D)) * (D1D-1)), e) += dxyz1;
3233 Y(dx + ((dy + (dz * (D1D-1))) * D1D) + ((D1D-1)*D1D*D1D), e) += dxyz2;
3237 Y(dx + ((dy + (dz * D1D)) * D1D) + (2*(D1D-1)*D1D*D1D), e) += dxyz3;
3245 auto host_kernel = [&] MFEM_LAMBDA (
int)
3247 MFEM_ABORT_KERNEL(
"This kernel should only be used on GPU.");
3250 ForallWrap<3>(
true, NE, device_kernel, host_kernel, Q1D, Q1D, Q1D);
3255template<
int DIM,
int T_D1D,
int T_Q1D>
3258 if constexpr (
DIM == 2)
3260 return internal::PACurlCurlApply2D;
3262 else if constexpr (
DIM == 3)
3266 return internal::SmemPACurlCurlApply3D<T_D1D, T_Q1D>;
3270 return internal::PACurlCurlApply3D;
3276template <
int DIM,
int T_D1D,
int T_Q1D>
3278CurlCurlIntegrator::DiagonalPAKernels::Kernel()
3280 if constexpr (
DIM == 2)
3282 return internal::PACurlCurlAssembleDiagonal2D;
3284 else if constexpr (
DIM == 3)
3288 return internal::SmemPACurlCurlAssembleDiagonal3D<T_D1D, T_Q1D>;
3292 return internal::PACurlCurlAssembleDiagonal3D;
void(*)(const int, const int, const bool, const int, const Array< real_t > &, const Array< real_t > &, const Array< real_t > &, const Array< real_t > &, const Vector &, Vector &) DiagonalKernelType
arguments: d1d, q1d, symmetric, ne, Bo, Bc, Go, Gc, pa_data, diag
void(*)( const int, const int, const bool, const int, const Array< real_t > &, const Array< real_t > &, const Array< real_t > &, const Array< real_t > &, const Array< real_t > &, const Array< real_t > &, const Vector &, const Vector &, Vector &, const bool) ApplyKernelType
static bool Allows(unsigned long b_mask)
Return true if any of the backends in the backend mask, b_mask, are allowed.
void ForallWrap(const bool use_dev, const int N, d_lambda &&d_body, h_lambda &&h_body, const int X=0, const int Y=0, const int Z=0, const int G=0)
Forall host & device kernel dispatch.
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)
void forall(int N, lambda &&body)
@ DEVICE_MASK
Biwise-OR of all device backends.
static const DeviceDofQuadLimits & Get()
Return a const reference to the DeviceDofQuadLimits singleton.