12#ifndef MFEM_BILININTEG_HCURLHDIV_KERNELS_HPP
13#define MFEM_BILININTEG_HCURLHDIV_KERNELS_HPP
30void PAHcurlHdivMassSetup2D(
const int Q1D,
34 const Array<real_t> &w_,
40void PAHcurlHdivMassSetup3D(
const int Q1D,
44 const Array<real_t> &w_,
50void PAHcurlHdivMassApply2D(
const int D1D,
54 const bool scalarCoeff,
55 const bool trialHcurl,
57 const Array<real_t> &Bo_,
58 const Array<real_t> &Bc_,
59 const Array<real_t> &Bot_,
60 const Array<real_t> &Bct_,
67PAHcurlHdivMassApply2D(
const int NE,
const bool,
const bool scalarCoeff,
68 const Array<real_t> &Bo_,
const Array<real_t> &Bc_,
69 const Array<real_t> &Bot_,
const Array<real_t> &Bct_,
70 const Vector &op_,
const Vector &x_, Vector &y_,
71 const int D1D,
const int D1Dtest,
const int Q1D)
73 return PAHcurlHdivMassApply2D(D1D, D1Dtest, Q1D, NE, scalarCoeff,
false,
74 false, Bo_, Bc_, Bot_, Bct_, op_, x_, y_);
79PAHdivHcurlMassApply2D(
const int NE,
const bool,
const bool scalarCoeff,
80 const Array<real_t> &Bo_,
const Array<real_t> &Bc_,
81 const Array<real_t> &Bot_,
const Array<real_t> &Bct_,
82 const Vector &op_,
const Vector &x_, Vector &y_,
83 const int D1D,
const int D1Dtest,
const int Q1D)
85 return PAHcurlHdivMassApply2D(D1D, D1Dtest, Q1D, NE, scalarCoeff,
true,
86 false, Bo_, Bc_, Bot_, Bct_, op_, x_, y_);
90void PAHcurlHdivMassApply3D(
const int D1D,
94 const bool scalarCoeff,
95 const bool trialHcurl,
97 const Array<real_t> &Bo_,
98 const Array<real_t> &Bc_,
99 const Array<real_t> &Bot_,
100 const Array<real_t> &Bct_,
107PAHcurlHdivMassApply3D(
const int NE,
const bool,
const bool scalarCoeff,
108 const Array<real_t> &Bo_,
const Array<real_t> &Bc_,
109 const Array<real_t> &Bot_,
const Array<real_t> &Bct_,
110 const Vector &op_,
const Vector &x_, Vector &y_,
111 const int D1D,
const int D1Dtest,
const int Q1D)
113 PAHcurlHdivMassApply3D(D1D, D1Dtest, Q1D, NE, scalarCoeff,
false,
false, Bo_,
114 Bc_, Bot_, Bct_, op_, x_, y_);
119PAHdivHcurlMassApply3D(
const int NE,
const bool,
const bool scalarCoeff,
120 const Array<real_t> &Bo_,
const Array<real_t> &Bc_,
121 const Array<real_t> &Bot_,
const Array<real_t> &Bct_,
122 const Vector &op_,
const Vector &x_, Vector &y_,
123 const int D1D,
const int D1Dtest,
const int Q1D)
125 PAHcurlHdivMassApply3D(D1D, D1Dtest, Q1D, NE, scalarCoeff,
true,
false, Bo_,
126 Bc_, Bot_, Bct_, op_, x_, y_);
130template<
int T_D1D = 0,
int T_D1D_TEST = 0,
int T_Q1D = 0>
131inline void PAHcurlHdivApply3D(
const int d1d,
135 const Array<real_t> &bo,
136 const Array<real_t> &bc,
137 const Array<real_t> &bot,
138 const Array<real_t> &bct,
139 const Array<real_t> &gc,
140 const Vector &pa_data,
145 "Error: d1d > HCURL_MAX_D1D");
147 "Error: d1dtest > HCURL_MAX_D1D");
149 "Error: q1d > HCURL_MAX_Q1D");
150 const int D1D = T_D1D ? T_D1D : d1d;
151 const int D1Dtest = T_D1D_TEST ? T_D1D_TEST : d1dtest;
152 const int Q1D = T_Q1D ? T_Q1D : q1d;
154 auto Bo =
Reshape(bo.Read(), Q1D, D1D-1);
155 auto Bc =
Reshape(bc.Read(), Q1D, D1D);
156 auto Bot =
Reshape(bot.Read(), D1Dtest-1, Q1D);
157 auto Bct =
Reshape(bct.Read(), D1Dtest, Q1D);
158 auto Gc =
Reshape(gc.Read(), Q1D, D1D);
159 auto op =
Reshape(pa_data.Read(), Q1D, Q1D, Q1D, 6, NE);
160 auto X =
Reshape(x.Read(), 3*(D1D-1)*D1D*D1D, NE);
161 auto Y =
Reshape(y.ReadWrite(), 3*(D1Dtest-1)*(D1Dtest-1)*D1Dtest, NE);
172 constexpr int VDIM = 3;
173 constexpr int MD1D = T_D1D ? T_D1D :
174 DofQuadLimits::HCURL_MAX_D1D;
175 constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
176 const int D1D = T_D1D ? T_D1D : d1d;
177 const int D1Dtest = T_D1D_TEST ? T_D1D_TEST : d1dtest;
178 const int Q1D = T_Q1D ? T_Q1D : q1d;
180 real_t curl[MQ1D][MQ1D][MQ1D][VDIM];
183 for (
int qz = 0; qz < Q1D; ++qz)
185 for (
int qy = 0; qy < Q1D; ++qy)
187 for (
int qx = 0; qx < Q1D; ++qx)
189 for (
int c = 0; c < VDIM; ++c)
191 curl[qz][qy][qx][c] = 0.0;
203 const int D1Dz = D1D;
204 const int D1Dy = D1D;
205 const int D1Dx = D1D - 1;
207 for (
int dz = 0; dz < D1Dz; ++dz)
209 real_t gradXY[MQ1D][MQ1D][2];
210 for (
int qy = 0; qy < Q1D; ++qy)
212 for (
int qx = 0; qx < Q1D; ++qx)
214 for (
int d = 0; d < 2; ++d)
216 gradXY[qy][qx][d] = 0.0;
221 for (
int dy = 0; dy < D1Dy; ++dy)
224 for (
int qx = 0; qx < Q1D; ++qx)
229 for (
int dx = 0; dx < D1Dx; ++dx)
231 const real_t t = X(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
232 for (
int qx = 0; qx < Q1D; ++qx)
234 massX[qx] += t * Bo(qx,dx);
238 for (
int qy = 0; qy < Q1D; ++qy)
240 const real_t wy = Bc(qy,dy);
241 const real_t wDy = Gc(qy,dy);
242 for (
int qx = 0; qx < Q1D; ++qx)
244 const real_t wx = massX[qx];
245 gradXY[qy][qx][0] += wx * wDy;
246 gradXY[qy][qx][1] += wx * wy;
251 for (
int qz = 0; qz < Q1D; ++qz)
253 const real_t wz = Bc(qz,dz);
254 const real_t wDz = Gc(qz,dz);
255 for (
int qy = 0; qy < Q1D; ++qy)
257 for (
int qx = 0; qx < Q1D; ++qx)
260 curl[qz][qy][qx][1] += gradXY[qy][qx][1] * wDz;
261 curl[qz][qy][qx][2] -= gradXY[qy][qx][0] * wz;
267 osc += D1Dx * D1Dy * D1Dz;
272 const int D1Dz = D1D;
273 const int D1Dy = D1D - 1;
274 const int D1Dx = D1D;
276 for (
int dz = 0; dz < D1Dz; ++dz)
278 real_t gradXY[MQ1D][MQ1D][2];
279 for (
int qy = 0; qy < Q1D; ++qy)
281 for (
int qx = 0; qx < Q1D; ++qx)
283 for (
int d = 0; d < 2; ++d)
285 gradXY[qy][qx][d] = 0.0;
290 for (
int dx = 0; dx < D1Dx; ++dx)
293 for (
int qy = 0; qy < Q1D; ++qy)
298 for (
int dy = 0; dy < D1Dy; ++dy)
300 const real_t t = X(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
301 for (
int qy = 0; qy < Q1D; ++qy)
303 massY[qy] += t * Bo(qy,dy);
307 for (
int qx = 0; qx < Q1D; ++qx)
309 const real_t wx = Bc(qx,dx);
310 const real_t wDx = Gc(qx,dx);
311 for (
int qy = 0; qy < Q1D; ++qy)
313 const real_t wy = massY[qy];
314 gradXY[qy][qx][0] += wDx * wy;
315 gradXY[qy][qx][1] += wx * wy;
320 for (
int qz = 0; qz < Q1D; ++qz)
322 const real_t wz = Bc(qz,dz);
323 const real_t wDz = Gc(qz,dz);
324 for (
int qy = 0; qy < Q1D; ++qy)
326 for (
int qx = 0; qx < Q1D; ++qx)
329 curl[qz][qy][qx][0] -= gradXY[qy][qx][1] * wDz;
330 curl[qz][qy][qx][2] += gradXY[qy][qx][0] * wz;
336 osc += D1Dx * D1Dy * D1Dz;
341 const int D1Dz = D1D - 1;
342 const int D1Dy = D1D;
343 const int D1Dx = D1D;
345 for (
int dx = 0; dx < D1Dx; ++dx)
347 real_t gradYZ[MQ1D][MQ1D][2];
348 for (
int qz = 0; qz < Q1D; ++qz)
350 for (
int qy = 0; qy < Q1D; ++qy)
352 for (
int d = 0; d < 2; ++d)
354 gradYZ[qz][qy][d] = 0.0;
359 for (
int dy = 0; dy < D1Dy; ++dy)
362 for (
int qz = 0; qz < Q1D; ++qz)
367 for (
int dz = 0; dz < D1Dz; ++dz)
369 const real_t t = X(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
370 for (
int qz = 0; qz < Q1D; ++qz)
372 massZ[qz] += t * Bo(qz,dz);
376 for (
int qy = 0; qy < Q1D; ++qy)
378 const real_t wy = Bc(qy,dy);
379 const real_t wDy = Gc(qy,dy);
380 for (
int qz = 0; qz < Q1D; ++qz)
382 const real_t wz = massZ[qz];
383 gradYZ[qz][qy][0] += wz * wy;
384 gradYZ[qz][qy][1] += wz * wDy;
389 for (
int qx = 0; qx < Q1D; ++qx)
391 const real_t wx = Bc(qx,dx);
392 const real_t wDx = Gc(qx,dx);
394 for (
int qy = 0; qy < Q1D; ++qy)
396 for (
int qz = 0; qz < Q1D; ++qz)
399 curl[qz][qy][qx][0] += gradYZ[qz][qy][1] * wx;
400 curl[qz][qy][qx][1] -= gradYZ[qz][qy][0] * wDx;
408 for (
int qz = 0; qz < Q1D; ++qz)
410 for (
int qy = 0; qy < Q1D; ++qy)
412 for (
int qx = 0; qx < Q1D; ++qx)
414 const real_t O11 = op(qx,qy,qz,0,e);
415 const real_t O12 = op(qx,qy,qz,1,e);
416 const real_t O13 = op(qx,qy,qz,2,e);
417 const real_t O22 = op(qx,qy,qz,3,e);
418 const real_t O23 = op(qx,qy,qz,4,e);
419 const real_t O33 = op(qx,qy,qz,5,e);
421 const real_t c1 = (O11 * curl[qz][qy][qx][0]) + (O12 * curl[qz][qy][qx][1]) +
422 (O13 * curl[qz][qy][qx][2]);
423 const real_t c2 = (O12 * curl[qz][qy][qx][0]) + (O22 * curl[qz][qy][qx][1]) +
424 (O23 * curl[qz][qy][qx][2]);
425 const real_t c3 = (O13 * curl[qz][qy][qx][0]) + (O23 * curl[qz][qy][qx][1]) +
426 (O33 * curl[qz][qy][qx][2]);
428 curl[qz][qy][qx][0] = c1;
429 curl[qz][qy][qx][1] = c2;
430 curl[qz][qy][qx][2] = c3;
435 for (
int qz = 0; qz < Q1D; ++qz)
437 real_t massXY[MD1D][MD1D];
441 for (
int c = 0; c < VDIM; ++c)
443 const int D1Dz = (c == 2) ? D1Dtest : D1Dtest - 1;
444 const int D1Dy = (c == 1) ? D1Dtest : D1Dtest - 1;
445 const int D1Dx = (c == 0) ? D1Dtest : D1Dtest - 1;
447 for (
int dy = 0; dy < D1Dy; ++dy)
449 for (
int dx = 0; dx < D1Dx; ++dx)
454 for (
int qy = 0; qy < Q1D; ++qy)
457 for (
int dx = 0; dx < D1Dx; ++dx)
461 for (
int qx = 0; qx < Q1D; ++qx)
463 for (
int dx = 0; dx < D1Dx; ++dx)
465 massX[dx] += curl[qz][qy][qx][c] *
466 ((c == 0) ? Bct(dx,qx) : Bot(dx,qx));
469 for (
int dy = 0; dy < D1Dy; ++dy)
471 const real_t wy = (c == 1) ? Bct(dy,qy) : Bot(dy,qy);
472 for (
int dx = 0; dx < D1Dx; ++dx)
474 massXY[dy][dx] += massX[dx] * wy;
479 for (
int dz = 0; dz < D1Dz; ++dz)
481 const real_t wz = (c == 2) ? Bct(dz,qz) : Bot(dz,qz);
482 for (
int dy = 0; dy < D1Dy; ++dy)
484 for (
int dx = 0; dx < D1Dx; ++dx)
486 Y(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e) +=
492 osc += D1Dx * D1Dy * D1Dz;
499template<
int T_D1D = 0,
int T_D1D_TEST = 0,
int T_Q1D = 0>
500inline void PAHcurlHdivApplyTranspose3D(
const int d1d,
504 const Array<real_t> &bo,
505 const Array<real_t> &bc,
506 const Array<real_t> &bot,
507 const Array<real_t> &bct,
508 const Array<real_t> &gct,
509 const Vector &pa_data,
514 "Error: d1d > HCURL_MAX_D1D");
516 "Error: d1dtest > HCURL_MAX_D1D");
518 "Error: q1d > HCURL_MAX_Q1D");
519 const int D1D = T_D1D ? T_D1D : d1d;
520 const int D1Dtest = T_D1D_TEST ? T_D1D_TEST : d1dtest;
521 const int Q1D = T_Q1D ? T_Q1D : q1d;
523 auto Bo =
Reshape(bo.Read(), Q1D, D1D-1);
524 auto Bc =
Reshape(bc.Read(), Q1D, D1D);
525 auto Bot =
Reshape(bot.Read(), D1Dtest-1, Q1D);
526 auto Bct =
Reshape(bct.Read(), D1Dtest, Q1D);
527 auto Gct =
Reshape(gct.Read(), D1D, Q1D);
528 auto op =
Reshape(pa_data.Read(), Q1D, Q1D, Q1D, 6, NE);
529 auto X =
Reshape(x.Read(), 3*(D1Dtest-1)*(D1Dtest-1)*D1Dtest, NE);
530 auto Y =
Reshape(y.ReadWrite(), 3*(D1D-1)*D1D*D1D, NE);
541 constexpr int VDIM = 3;
542 constexpr int MD1D = T_D1D ? T_D1D :
543 DofQuadLimits::HCURL_MAX_D1D;
544 constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
545 const int D1D = T_D1D ? T_D1D : d1d;
546 const int D1Dtest = T_D1D_TEST ? T_D1D_TEST : d1dtest;
547 const int Q1D = T_Q1D ? T_Q1D : q1d;
551 for (
int qz = 0; qz < Q1D; ++qz)
553 for (
int qy = 0; qy < Q1D; ++qy)
555 for (
int qx = 0; qx < Q1D; ++qx)
557 for (
int c = 0; c < VDIM; ++c)
559 mass[qz][qy][qx][c] = 0.0;
567 for (
int c = 0; c < VDIM; ++c)
569 const int D1Dz = (c == 2) ? D1Dtest : D1Dtest - 1;
570 const int D1Dy = (c == 1) ? D1Dtest : D1Dtest - 1;
571 const int D1Dx = (c == 0) ? D1Dtest : D1Dtest - 1;
573 for (
int dz = 0; dz < D1Dz; ++dz)
575 real_t massXY[MQ1D][MQ1D];
576 for (
int qy = 0; qy < Q1D; ++qy)
578 for (
int qx = 0; qx < Q1D; ++qx)
580 massXY[qy][qx] = 0.0;
584 for (
int dy = 0; dy < D1Dy; ++dy)
587 for (
int qx = 0; qx < Q1D; ++qx)
592 for (
int dx = 0; dx < D1Dx; ++dx)
594 const real_t t = X(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
595 for (
int qx = 0; qx < Q1D; ++qx)
597 massX[qx] += t * ((c == 0) ? Bc(qx,dx) : Bo(qx,dx));
601 for (
int qy = 0; qy < Q1D; ++qy)
603 const real_t wy = (c == 1) ? Bc(qy,dy) : Bo(qy,dy);
604 for (
int qx = 0; qx < Q1D; ++qx)
606 const real_t wx = massX[qx];
607 massXY[qy][qx] += wx * wy;
612 for (
int qz = 0; qz < Q1D; ++qz)
614 const real_t wz = (c == 2) ? Bc(qz,dz) : Bo(qz,dz);
615 for (
int qy = 0; qy < Q1D; ++qy)
617 for (
int qx = 0; qx < Q1D; ++qx)
619 mass[qz][qy][qx][c] += massXY[qy][qx] * wz;
625 osc += D1Dx * D1Dy * D1Dz;
629 for (
int qz = 0; qz < Q1D; ++qz)
631 for (
int qy = 0; qy < Q1D; ++qy)
633 for (
int qx = 0; qx < Q1D; ++qx)
635 const real_t O11 = op(qx,qy,qz,0,e);
636 const real_t O12 = op(qx,qy,qz,1,e);
637 const real_t O13 = op(qx,qy,qz,2,e);
638 const real_t O22 = op(qx,qy,qz,3,e);
639 const real_t O23 = op(qx,qy,qz,4,e);
640 const real_t O33 = op(qx,qy,qz,5,e);
644 mass[qz][qy][qx][0] = (O11*massX)+(O12*massY)+(O13*massZ);
645 mass[qz][qy][qx][1] = (O12*massX)+(O22*massY)+(O23*massZ);
646 mass[qz][qy][qx][2] = (O13*massX)+(O23*massY)+(O33*massZ);
654 const int D1Dz = D1D;
655 const int D1Dy = D1D;
656 const int D1Dx = D1D - 1;
658 for (
int qz = 0; qz < Q1D; ++qz)
660 real_t gradXY12[MD1D][MD1D];
661 real_t gradXY21[MD1D][MD1D];
663 for (
int dy = 0; dy < D1Dy; ++dy)
665 for (
int dx = 0; dx < D1Dx; ++dx)
667 gradXY12[dy][dx] = 0.0;
668 gradXY21[dy][dx] = 0.0;
671 for (
int qy = 0; qy < Q1D; ++qy)
674 for (
int dx = 0; dx < D1Dx; ++dx)
676 for (
int n = 0; n < 2; ++n)
681 for (
int qx = 0; qx < Q1D; ++qx)
683 for (
int dx = 0; dx < D1Dx; ++dx)
685 const real_t wx = Bot(dx,qx);
687 massX[dx][0] += wx *
mass[qz][qy][qx][1];
688 massX[dx][1] += wx *
mass[qz][qy][qx][2];
691 for (
int dy = 0; dy < D1Dy; ++dy)
693 const real_t wy = Bct(dy,qy);
694 const real_t wDy = Gct(dy,qy);
696 for (
int dx = 0; dx < D1Dx; ++dx)
698 gradXY21[dy][dx] += massX[dx][0] * wy;
699 gradXY12[dy][dx] += massX[dx][1] * wDy;
704 for (
int dz = 0; dz < D1Dz; ++dz)
706 const real_t wz = Bct(dz,qz);
707 const real_t wDz = Gct(dz,qz);
708 for (
int dy = 0; dy < D1Dy; ++dy)
710 for (
int dx = 0; dx < D1Dx; ++dx)
714 Y(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc,
715 e) += (gradXY21[dy][dx] * wDz) - (gradXY12[dy][dx] * wz);
721 osc += D1Dx * D1Dy * D1Dz;
726 const int D1Dz = D1D;
727 const int D1Dy = D1D - 1;
728 const int D1Dx = D1D;
730 for (
int qz = 0; qz < Q1D; ++qz)
732 real_t gradXY02[MD1D][MD1D];
733 real_t gradXY20[MD1D][MD1D];
735 for (
int dy = 0; dy < D1Dy; ++dy)
737 for (
int dx = 0; dx < D1Dx; ++dx)
739 gradXY02[dy][dx] = 0.0;
740 gradXY20[dy][dx] = 0.0;
743 for (
int qx = 0; qx < Q1D; ++qx)
746 for (
int dy = 0; dy < D1Dy; ++dy)
751 for (
int qy = 0; qy < Q1D; ++qy)
753 for (
int dy = 0; dy < D1Dy; ++dy)
755 const real_t wy = Bot(dy,qy);
757 massY[dy][0] += wy *
mass[qz][qy][qx][2];
758 massY[dy][1] += wy *
mass[qz][qy][qx][0];
761 for (
int dx = 0; dx < D1Dx; ++dx)
763 const real_t wx = Bct(dx,qx);
764 const real_t wDx = Gct(dx,qx);
766 for (
int dy = 0; dy < D1Dy; ++dy)
768 gradXY02[dy][dx] += massY[dy][0] * wDx;
769 gradXY20[dy][dx] += massY[dy][1] * wx;
774 for (
int dz = 0; dz < D1Dz; ++dz)
776 const real_t wz = Bct(dz,qz);
777 const real_t wDz = Gct(dz,qz);
778 for (
int dy = 0; dy < D1Dy; ++dy)
780 for (
int dx = 0; dx < D1Dx; ++dx)
784 Y(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc,
785 e) += (-gradXY20[dy][dx] * wDz) + (gradXY02[dy][dx] * wz);
791 osc += D1Dx * D1Dy * D1Dz;
796 const int D1Dz = D1D - 1;
797 const int D1Dy = D1D;
798 const int D1Dx = D1D;
800 for (
int qx = 0; qx < Q1D; ++qx)
802 real_t gradYZ01[MD1D][MD1D];
803 real_t gradYZ10[MD1D][MD1D];
805 for (
int dy = 0; dy < D1Dy; ++dy)
807 for (
int dz = 0; dz < D1Dz; ++dz)
809 gradYZ01[dz][dy] = 0.0;
810 gradYZ10[dz][dy] = 0.0;
813 for (
int qy = 0; qy < Q1D; ++qy)
816 for (
int dz = 0; dz < D1Dz; ++dz)
818 for (
int n = 0; n < 2; ++n)
823 for (
int qz = 0; qz < Q1D; ++qz)
825 for (
int dz = 0; dz < D1Dz; ++dz)
827 const real_t wz = Bot(dz,qz);
829 massZ[dz][0] += wz *
mass[qz][qy][qx][0];
830 massZ[dz][1] += wz *
mass[qz][qy][qx][1];
833 for (
int dy = 0; dy < D1Dy; ++dy)
835 const real_t wy = Bct(dy,qy);
836 const real_t wDy = Gct(dy,qy);
838 for (
int dz = 0; dz < D1Dz; ++dz)
840 gradYZ01[dz][dy] += wy * massZ[dz][1];
841 gradYZ10[dz][dy] += wDy * massZ[dz][0];
846 for (
int dx = 0; dx < D1Dx; ++dx)
848 const real_t wx = Bct(dx,qx);
849 const real_t wDx = Gct(dx,qx);
851 for (
int dy = 0; dy < D1Dy; ++dy)
853 for (
int dz = 0; dz < D1Dz; ++dz)
857 Y(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc,
858 e) += (gradYZ10[dz][dy] * wx) - (gradYZ01[dz][dy] * wDx);
869constexpr int NBZ3D(
int ndof_o,
int nquad_o,
int mdq)
871 if (ndof_o <= 0 || nquad_o <= 0)
875 int ndof_c = ndof_o + 1;
876 int nquad_c = nquad_o + 1;
879 std::min((128 + mdq * mdq * (mdq - 1) - 1) / (mdq * mdq * (mdq - 1)), 64);
882 ((3 * ndof_c * ndof_c * ndof_o + 2 * 2 * mdq * mdq * mdq) * tmp +
883 ndof_c * nquad_o + ndof_c * nquad_c + ndof_o * nquad_o);
885 return std::max(std::min(tmp, (48 * 1024 + smem_req - 1) / smem_req), 1);
889template <
int T_NDOF_O,
int T_NQUAD_O>
890void CurlInterpolatorApply3DSmem(
const int ne,
const int ndof_o,
891 const int nquad_o,
const Vector &pa,
892 const Vector &x_, Vector &y_)
894 constexpr int mnd_o = T_NDOF_O ? T_NDOF_O : DofQuadLimits::HCURL_MAX_D1D - 1;
895 constexpr int mnq_o =
896 T_NQUAD_O ? T_NQUAD_O : DofQuadLimits::HDIV_MAX_D1D - 1;
897 constexpr int mndq = std::max(mnd_o + 1, mnq_o + 1);
898 constexpr int tbatch = curlinterp::NBZ3D(T_NDOF_O, T_NQUAD_O, mndq);
899 MFEM_VERIFY(ndof_o <= mnd_o,
"Error: H(curl) order larger than supported");
900 MFEM_VERIFY(nquad_o <= mnq_o,
"Error: H(div) order larger than supported");
901 int mnq = std::max(ndof_o + 1, nquad_o + 1);
902 auto pa_data = pa.Read();
903 auto x_d = x_.Read();
904 auto y_d = y_.ReadWrite();
906 ne, mnq * mnq * (mnq - 1), 1, tbatch, [=] MFEM_HOST_DEVICE(
int e)
908 constexpr int MND_O =
909 T_NDOF_O ? T_NDOF_O : DofQuadLimits::HCURL_MAX_D1D - 1;
910 constexpr int MNQ_O =
911 T_NQUAD_O ? T_NQUAD_O : DofQuadLimits::HDIV_MAX_D1D - 1;
912 constexpr int MNDQ = std::max(MND_O + 1, MNQ_O + 1);
913#if defined(__CUDA_ARCH__) || defined(__HIP_DEVICE_COMPILE__)
914 constexpr int nbz = curlinterp::NBZ3D(T_NDOF_O, T_NQUAD_O, MNDQ);
915 int tidz = MFEM_THREAD_ID(z);
918 int mnq = std::max(ndof_o + 1, nquad_o + 1);
920 constexpr int nbz = 1;
921 constexpr int tidz = 0;
923 const int NDOF_O = T_NDOF_O ? T_NDOF_O : ndof_o;
924 const int NQUAD_O = T_NQUAD_O ? T_NQUAD_O : nquad_o;
925 const int NDOF_C = NDOF_O + 1;
926 const int NQUAD_C = NQUAD_O + 1;
928 sBG[(MND_O + 1) * MNQ_O + (MND_O + 1) * (MNQ_O + 1) + MND_O * MNQ_O];
929 auto X_ =
Reshape(x_d, 3 * NDOF_C * NDOF_C * NDOF_O, ne);
930 auto Y =
Reshape(y_d, 3 * NQUAD_C * NQUAD_O * NQUAD_O, ne);
931 auto Gco =
Reshape(sBG, NQUAD_O, NDOF_C);
932 auto Bcc =
Reshape(sBG + NDOF_C * NQUAD_O, NQUAD_C, NDOF_C);
934 Reshape(sBG + NDOF_C * NQUAD_O + NDOF_C * NQUAD_C, NQUAD_O, NDOF_O);
935 MFEM_SHARED
real_t X[3][nbz][MND_O * (MND_O + 1) * (MND_O + 1)];
936 MFEM_SHARED
real_t sm0[nbz * 2 * MNDQ * MNDQ * MNDQ];
937 MFEM_SHARED
real_t sm1[nbz * 2 * MNDQ * MNDQ * MNDQ];
941 real_t(*DDQ)[nbz][MNDQ][MNDQ][MNDQ] =
942 (
real_t(*)[nbz][MNDQ][MNDQ][MNDQ])(sm0);
943 real_t(*DQQ)[nbz][MNDQ][MNDQ][MNDQ] =
944 (
real_t(*)[nbz][MNDQ][MNDQ][MNDQ])(sm1);
945 real_t(*QQQ)[nbz][MNDQ][MNDQ][MNDQ] =
946 (
real_t(*)[nbz][MNDQ][MNDQ][MNDQ])(sm0);
947 const int offset = NDOF_O * NDOF_C * NDOF_C;
948 const int offsetq = NQUAD_C * NQUAD_O * NQUAD_O;
949 MFEM_FOREACH_THREAD_DIRECT(ix, x, offset)
953 X[
dim][tidz][ix] = X_(ix +
dim * offset, e);
959 auto npts = NDOF_C * NQUAD_O + NDOF_C * NQUAD_C + NDOF_O * NQUAD_O;
960 MFEM_FOREACH_THREAD(ix, x, npts) { sBG[ix] = pa_data[ix]; }
966 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, dy, dz, x, NQUAD_C, NDOF_C,
967 NDOF_O, mnq, mnq, mnq - 1)
970 for (
int dx = 0; dx < NDOF_C; ++dx)
972 u += X[2][tidz][dx + (dy + dz * NDOF_C) * NDOF_C] * Bcc(qx, dx);
974 DDQ[0][tidz][dz][dy][qx] =
u;
977 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, dy, dz, x, NQUAD_C, NDOF_O,
978 NDOF_C, mnq, mnq - 1, mnq)
981 for (
int dx = 0; dx < NDOF_C; ++dx)
983 u += X[1][tidz][dx + (dy + dz * NDOF_O) * NDOF_C] * Bcc(qx, dx);
985 DDQ[1][tidz][dz][dy][qx] =
u;
990 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, qy, dz, x, NQUAD_C, NQUAD_O,
991 NDOF_O, mnq, mnq, mnq - 1)
994 for (
int dy = 0; dy < NDOF_C; ++dy)
996 u += DDQ[0][tidz][dz][dy][qx] * Gco(qy, dy);
998 DQQ[0][tidz][dz][qy][qx] =
u;
1001 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, qy, dz, x, NQUAD_C, NQUAD_O,
1002 NDOF_C, mnq, mnq - 1, mnq)
1005 for (
int dy = 0; dy < NDOF_O; ++dy)
1007 u += DDQ[1][tidz][dz][dy][qx] * Boo(qy, dy);
1009 DQQ[1][tidz][dz][qy][qx] =
u;
1014 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, qy, qz, x, NQUAD_C, NQUAD_O,
1015 NQUAD_O, mnq, mnq, mnq - 1)
1018 for (
int dz = 0; dz < NDOF_O; ++dz)
1020 u += DQQ[0][tidz][dz][qy][qx] * Boo(qz, dz);
1022 QQQ[0][tidz][qz][qy][qx] =
u;
1026 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, qy, qz, x, NQUAD_C, NQUAD_O,
1027 NQUAD_O, mnq, mnq, mnq - 1)
1030 for (
int dz = 0; dz < NDOF_C; ++dz)
1032 u += DQQ[1][tidz][dz][qy][qx] * Gco(qz, dz);
1034 Y(qx + (qy + qz * NQUAD_O) * NQUAD_C, e) =
1035 QQQ[0][tidz][qz][qy][qx] -
u;
1041 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, dy, dz, x, NQUAD_O, NDOF_C,
1042 NDOF_C, mnq - 1, mnq, mnq)
1045 for (
int dx = 0; dx < NDOF_O; ++dx)
1047 u += X[0][tidz][dx + (dy + dz * NDOF_C) * NDOF_O] * Boo(qx, dx);
1049 DDQ[0][tidz][dz][dy][qx] =
u;
1052 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, dy, dz, x, NQUAD_O, NDOF_C,
1053 NDOF_O, mnq, mnq, mnq - 1)
1056 for (
int dx = 0; dx < NDOF_C; ++dx)
1058 u += X[2][tidz][dx + (dy + dz * NDOF_C) * NDOF_C] * Gco(qx, dx);
1060 DDQ[1][tidz][dz][dy][qx] =
u;
1065 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, qy, dz, x, NQUAD_O, NQUAD_C,
1066 NDOF_C, mnq - 1, mnq, mnq)
1069 for (
int dy = 0; dy < NDOF_C; ++dy)
1071 u += DDQ[0][tidz][dz][dy][qx] * Bcc(qy, dy);
1073 DQQ[0][tidz][dz][qy][qx] =
u;
1076 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, qy, dz, x, NQUAD_O, NQUAD_C,
1077 NDOF_O, mnq - 1, mnq, mnq)
1080 for (
int dy = 0; dy < NDOF_C; ++dy)
1082 u += DDQ[1][tidz][dz][dy][qx] * Bcc(qy, dy);
1084 DQQ[1][tidz][dz][qy][qx] =
u;
1089 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, qy, qz, x, NQUAD_O, NQUAD_C,
1090 NQUAD_O, mnq, mnq, mnq - 1)
1093 for (
int dz = 0; dz < NDOF_C; ++dz)
1095 u += DQQ[0][tidz][dz][qy][qx] * Gco(qz, dz);
1097 QQQ[0][tidz][qz][qy][qx] =
u;
1101 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, qy, qz, x, NQUAD_O, NQUAD_C,
1102 NQUAD_O, mnq, mnq, mnq - 1)
1105 for (
int dz = 0; dz < NDOF_O; ++dz)
1107 u += DQQ[1][tidz][dz][qy][qx] * Boo(qz, dz);
1109 Y(qx + (qy + qz * NQUAD_C) * NQUAD_O + offsetq, e) =
1110 QQQ[0][tidz][qz][qy][qx] -
u;
1116 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, dy, dz, x, NQUAD_O, NDOF_O,
1117 NDOF_C, mnq, mnq - 1, mnq)
1120 for (
int dx = 0; dx < NDOF_C; ++dx)
1122 u += X[1][tidz][dx + (dy + dz * NDOF_O) * NDOF_C] * Gco(qx, dx);
1124 DDQ[0][tidz][dz][dy][qx] =
u;
1127 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, dy, dz, x, NQUAD_O, NDOF_C,
1128 NDOF_C, mnq - 1, mnq, mnq)
1131 for (
int dx = 0; dx < NDOF_O; ++dx)
1133 u += X[0][tidz][dx + (dy + dz * NDOF_C) * NDOF_O] * Boo(qx, dx);
1135 DDQ[1][tidz][dz][dy][qx] =
u;
1140 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, qy, dz, x, NQUAD_O, NQUAD_O,
1141 NDOF_C, mnq, mnq - 1, mnq)
1144 for (
int dy = 0; dy < NDOF_O; ++dy)
1146 u += DDQ[0][tidz][dz][dy][qx] * Boo(qy, dy);
1148 DQQ[0][tidz][dz][qy][qx] =
u;
1151 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, qy, dz, x, NQUAD_O, NQUAD_O,
1152 NDOF_C, mnq, mnq - 1, mnq)
1155 for (
int dy = 0; dy < NDOF_C; ++dy)
1157 u += DDQ[1][tidz][dz][dy][qx] * Gco(qy, dy);
1159 DQQ[1][tidz][dz][qy][qx] =
u;
1164 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, qy, qz, x, NQUAD_O, NQUAD_O,
1165 NQUAD_C, mnq, mnq - 1, mnq)
1168 for (
int dz = 0; dz < NDOF_C; ++dz)
1170 u += DQQ[0][tidz][dz][qy][qx] * Bcc(qz, dz);
1172 QQQ[0][tidz][qz][qy][qx] =
u;
1176 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(qx, qy, qz, x, NQUAD_O, NQUAD_O,
1177 NQUAD_C, mnq, mnq - 1, mnq)
1180 for (
int dz = 0; dz < NDOF_C; ++dz)
1182 u += DQQ[1][tidz][dz][qy][qx] * Bcc(qz, dz);
1184 Y(qx + (qy + qz * NQUAD_O) * NQUAD_O + 2 * offsetq, e) =
1185 QQQ[0][tidz][qz][qy][qx] -
u;
1191template <
int T_NDOF_O,
int T_NQUAD_O>
1192void CurlInterpolatorTApply3DSmem(
const int ne,
const int ndof_o,
1193 const int nquad_o,
const Vector &pa,
1194 const Vector &x_, Vector &y_)
1196 constexpr int mnd_o = T_NDOF_O ? T_NDOF_O : DofQuadLimits::HCURL_MAX_D1D - 1;
1197 constexpr int mnq_o =
1198 T_NQUAD_O ? T_NQUAD_O : DofQuadLimits::HDIV_MAX_D1D - 1;
1199 constexpr int mndq = std::max(mnd_o + 1, mnq_o + 1);
1200 constexpr int tbatch = curlinterp::NBZ3D(T_NDOF_O, T_NQUAD_O, mndq);
1201 MFEM_VERIFY(ndof_o <= mnd_o,
"Error: H(curl) order larger than supported");
1202 MFEM_VERIFY(nquad_o <= mnq_o,
"Error: H(div) order larger than supported");
1203 int mnq = std::max(ndof_o + 1, nquad_o + 1);
1204 auto pa_data = pa.Read();
1205 auto x_d = x_.Read();
1206 auto y_d = y_.ReadWrite();
1208 ne, mnq * mnq * (mnq - 1), 1, tbatch, [=] MFEM_HOST_DEVICE(
int e)
1210 constexpr int MND_O =
1211 T_NDOF_O ? T_NDOF_O : DofQuadLimits::HCURL_MAX_D1D - 1;
1212 constexpr int MNQ_O =
1213 T_NQUAD_O ? T_NQUAD_O : DofQuadLimits::HDIV_MAX_D1D - 1;
1214 constexpr int MNDQ = std::max(MND_O + 1, MNQ_O + 1);
1215#if defined(__CUDA_ARCH__) || defined(__HIP_DEVICE_COMPILE__)
1216 constexpr int nbz = curlinterp::NBZ3D(T_NDOF_O, T_NQUAD_O, MNDQ);
1217 int tidz = MFEM_THREAD_ID(z);
1220 int mnq = std::max(ndof_o + 1, nquad_o + 1);
1222 constexpr int nbz = 1;
1223 constexpr int tidz = 0;
1225 const int NDOF_O = T_NDOF_O ? T_NDOF_O : ndof_o;
1226 const int NQUAD_O = T_NQUAD_O ? T_NQUAD_O : nquad_o;
1227 const int NDOF_C = NDOF_O + 1;
1228 const int NQUAD_C = NQUAD_O + 1;
1230 sBG[(MND_O + 1) * MNQ_O + (MND_O + 1) * (MNQ_O + 1) + MND_O * MNQ_O];
1231 auto X_ =
Reshape(x_d, 3 * NQUAD_C * NQUAD_O * NQUAD_O, ne);
1232 auto Y =
Reshape(y_d, 3 * NDOF_C * NDOF_C * NDOF_O, ne);
1233 auto Gco =
Reshape(sBG, NQUAD_O, NDOF_C);
1234 auto Bcc =
Reshape(sBG + NDOF_C * NQUAD_O, NQUAD_C, NDOF_C);
1236 Reshape(sBG + NDOF_C * NQUAD_O + NDOF_C * NQUAD_C, NQUAD_O, NDOF_O);
1237 MFEM_SHARED
real_t X[3][nbz][MNQ_O * MNQ_O * (MNQ_O + 1)];
1238 MFEM_SHARED
real_t sm0[nbz * 2 * MNDQ * MNDQ * MNDQ];
1239 MFEM_SHARED
real_t sm1[nbz * 2 * MNDQ * MNDQ * MNDQ];
1243 real_t(*QQD)[nbz][MNDQ][MNDQ][MNDQ] =
1244 (
real_t(*)[nbz][MNDQ][MNDQ][MNDQ])(sm0);
1245 real_t(*QDD)[nbz][MNDQ][MNDQ][MNDQ] =
1246 (
real_t(*)[nbz][MNDQ][MNDQ][MNDQ])(sm1);
1247 real_t(*DDD)[nbz][MNDQ][MNDQ][MNDQ] =
1248 (
real_t(*)[nbz][MNDQ][MNDQ][MNDQ])(sm0);
1249 const int offset = NDOF_O * NDOF_C * NDOF_C;
1250 const int offsetq = NQUAD_C * NQUAD_O * NQUAD_O;
1251 MFEM_FOREACH_THREAD_DIRECT(ix, x, offsetq)
1255 X[
dim][tidz][ix] = X_(ix +
dim * offsetq, e);
1261 auto npts = NDOF_C * NQUAD_O + NDOF_C * NQUAD_C + NDOF_O * NQUAD_O;
1262 MFEM_FOREACH_THREAD(ix, x, npts) { sBG[ix] = pa_data[ix]; }
1268 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dz, qx, qy, x, NDOF_C, NQUAD_O,
1269 NQUAD_C, mnq, mnq - 1, mnq)
1272 for (
int qz = 0; qz < NQUAD_O; ++qz)
1274 u += X[1][tidz][qx + (qy + qz * NQUAD_C) * NQUAD_O] * Gco(qz, dz);
1276 QQD[0][tidz][qy][qx][dz] =
u;
1279 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dz, qx, qy, x, NDOF_C, NQUAD_O,
1280 NQUAD_O, mnq, mnq, mnq - 1)
1283 for (
int qz = 0; qz < NQUAD_C; ++qz)
1285 u += X[2][tidz][qx + (qy + qz * NQUAD_O) * NQUAD_O] * Bcc(qz, dz);
1287 QQD[1][tidz][qy][qx][dz] =
u;
1292 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dy, dz, qx, x, NDOF_C, NDOF_C,
1293 NQUAD_O, mnq, mnq, mnq - 1)
1296 for (
int qy = 0; qy < NQUAD_C; ++qy)
1298 u += QQD[0][tidz][qy][qx][dz] * Bcc(qy, dy);
1300 QDD[0][tidz][qx][dz][dy] =
u;
1303 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dy, dz, qx, x, NDOF_C, NDOF_C,
1304 NQUAD_O, mnq, mnq, mnq - 1)
1307 for (
int qy = 0; qy < NQUAD_O; ++qy)
1309 u += QQD[1][tidz][qy][qx][dz] * Gco(qy, dy);
1311 QDD[1][tidz][qx][dz][dy] =
u;
1316 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dx, dy, dz, x, NDOF_O, NDOF_C,
1317 NDOF_C, mnq - 1, mnq, mnq)
1320 for (
int qx = 0; qx < NQUAD_O; ++qx)
1322 u += QDD[0][tidz][qx][dz][dy] * Boo(qx, dx);
1324 DDD[0][tidz][dz][dy][dx] =
u;
1328 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dx, dy, dz, x, NDOF_O, NDOF_C,
1329 NDOF_C, mnq - 1, mnq, mnq)
1332 for (
int qx = 0; qx < NQUAD_O; ++qx)
1334 u += QDD[1][tidz][qx][dz][dy] * Boo(qx, dx);
1336 Y(dx + (dy + dz * NDOF_C) * NDOF_O, e) =
1337 DDD[0][tidz][dz][dy][dx] -
u;
1343 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dz, qx, qy, x, NDOF_C, NQUAD_O,
1344 NQUAD_O, mnq, mnq, mnq - 1)
1347 for (
int qz = 0; qz < NQUAD_C; ++qz)
1349 u += X[2][tidz][qx + (qy + qz * NQUAD_O) * NQUAD_O] * Bcc(qz, dz);
1351 QQD[0][tidz][qy][qx][dz] =
u;
1354 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dz, qx, qy, x, NDOF_C, NQUAD_C,
1355 NQUAD_O, mnq, mnq, mnq - 1)
1358 for (
int qz = 0; qz < NQUAD_O; ++qz)
1360 u += X[0][tidz][qx + (qy + qz * NQUAD_O) * NQUAD_C] * Gco(qz, dz);
1362 QQD[1][tidz][qy][qx][dz] =
u;
1367 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dy, dz, qx, x, NDOF_O, NDOF_C,
1368 NQUAD_O, mnq, mnq, mnq - 1)
1371 for (
int qy = 0; qy < NQUAD_O; ++qy)
1373 u += QQD[0][tidz][qy][qx][dz] * Boo(qy, dy);
1375 QDD[0][tidz][qx][dz][dy] =
u;
1378 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dy, dz, qx, x, NDOF_O, NDOF_C,
1379 NQUAD_C, mnq - 1, mnq, mnq)
1382 for (
int qy = 0; qy < NQUAD_O; ++qy)
1384 u += QQD[1][tidz][qy][qx][dz] * Boo(qy, dy);
1386 QDD[1][tidz][qx][dz][dy] =
u;
1391 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dx, dy, dz, x, NDOF_C, NDOF_O,
1392 NDOF_C, mnq, mnq - 1, mnq)
1395 for (
int qx = 0; qx < NQUAD_O; ++qx)
1397 u += QDD[0][tidz][qx][dz][dy] * Gco(qx, dx);
1399 DDD[0][tidz][dz][dy][dx] =
u;
1403 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dx, dy, dz, x, NDOF_C, NDOF_O,
1404 NDOF_C, mnq, mnq - 1, mnq)
1407 for (
int qx = 0; qx < NQUAD_C; ++qx)
1409 u += QDD[1][tidz][qx][dz][dy] * Bcc(qx, dx);
1411 Y(dx + (dy + dz * NDOF_O) * NDOF_C + offset, e) =
1412 DDD[0][tidz][dz][dy][dx] -
u;
1418 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dz, qx, qy, x, NDOF_O, NQUAD_C,
1419 NQUAD_O, mnq, mnq, mnq - 1)
1422 for (
int qz = 0; qz < NQUAD_O; ++qz)
1424 u += X[0][tidz][qx + (qy + qz * NQUAD_O) * NQUAD_C] * Boo(qz, dz);
1426 QQD[0][tidz][qy][qx][dz] =
u;
1429 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dz, qx, qy, x, NDOF_O, NQUAD_O,
1430 NQUAD_C, mnq, mnq - 1, mnq)
1433 for (
int qz = 0; qz < NQUAD_O; ++qz)
1435 u += X[1][tidz][qx + (qy + qz * NQUAD_C) * NQUAD_O] * Boo(qz, dz);
1437 QQD[1][tidz][qy][qx][dz] =
u;
1442 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dy, dz, qx, x, NDOF_C, NDOF_O,
1443 NQUAD_C, mnq, mnq - 1, mnq)
1446 for (
int qy = 0; qy < NQUAD_O; ++qy)
1448 u += QQD[0][tidz][qy][qx][dz] * Gco(qy, dy);
1450 QDD[0][tidz][qx][dz][dy] =
u;
1453 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dy, dz, qx, x, NDOF_C, NDOF_O,
1454 NQUAD_O, mnq, mnq, mnq - 1)
1457 for (
int qy = 0; qy < NQUAD_C; ++qy)
1459 u += QQD[1][tidz][qy][qx][dz] * Bcc(qy, dy);
1461 QDD[1][tidz][qx][dz][dy] =
u;
1466 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dx, dy, dz, x, NDOF_C, NDOF_C,
1467 NDOF_O, mnq, mnq, mnq - 1)
1470 for (
int qx = 0; qx < NQUAD_C; ++qx)
1472 u += QDD[0][tidz][qx][dz][dy] * Bcc(qx, dx);
1474 DDD[0][tidz][dz][dy][dx] =
u;
1478 MFEM_FOREACH_THREAD_DIRECT_3D_OFFSET(dx, dy, dz, x, NDOF_C, NDOF_C,
1479 NDOF_O, mnq, mnq, mnq - 1)
1482 for (
int qx = 0; qx < NQUAD_O; ++qx)
1484 u += QDD[1][tidz][qx][dz][dy] * Gco(qx, dx);
1486 Y(dx + (dy + dz * NDOF_C) * NDOF_C + 2 * offset, e) =
1487 DDD[0][tidz][dz][dy][dx] -
u;
1495template <
int DIM,
int NDOF_O,
int NQUAD_O>
1497CurlInterpolator::ApplyPAKernels::Kernel()
1499 if constexpr (
DIM == 3)
1501 return internal::CurlInterpolatorApply3DSmem<NDOF_O, NQUAD_O>;
1503 MFEM_ABORT(
"Bad dimension!");
1506template <
int DIM,
int NDOF_O,
int NQUAD_O>
1508CurlInterpolator::ApplyTPAKernels::Kernel()
1510 if constexpr (
DIM == 3)
1512 return internal::CurlInterpolatorTApply3DSmem<NDOF_O, NQUAD_O>;
1514 MFEM_ABORT(
"Bad dimension!");
void(*)(const int ne, const int ndof_o, const int nquad_o, const Vector &pa, const Vector &x, Vector &y) ApplyKernelType
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(int N, lambda &&body)
static const DeviceDofQuadLimits & Get()
Return a const reference to the DeviceDofQuadLimits singleton.