25void PAHcurlApplyCurl2D(
const int c_dofs1D,
28 const Array<real_t> &Bo_,
29 const Array<real_t> &Gc_,
33 auto Bo =
Reshape(Bo_.Read(), o_dofs1D, o_dofs1D);
34 auto Gc =
Reshape(Gc_.Read(), o_dofs1D, c_dofs1D);
35 auto X =
Reshape(x_.Read(), 2 * c_dofs1D * o_dofs1D, NE);
36 auto Y =
Reshape(y_.ReadWrite(), o_dofs1D, o_dofs1D, NE);
40 for (
int iy = 0; iy < c_dofs1D; ++iy)
42 for (
int ix = 0; ix < o_dofs1D; ++ix)
44 const real_t xv = X(ix + iy * o_dofs1D, e);
45 for (
int oy = 0; oy < o_dofs1D; ++oy)
47 const real_t gy = Gc(oy, iy);
48 for (
int ox = 0; ox < o_dofs1D; ++ox)
50 Y(ox, oy, e) -= Bo(ox, ix) * gy * xv;
56 const int y_nd = c_dofs1D * o_dofs1D;
57 for (
int iy = 0; iy < o_dofs1D; ++iy)
59 for (
int ix = 0; ix < c_dofs1D; ++ix)
61 const real_t xv = X(y_nd + ix + iy * c_dofs1D, e);
62 for (
int oy = 0; oy < o_dofs1D; ++oy)
64 const real_t by = Bo(oy, iy);
65 for (
int ox = 0; ox < o_dofs1D; ++ox)
67 Y(ox, oy, e) += Gc(ox, ix) * by * xv;
75void PAHcurlApplyCurlTranspose2D(
const int c_dofs1D,
78 const Array<real_t> &Bo_,
79 const Array<real_t> &Gc_,
83 auto Bo =
Reshape(Bo_.Read(), o_dofs1D, o_dofs1D);
84 auto Gc =
Reshape(Gc_.Read(), o_dofs1D, c_dofs1D);
85 auto X =
Reshape(x_.Read(), o_dofs1D, o_dofs1D, NE);
86 auto Y =
Reshape(y_.ReadWrite(), 2 * c_dofs1D * o_dofs1D, NE);
90 for (
int dy = 0; dy < c_dofs1D; ++dy)
92 for (
int dx = 0; dx < o_dofs1D; ++dx)
95 for (
int oy = 0; oy < o_dofs1D; ++oy)
97 const real_t gy = Gc(oy, dy);
98 for (
int ox = 0; ox < o_dofs1D; ++ox)
100 sum -= Bo(ox, dx) * gy * X(ox, oy, e);
103 Y(dx + dy * o_dofs1D, e) += sum;
107 const int y_nd = c_dofs1D * o_dofs1D;
108 for (
int dy = 0; dy < o_dofs1D; ++dy)
110 for (
int dx = 0; dx < c_dofs1D; ++dx)
113 for (
int oy = 0; oy < o_dofs1D; ++oy)
115 const real_t by = Bo(oy, dy);
116 for (
int ox = 0; ox < o_dofs1D; ++ox)
118 sum += Gc(ox, dx) * by * X(ox, oy, e);
121 Y(y_nd + dx + dy * c_dofs1D, e) += sum;
127void PAHdivApplyCurl2D(
const int c_dofs1D,
130 const Array<real_t> &Bc_,
131 const Array<real_t> &Gc_,
135 auto Bc =
Reshape(Bc_.Read(), c_dofs1D, c_dofs1D);
136 auto Gc =
Reshape(Gc_.Read(), o_dofs1D, c_dofs1D);
137 auto X =
Reshape(x_.Read(), c_dofs1D, c_dofs1D, NE);
138 auto Y =
Reshape(y_.ReadWrite(), 2 * c_dofs1D * o_dofs1D, NE);
142 for (
int iy = 0; iy < c_dofs1D; ++iy)
144 for (
int ix = 0; ix < c_dofs1D; ++ix)
146 const real_t xv = X(ix, iy, e);
147 for (
int oy = 0; oy < o_dofs1D; ++oy)
149 const real_t gy = Gc(oy, iy);
150 for (
int ox = 0; ox < c_dofs1D; ++ox)
152 Y(ox + oy * c_dofs1D, e) += Bc(ox, ix) * gy * xv;
158 const int y_nd = c_dofs1D * o_dofs1D;
159 for (
int iy = 0; iy < c_dofs1D; ++iy)
161 for (
int ix = 0; ix < c_dofs1D; ++ix)
163 const real_t xv = X(ix, iy, e);
164 for (
int oy = 0; oy < c_dofs1D; ++oy)
166 const real_t by = Bc(oy, iy);
167 for (
int ox = 0; ox < o_dofs1D; ++ox)
169 Y(y_nd + ox + oy * o_dofs1D, e) -= Gc(ox, ix) * by * xv;
177void PAHdivApplyCurlTranspose2D(
const int c_dofs1D,
180 const Array<real_t> &Bc_,
181 const Array<real_t> &Gc_,
185 auto Bc =
Reshape(Bc_.Read(), c_dofs1D, c_dofs1D);
186 auto Gc =
Reshape(Gc_.Read(), o_dofs1D, c_dofs1D);
187 auto X =
Reshape(x_.Read(), 2 * c_dofs1D * o_dofs1D, NE);
188 auto Y =
Reshape(y_.ReadWrite(), c_dofs1D, c_dofs1D, NE);
192 for (
int dy = 0; dy < o_dofs1D; ++dy)
194 for (
int dx = 0; dx < c_dofs1D; ++dx)
196 const real_t xv = X(dx + dy * c_dofs1D, e);
197 for (
int iy = 0; iy < c_dofs1D; ++iy)
199 const real_t gy = Gc(dy, iy);
200 for (
int ix = 0; ix < c_dofs1D; ++ix)
202 Y(ix, iy, e) += Bc(dx, ix) * gy * xv;
208 const int y_nd = c_dofs1D * o_dofs1D;
209 for (
int dy = 0; dy < c_dofs1D; ++dy)
211 for (
int dx = 0; dx < o_dofs1D; ++dx)
213 const real_t xv = X(y_nd + dx + dy * o_dofs1D, e);
214 for (
int iy = 0; iy < c_dofs1D; ++iy)
216 const real_t by = Bc(dy, iy);
217 for (
int ix = 0; ix < c_dofs1D; ++ix)
219 Y(ix, iy, e) -= Gc(dx, ix) * by * xv;
232static void PAHcurlApplyGradient2D(
const int c_dofs1D,
235 const Array<real_t> &B_,
236 const Array<real_t> &G_,
240 auto B =
Reshape(B_.Read(), c_dofs1D, c_dofs1D);
241 auto G =
Reshape(G_.Read(), o_dofs1D, c_dofs1D);
243 auto x =
Reshape(x_.Read(), c_dofs1D, c_dofs1D, NE);
244 auto y =
Reshape(y_.ReadWrite(), 2 * c_dofs1D * o_dofs1D, NE);
247 o_dofs1D <= c_dofs1D,
"");
251 constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
252 real_t w[MAX_D1D][MAX_D1D];
255 for (
int dx = 0; dx < c_dofs1D; ++dx)
257 for (
int ey = 0; ey < c_dofs1D; ++ey)
260 for (
int dy = 0; dy < c_dofs1D; ++dy)
262 w[dx][ey] += B(ey, dy) * x(dx, dy, e);
267 for (
int ey = 0; ey < c_dofs1D; ++ey)
269 for (
int ex = 0; ex < o_dofs1D; ++ex)
272 for (
int dx = 0; dx < c_dofs1D; ++dx)
274 s += G(ex, dx) * w[dx][ey];
276 const int local_index = ey*o_dofs1D + ex;
277 y(local_index, e) += s;
282 for (
int dx = 0; dx < c_dofs1D; ++dx)
284 for (
int ey = 0; ey < o_dofs1D; ++ey)
287 for (
int dy = 0; dy < c_dofs1D; ++dy)
289 w[dx][ey] += G(ey, dy) * x(dx, dy, e);
294 for (
int ey = 0; ey < o_dofs1D; ++ey)
296 for (
int ex = 0; ex < c_dofs1D; ++ex)
299 for (
int dx = 0; dx < c_dofs1D; ++dx)
301 s += B(ex, dx) * w[dx][ey];
303 const int local_index = c_dofs1D * o_dofs1D + ey*c_dofs1D + ex;
304 y(local_index, e) += s;
311static void PAHcurlApplyGradient2DBId(
const int c_dofs1D,
314 const Array<real_t> &G_,
318 auto G =
Reshape(G_.Read(), o_dofs1D, c_dofs1D);
320 auto x =
Reshape(x_.Read(), c_dofs1D, c_dofs1D, NE);
321 auto y =
Reshape(y_.ReadWrite(), 2 * c_dofs1D * o_dofs1D, NE);
324 o_dofs1D <= c_dofs1D,
"");
328 constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
329 real_t w[MAX_D1D][MAX_D1D];
332 for (
int dx = 0; dx < c_dofs1D; ++dx)
334 for (
int ey = 0; ey < c_dofs1D; ++ey)
337 w[dx][ey] = x(dx, dy, e);
341 for (
int ey = 0; ey < c_dofs1D; ++ey)
343 for (
int ex = 0; ex < o_dofs1D; ++ex)
346 for (
int dx = 0; dx < c_dofs1D; ++dx)
348 s += G(ex, dx) * w[dx][ey];
350 const int local_index = ey*o_dofs1D + ex;
351 y(local_index, e) += s;
356 for (
int dx = 0; dx < c_dofs1D; ++dx)
358 for (
int ey = 0; ey < o_dofs1D; ++ey)
361 for (
int dy = 0; dy < c_dofs1D; ++dy)
363 w[dx][ey] += G(ey, dy) * x(dx, dy, e);
368 for (
int ey = 0; ey < o_dofs1D; ++ey)
370 for (
int ex = 0; ex < c_dofs1D; ++ex)
373 const real_t s = w[dx][ey];
374 const int local_index = c_dofs1D * o_dofs1D + ey*c_dofs1D + ex;
375 y(local_index, e) += s;
381static void PAHcurlApplyGradientTranspose2D(
382 const int c_dofs1D,
const int o_dofs1D,
const int NE,
383 const Array<real_t> &B_,
const Array<real_t> &G_,
384 const Vector &x_, Vector &y_)
386 auto B =
Reshape(B_.Read(), c_dofs1D, c_dofs1D);
387 auto G =
Reshape(G_.Read(), o_dofs1D, c_dofs1D);
389 auto x =
Reshape(x_.Read(), 2 * c_dofs1D * o_dofs1D, NE);
390 auto y =
Reshape(y_.ReadWrite(), c_dofs1D, c_dofs1D, NE);
393 o_dofs1D <= c_dofs1D,
"");
397 constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
398 real_t w[MAX_D1D][MAX_D1D];
401 for (
int dy = 0; dy < c_dofs1D; ++dy)
403 for (
int ex = 0; ex < o_dofs1D; ++ex)
406 for (
int ey = 0; ey < c_dofs1D; ++ey)
408 const int local_index = ey*o_dofs1D + ex;
409 w[dy][ex] += B(ey, dy) * x(local_index, e);
414 for (
int dy = 0; dy < c_dofs1D; ++dy)
416 for (
int dx = 0; dx < c_dofs1D; ++dx)
419 for (
int ex = 0; ex < o_dofs1D; ++ex)
421 s += G(ex, dx) * w[dy][ex];
428 for (
int dy = 0; dy < c_dofs1D; ++dy)
430 for (
int ex = 0; ex < c_dofs1D; ++ex)
433 for (
int ey = 0; ey < o_dofs1D; ++ey)
435 const int local_index = c_dofs1D * o_dofs1D + ey*c_dofs1D + ex;
436 w[dy][ex] += G(ey, dy) * x(local_index, e);
441 for (
int dy = 0; dy < c_dofs1D; ++dy)
443 for (
int dx = 0; dx < c_dofs1D; ++dx)
446 for (
int ex = 0; ex < c_dofs1D; ++ex)
448 s += B(ex, dx) * w[dy][ex];
458static void PAHcurlApplyGradientTranspose2DBId(
459 const int c_dofs1D,
const int o_dofs1D,
const int NE,
460 const Array<real_t> &G_,
461 const Vector &x_, Vector &y_)
463 auto G =
Reshape(G_.Read(), o_dofs1D, c_dofs1D);
465 auto x =
Reshape(x_.Read(), 2 * c_dofs1D * o_dofs1D, NE);
466 auto y =
Reshape(y_.ReadWrite(), c_dofs1D, c_dofs1D, NE);
469 o_dofs1D <= c_dofs1D,
"");
473 constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
474 real_t w[MAX_D1D][MAX_D1D];
477 for (
int dy = 0; dy < c_dofs1D; ++dy)
479 for (
int ex = 0; ex < o_dofs1D; ++ex)
482 const int local_index = ey*o_dofs1D + ex;
483 w[dy][ex] = x(local_index, e);
487 for (
int dy = 0; dy < c_dofs1D; ++dy)
489 for (
int dx = 0; dx < c_dofs1D; ++dx)
492 for (
int ex = 0; ex < o_dofs1D; ++ex)
494 s += G(ex, dx) * w[dy][ex];
501 for (
int dy = 0; dy < c_dofs1D; ++dy)
503 for (
int ex = 0; ex < c_dofs1D; ++ex)
506 for (
int ey = 0; ey < o_dofs1D; ++ey)
508 const int local_index = c_dofs1D * o_dofs1D + ey*c_dofs1D + ex;
509 w[dy][ex] += G(ey, dy) * x(local_index, e);
514 for (
int dy = 0; dy < c_dofs1D; ++dy)
516 for (
int dx = 0; dx < c_dofs1D; ++dx)
519 const real_t s = w[dy][ex];
526static void PAHcurlApplyGradient3D(
const int c_dofs1D,
529 const Array<real_t> &B_,
530 const Array<real_t> &G_,
534 auto B =
Reshape(B_.Read(), c_dofs1D, c_dofs1D);
535 auto G =
Reshape(G_.Read(), o_dofs1D, c_dofs1D);
537 auto x =
Reshape(x_.Read(), c_dofs1D, c_dofs1D, c_dofs1D, NE);
538 auto y =
Reshape(y_.ReadWrite(), (3 * c_dofs1D * c_dofs1D * o_dofs1D), NE);
541 o_dofs1D <= c_dofs1D,
"");
545 constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
546 real_t w1[MAX_D1D][MAX_D1D][MAX_D1D];
547 real_t w2[MAX_D1D][MAX_D1D][MAX_D1D];
554 for (
int ez = 0; ez < c_dofs1D; ++ez)
556 for (
int dx = 0; dx < c_dofs1D; ++dx)
558 for (
int dy = 0; dy < c_dofs1D; ++dy)
560 w1[dx][dy][ez] = 0.0;
561 for (
int dz = 0; dz < c_dofs1D; ++dz)
563 w1[dx][dy][ez] += B(ez, dz) * x(dx, dy, dz, e);
570 for (
int ez = 0; ez < c_dofs1D; ++ez)
572 for (
int ey = 0; ey < c_dofs1D; ++ey)
574 for (
int dx = 0; dx < c_dofs1D; ++dx)
576 w2[dx][ey][ez] = 0.0;
577 for (
int dy = 0; dy < c_dofs1D; ++dy)
579 w2[dx][ey][ez] += B(ey, dy) * w1[dx][dy][ez];
586 for (
int ez = 0; ez < c_dofs1D; ++ez)
588 for (
int ey = 0; ey < c_dofs1D; ++ey)
590 for (
int ex = 0; ex < o_dofs1D; ++ex)
593 for (
int dx = 0; dx < c_dofs1D; ++dx)
595 s += G(ex, dx) * w2[dx][ey][ez];
597 const int local_index = ez*c_dofs1D*o_dofs1D + ey*o_dofs1D + ex;
598 y(local_index, e) += s;
608 for (
int ez = 0; ez < c_dofs1D; ++ez)
610 for (
int dx = 0; dx < c_dofs1D; ++dx)
612 for (
int dy = 0; dy < c_dofs1D; ++dy)
614 w1[dx][dy][ez] = 0.0;
615 for (
int dz = 0; dz < c_dofs1D; ++dz)
617 w1[dx][dy][ez] += B(ez, dz) * x(dx, dy, dz, e);
624 for (
int ez = 0; ez < c_dofs1D; ++ez)
626 for (
int ey = 0; ey < o_dofs1D; ++ey)
628 for (
int dx = 0; dx < c_dofs1D; ++dx)
630 w2[dx][ey][ez] = 0.0;
631 for (
int dy = 0; dy < c_dofs1D; ++dy)
633 w2[dx][ey][ez] += G(ey, dy) * w1[dx][dy][ez];
640 for (
int ez = 0; ez < c_dofs1D; ++ez)
642 for (
int ey = 0; ey < o_dofs1D; ++ey)
644 for (
int ex = 0; ex < c_dofs1D; ++ex)
647 for (
int dx = 0; dx < c_dofs1D; ++dx)
649 s += B(ex, dx) * w2[dx][ey][ez];
651 const int local_index = c_dofs1D*c_dofs1D*o_dofs1D +
652 ez*c_dofs1D*o_dofs1D + ey*c_dofs1D + ex;
653 y(local_index, e) += s;
663 for (
int ez = 0; ez < o_dofs1D; ++ez)
665 for (
int dx = 0; dx < c_dofs1D; ++dx)
667 for (
int dy = 0; dy < c_dofs1D; ++dy)
669 w1[dx][dy][ez] = 0.0;
670 for (
int dz = 0; dz < c_dofs1D; ++dz)
672 w1[dx][dy][ez] += G(ez, dz) * x(dx, dy, dz, e);
679 for (
int ez = 0; ez < o_dofs1D; ++ez)
681 for (
int ey = 0; ey < c_dofs1D; ++ey)
683 for (
int dx = 0; dx < c_dofs1D; ++dx)
685 w2[dx][ey][ez] = 0.0;
686 for (
int dy = 0; dy < c_dofs1D; ++dy)
688 w2[dx][ey][ez] += B(ey, dy) * w1[dx][dy][ez];
695 for (
int ez = 0; ez < o_dofs1D; ++ez)
697 for (
int ey = 0; ey < c_dofs1D; ++ey)
699 for (
int ex = 0; ex < c_dofs1D; ++ex)
702 for (
int dx = 0; dx < c_dofs1D; ++dx)
704 s += B(ex, dx) * w2[dx][ey][ez];
706 const int local_index = 2*c_dofs1D*c_dofs1D*o_dofs1D +
707 ez*c_dofs1D*c_dofs1D + ey*c_dofs1D + ex;
708 y(local_index, e) += s;
716static void PAHcurlApplyGradient3DBId(
const int c_dofs1D,
719 const Array<real_t> &G_,
723 auto G =
Reshape(G_.Read(), o_dofs1D, c_dofs1D);
725 auto x =
Reshape(x_.Read(), c_dofs1D, c_dofs1D, c_dofs1D, NE);
726 auto y =
Reshape(y_.ReadWrite(), (3 * c_dofs1D * c_dofs1D * o_dofs1D), NE);
729 o_dofs1D <= c_dofs1D,
"");
733 constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
735 real_t w1[MAX_D1D][MAX_D1D][MAX_D1D];
736 real_t w2[MAX_D1D][MAX_D1D][MAX_D1D];
743 for (
int ez = 0; ez < c_dofs1D; ++ez)
745 for (
int dx = 0; dx < c_dofs1D; ++dx)
747 for (
int dy = 0; dy < c_dofs1D; ++dy)
750 w1[dx][dy][ez] = x(dx, dy, dz, e);
756 for (
int ez = 0; ez < c_dofs1D; ++ez)
758 for (
int ey = 0; ey < c_dofs1D; ++ey)
760 for (
int dx = 0; dx < c_dofs1D; ++dx)
763 w2[dx][ey][ez] = w1[dx][dy][ez];
769 for (
int ez = 0; ez < c_dofs1D; ++ez)
771 for (
int ey = 0; ey < c_dofs1D; ++ey)
773 for (
int ex = 0; ex < o_dofs1D; ++ex)
776 for (
int dx = 0; dx < c_dofs1D; ++dx)
778 s += G(ex, dx) * w2[dx][ey][ez];
780 const int local_index = ez*c_dofs1D*o_dofs1D + ey*o_dofs1D + ex;
781 y(local_index, e) += s;
791 for (
int ez = 0; ez < c_dofs1D; ++ez)
793 for (
int dx = 0; dx < c_dofs1D; ++dx)
795 for (
int dy = 0; dy < c_dofs1D; ++dy)
798 w1[dx][dy][ez] = x(dx, dy, dz, e);
804 for (
int ez = 0; ez < c_dofs1D; ++ez)
806 for (
int ey = 0; ey < o_dofs1D; ++ey)
808 for (
int dx = 0; dx < c_dofs1D; ++dx)
810 w2[dx][ey][ez] = 0.0;
811 for (
int dy = 0; dy < c_dofs1D; ++dy)
813 w2[dx][ey][ez] += G(ey, dy) * w1[dx][dy][ez];
820 for (
int ez = 0; ez < c_dofs1D; ++ez)
822 for (
int ey = 0; ey < o_dofs1D; ++ey)
824 for (
int ex = 0; ex < c_dofs1D; ++ex)
827 const real_t s = w2[dx][ey][ez];
828 const int local_index = c_dofs1D*c_dofs1D*o_dofs1D +
829 ez*c_dofs1D*o_dofs1D + ey*c_dofs1D + ex;
830 y(local_index, e) += s;
840 for (
int ez = 0; ez < o_dofs1D; ++ez)
842 for (
int dx = 0; dx < c_dofs1D; ++dx)
844 for (
int dy = 0; dy < c_dofs1D; ++dy)
846 w1[dx][dy][ez] = 0.0;
847 for (
int dz = 0; dz < c_dofs1D; ++dz)
849 w1[dx][dy][ez] += G(ez, dz) * x(dx, dy, dz, e);
856 for (
int ez = 0; ez < o_dofs1D; ++ez)
858 for (
int ey = 0; ey < c_dofs1D; ++ey)
860 for (
int dx = 0; dx < c_dofs1D; ++dx)
863 w2[dx][ey][ez] = w1[dx][dy][ez];
869 for (
int ez = 0; ez < o_dofs1D; ++ez)
871 for (
int ey = 0; ey < c_dofs1D; ++ey)
873 for (
int ex = 0; ex < c_dofs1D; ++ex)
876 const real_t s = w2[dx][ey][ez];
877 const int local_index = 2*c_dofs1D*c_dofs1D*o_dofs1D +
878 ez*c_dofs1D*c_dofs1D + ey*c_dofs1D + ex;
879 y(local_index, e) += s;
886static void PAHcurlApplyGradientTranspose3D(
887 const int c_dofs1D,
const int o_dofs1D,
const int NE,
888 const Array<real_t> &B_,
const Array<real_t> &G_,
889 const Vector &x_, Vector &y_)
891 auto B =
Reshape(B_.Read(), c_dofs1D, c_dofs1D);
892 auto G =
Reshape(G_.Read(), o_dofs1D, c_dofs1D);
894 auto x =
Reshape(x_.Read(), (3 * c_dofs1D * c_dofs1D * o_dofs1D), NE);
895 auto y =
Reshape(y_.ReadWrite(), c_dofs1D, c_dofs1D, c_dofs1D, NE);
898 o_dofs1D <= c_dofs1D,
"");
902 constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
903 real_t w1[MAX_D1D][MAX_D1D][MAX_D1D];
904 real_t w2[MAX_D1D][MAX_D1D][MAX_D1D];
910 for (
int dz = 0; dz < c_dofs1D; ++dz)
912 for (
int ex = 0; ex < o_dofs1D; ++ex)
914 for (
int ey = 0; ey < c_dofs1D; ++ey)
916 w1[ex][ey][dz] = 0.0;
917 for (
int ez = 0; ez < c_dofs1D; ++ez)
919 const int local_index = ez*c_dofs1D*o_dofs1D + ey*o_dofs1D + ex;
920 w1[ex][ey][dz] += B(ez, dz) * x(local_index, e);
927 for (
int dz = 0; dz < c_dofs1D; ++dz)
929 for (
int dy = 0; dy < c_dofs1D; ++dy)
931 for (
int ex = 0; ex < o_dofs1D; ++ex)
933 w2[ex][dy][dz] = 0.0;
934 for (
int ey = 0; ey < c_dofs1D; ++ey)
936 w2[ex][dy][dz] += B(ey, dy) * w1[ex][ey][dz];
943 for (
int dz = 0; dz < c_dofs1D; ++dz)
945 for (
int dy = 0; dy < c_dofs1D; ++dy)
947 for (
int dx = 0; dx < c_dofs1D; ++dx)
950 for (
int ex = 0; ex < o_dofs1D; ++ex)
952 s += G(ex, dx) * w2[ex][dy][dz];
954 y(dx, dy, dz, e) += s;
964 for (
int dz = 0; dz < c_dofs1D; ++dz)
966 for (
int ex = 0; ex < c_dofs1D; ++ex)
968 for (
int ey = 0; ey < o_dofs1D; ++ey)
970 w1[ex][ey][dz] = 0.0;
971 for (
int ez = 0; ez < c_dofs1D; ++ez)
973 const int local_index = c_dofs1D*c_dofs1D*o_dofs1D +
974 ez*c_dofs1D*o_dofs1D + ey*c_dofs1D + ex;
975 w1[ex][ey][dz] += B(ez, dz) * x(local_index, e);
982 for (
int dz = 0; dz < c_dofs1D; ++dz)
984 for (
int dy = 0; dy < c_dofs1D; ++dy)
986 for (
int ex = 0; ex < c_dofs1D; ++ex)
988 w2[ex][dy][dz] = 0.0;
989 for (
int ey = 0; ey < o_dofs1D; ++ey)
991 w2[ex][dy][dz] += G(ey, dy) * w1[ex][ey][dz];
998 for (
int dz = 0; dz < c_dofs1D; ++dz)
1000 for (
int dy = 0; dy < c_dofs1D; ++dy)
1002 for (
int dx = 0; dx < c_dofs1D; ++dx)
1005 for (
int ex = 0; ex < c_dofs1D; ++ex)
1007 s += B(ex, dx) * w2[ex][dy][dz];
1009 y(dx, dy, dz, e) += s;
1019 for (
int dz = 0; dz < c_dofs1D; ++dz)
1021 for (
int ex = 0; ex < c_dofs1D; ++ex)
1023 for (
int ey = 0; ey < c_dofs1D; ++ey)
1025 w1[ex][ey][dz] = 0.0;
1026 for (
int ez = 0; ez < o_dofs1D; ++ez)
1028 const int local_index = 2*c_dofs1D*c_dofs1D*o_dofs1D +
1029 ez*c_dofs1D*c_dofs1D + ey*c_dofs1D + ex;
1030 w1[ex][ey][dz] += G(ez, dz) * x(local_index, e);
1037 for (
int dz = 0; dz < c_dofs1D; ++dz)
1039 for (
int dy = 0; dy < c_dofs1D; ++dy)
1041 for (
int ex = 0; ex < c_dofs1D; ++ex)
1043 w2[ex][dy][dz] = 0.0;
1044 for (
int ey = 0; ey < c_dofs1D; ++ey)
1046 w2[ex][dy][dz] += B(ey, dy) * w1[ex][ey][dz];
1053 for (
int dz = 0; dz < c_dofs1D; ++dz)
1055 for (
int dy = 0; dy < c_dofs1D; ++dy)
1057 for (
int dx = 0; dx < c_dofs1D; ++dx)
1060 for (
int ex = 0; ex < c_dofs1D; ++ex)
1062 s += B(ex, dx) * w2[ex][dy][dz];
1064 y(dx, dy, dz, e) += s;
1073static void PAHcurlApplyGradientTranspose3DBId(
1074 const int c_dofs1D,
const int o_dofs1D,
const int NE,
1075 const Array<real_t> &G_,
1076 const Vector &x_, Vector &y_)
1078 auto G =
Reshape(G_.Read(), o_dofs1D, c_dofs1D);
1080 auto x =
Reshape(x_.Read(), (3 * c_dofs1D * c_dofs1D * o_dofs1D), NE);
1081 auto y =
Reshape(y_.ReadWrite(), c_dofs1D, c_dofs1D, c_dofs1D, NE);
1084 o_dofs1D <= c_dofs1D,
"");
1088 constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
1090 real_t w1[MAX_D1D][MAX_D1D][MAX_D1D];
1091 real_t w2[MAX_D1D][MAX_D1D][MAX_D1D];
1097 for (
int dz = 0; dz < c_dofs1D; ++dz)
1099 for (
int ex = 0; ex < o_dofs1D; ++ex)
1101 for (
int ey = 0; ey < c_dofs1D; ++ey)
1104 const int local_index = ez*c_dofs1D*o_dofs1D + ey*o_dofs1D + ex;
1105 w1[ex][ey][dz] = x(local_index, e);
1111 for (
int dz = 0; dz < c_dofs1D; ++dz)
1113 for (
int dy = 0; dy < c_dofs1D; ++dy)
1115 for (
int ex = 0; ex < o_dofs1D; ++ex)
1118 w2[ex][dy][dz] = w1[ex][ey][dz];
1124 for (
int dz = 0; dz < c_dofs1D; ++dz)
1126 for (
int dy = 0; dy < c_dofs1D; ++dy)
1128 for (
int dx = 0; dx < c_dofs1D; ++dx)
1131 for (
int ex = 0; ex < o_dofs1D; ++ex)
1133 s += G(ex, dx) * w2[ex][dy][dz];
1135 y(dx, dy, dz, e) += s;
1145 for (
int dz = 0; dz < c_dofs1D; ++dz)
1147 for (
int ex = 0; ex < c_dofs1D; ++ex)
1149 for (
int ey = 0; ey < o_dofs1D; ++ey)
1152 const int local_index = c_dofs1D*c_dofs1D*o_dofs1D +
1153 ez*c_dofs1D*o_dofs1D + ey*c_dofs1D + ex;
1154 w1[ex][ey][dz] = x(local_index, e);
1160 for (
int dz = 0; dz < c_dofs1D; ++dz)
1162 for (
int dy = 0; dy < c_dofs1D; ++dy)
1164 for (
int ex = 0; ex < c_dofs1D; ++ex)
1166 w2[ex][dy][dz] = 0.0;
1167 for (
int ey = 0; ey < o_dofs1D; ++ey)
1169 w2[ex][dy][dz] += G(ey, dy) * w1[ex][ey][dz];
1176 for (
int dz = 0; dz < c_dofs1D; ++dz)
1178 for (
int dy = 0; dy < c_dofs1D; ++dy)
1180 for (
int dx = 0; dx < c_dofs1D; ++dx)
1183 real_t s = w2[ex][dy][dz];
1184 y(dx, dy, dz, e) += s;
1194 for (
int dz = 0; dz < c_dofs1D; ++dz)
1196 for (
int ex = 0; ex < c_dofs1D; ++ex)
1198 for (
int ey = 0; ey < c_dofs1D; ++ey)
1200 w1[ex][ey][dz] = 0.0;
1201 for (
int ez = 0; ez < o_dofs1D; ++ez)
1203 const int local_index = 2*c_dofs1D*c_dofs1D*o_dofs1D +
1204 ez*c_dofs1D*c_dofs1D + ey*c_dofs1D + ex;
1205 w1[ex][ey][dz] += G(ez, dz) * x(local_index, e);
1212 for (
int dz = 0; dz < c_dofs1D; ++dz)
1214 for (
int dy = 0; dy < c_dofs1D; ++dy)
1216 for (
int ex = 0; ex < c_dofs1D; ++ex)
1219 w2[ex][dy][dz] = w1[ex][ey][dz];
1225 for (
int dz = 0; dz < c_dofs1D; ++dz)
1227 for (
int dy = 0; dy < c_dofs1D; ++dy)
1229 for (
int dx = 0; dx < c_dofs1D; ++dx)
1232 real_t s = w2[ex][dy][dz];
1233 y(dx, dy, dz, e) += s;
1250 MFEM_VERIFY(trial_el != NULL,
"Only NodalTensorFiniteElement is supported!");
1254 MFEM_VERIFY(test_el != NULL,
"Only VectorTensorFiniteElement is supported!");
1256 const int dims = trial_el->
GetDim();
1257 MFEM_VERIFY(dims == 2 || dims == 3,
"Bad dimension!");
1259 MFEM_VERIFY(dim == 2 || dim == 3,
"Bad dimension!");
1261 "Orders do not match!");
1262 ne = trial_fes.
GetNE();
1264 const int order = trial_el->
GetOrder();
1275 o_dofs1D = maps_O_C->
nqpt;
1279 c_dofs1D = maps_O_C->
ndof;
1285 c_dofs1D = maps_C_C->
nqpt;
1295 PAHcurlApplyGradient3DBId(c_dofs1D, o_dofs1D, ne,
1300 PAHcurlApplyGradient3D(c_dofs1D, o_dofs1D, ne, maps_C_C->
B,
1308 PAHcurlApplyGradient2DBId(c_dofs1D, o_dofs1D, ne,
1313 PAHcurlApplyGradient2D(c_dofs1D, o_dofs1D, ne, maps_C_C->
B, maps_O_C->
G,
1329 PAHcurlApplyGradientTranspose3DBId(c_dofs1D, o_dofs1D, ne,
1334 PAHcurlApplyGradientTranspose3D(c_dofs1D, o_dofs1D, ne, maps_C_C->
B,
1342 PAHcurlApplyGradientTranspose2DBId(c_dofs1D, o_dofs1D, ne,
1347 PAHcurlApplyGradientTranspose2D(c_dofs1D, o_dofs1D, ne, maps_C_C->
B,
1357static void PAHcurlVecH1IdentityApply2D(
const int c_dofs1D,
1366 auto Bc =
Reshape(Bclosed.
Read(), c_dofs1D, c_dofs1D);
1367 auto Bo =
Reshape(Bopen.
Read(), o_dofs1D, c_dofs1D);
1369 auto x =
Reshape(x_.
Read(), c_dofs1D, c_dofs1D, 2, NE);
1372 auto vk =
Reshape(pa_data.
Read(), 2, (2 * c_dofs1D * o_dofs1D), NE);
1375 o_dofs1D <= c_dofs1D,
"");
1379 constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
1381 real_t w[2][MAX_D1D][MAX_D1D];
1386 for (
int ey = 0; ey < c_dofs1D; ++ey)
1388 for (
int dx = 0; dx < c_dofs1D; ++dx)
1390 for (
int j=0; j<2; ++j)
1393 for (
int dy = 0; dy < c_dofs1D; ++dy)
1395 w[j][dx][ey] += Bc(ey, dy) * x(dx, dy, j, e);
1402 for (
int ey = 0; ey < c_dofs1D; ++ey)
1404 for (
int ex = 0; ex < o_dofs1D; ++ex)
1406 for (
int j=0; j<2; ++j)
1409 for (
int dx = 0; dx < c_dofs1D; ++dx)
1411 s += Bo(ex, dx) * w[j][dx][ey];
1413 const int local_index = ey*o_dofs1D + ex;
1414 y(local_index, e) += s * vk(j, local_index, e);
1422 for (
int ey = 0; ey < o_dofs1D; ++ey)
1424 for (
int dx = 0; dx < c_dofs1D; ++dx)
1426 for (
int j=0; j<2; ++j)
1429 for (
int dy = 0; dy < c_dofs1D; ++dy)
1431 w[j][dx][ey] += Bo(ey, dy) * x(dx, dy, j, e);
1438 for (
int ey = 0; ey < o_dofs1D; ++ey)
1440 for (
int ex = 0; ex < c_dofs1D; ++ex)
1442 for (
int j=0; j<2; ++j)
1445 for (
int dx = 0; dx < c_dofs1D; ++dx)
1447 s += Bc(ex, dx) * w[j][dx][ey];
1449 const int local_index = c_dofs1D*o_dofs1D + ey*c_dofs1D + ex;
1450 y(local_index, e) += s * vk(j, local_index, e);
1457static void PAHcurlVecH1IdentityApplyTranspose2D(
const int c_dofs1D,
1460 const Array<real_t> &Bclosed,
1461 const Array<real_t> &Bopen,
1462 const Vector &pa_data,
1466 auto Bc =
Reshape(Bclosed.Read(), c_dofs1D, c_dofs1D);
1467 auto Bo =
Reshape(Bopen.Read(), o_dofs1D, c_dofs1D);
1469 auto x =
Reshape(x_.Read(), (2 * c_dofs1D * o_dofs1D), NE);
1470 auto y =
Reshape(y_.ReadWrite(), c_dofs1D, c_dofs1D, 2, NE);
1472 auto vk =
Reshape(pa_data.Read(), 2, (2 * c_dofs1D * o_dofs1D), NE);
1475 o_dofs1D <= c_dofs1D,
"");
1479 constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
1481 real_t w[2][MAX_D1D][MAX_D1D];
1486 for (
int ey = 0; ey < c_dofs1D; ++ey)
1488 for (
int dx = 0; dx < c_dofs1D; ++dx)
1490 for (
int j=0; j<2; ++j) { w[j][dx][ey] = 0.0; }
1492 for (
int ex = 0; ex < o_dofs1D; ++ex)
1494 const int local_index = ey*o_dofs1D + ex;
1495 const real_t xd = x(local_index, e);
1497 for (
int dx = 0; dx < c_dofs1D; ++dx)
1499 for (
int j=0; j<2; ++j)
1501 w[j][dx][ey] += Bo(ex, dx) * xd * vk(j, local_index, e);
1508 for (
int dx = 0; dx < c_dofs1D; ++dx)
1510 for (
int dy = 0; dy < c_dofs1D; ++dy)
1512 for (
int j=0; j<2; ++j)
1515 for (
int ey = 0; ey < c_dofs1D; ++ey)
1517 s += w[j][dx][ey] * Bc(ey, dy);
1519 y(dx, dy, j, e) += s;
1527 for (
int ey = 0; ey < o_dofs1D; ++ey)
1529 for (
int dx = 0; dx < c_dofs1D; ++dx)
1531 for (
int j=0; j<2; ++j) { w[j][dx][ey] = 0.0; }
1533 for (
int ex = 0; ex < c_dofs1D; ++ex)
1535 const int local_index = c_dofs1D*o_dofs1D + ey*c_dofs1D + ex;
1536 const real_t xd = x(local_index, e);
1537 for (
int dx = 0; dx < c_dofs1D; ++dx)
1539 for (
int j=0; j<2; ++j)
1541 w[j][dx][ey] += Bc(ex, dx) * xd * vk(j, local_index, e);
1548 for (
int dx = 0; dx < c_dofs1D; ++dx)
1550 for (
int dy = 0; dy < c_dofs1D; ++dy)
1552 for (
int j=0; j<2; ++j)
1555 for (
int ey = 0; ey < o_dofs1D; ++ey)
1557 s += w[j][dx][ey] * Bo(ey, dy);
1559 y(dx, dy, j, e) += s;
1566static void PAHcurlVecH1IdentityApply3D(
const int c_dofs1D,
1569 const Array<real_t> &Bclosed,
1570 const Array<real_t> &Bopen,
1571 const Vector &pa_data,
1575 auto Bc =
Reshape(Bclosed.Read(), c_dofs1D, c_dofs1D);
1576 auto Bo =
Reshape(Bopen.Read(), o_dofs1D, c_dofs1D);
1578 auto x =
Reshape(x_.Read(), c_dofs1D, c_dofs1D, c_dofs1D, 3, NE);
1579 auto y =
Reshape(y_.ReadWrite(), (3 * c_dofs1D * c_dofs1D * o_dofs1D), NE);
1581 auto vk =
Reshape(pa_data.Read(), 3, (3 * c_dofs1D * c_dofs1D * o_dofs1D),
1584 o_dofs1D <= c_dofs1D,
"");
1588 constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
1590 real_t w1[3][MAX_D1D][MAX_D1D][MAX_D1D];
1591 real_t w2[3][MAX_D1D][MAX_D1D][MAX_D1D];
1596 for (
int ez = 0; ez < c_dofs1D; ++ez)
1598 for (
int dx = 0; dx < c_dofs1D; ++dx)
1600 for (
int dy = 0; dy < c_dofs1D; ++dy)
1602 for (
int j=0; j<3; ++j)
1604 w1[j][dx][dy][ez] = 0.0;
1605 for (
int dz = 0; dz < c_dofs1D; ++dz)
1607 w1[j][dx][dy][ez] += Bc(ez, dz) * x(dx, dy, dz, j, e);
1615 for (
int ez = 0; ez < c_dofs1D; ++ez)
1617 for (
int ey = 0; ey < c_dofs1D; ++ey)
1619 for (
int dx = 0; dx < c_dofs1D; ++dx)
1621 for (
int j=0; j<3; ++j)
1623 w2[j][dx][ey][ez] = 0.0;
1624 for (
int dy = 0; dy < c_dofs1D; ++dy)
1626 w2[j][dx][ey][ez] += Bc(ey, dy) * w1[j][dx][dy][ez];
1634 for (
int ez = 0; ez < c_dofs1D; ++ez)
1636 for (
int ey = 0; ey < c_dofs1D; ++ey)
1638 for (
int ex = 0; ex < o_dofs1D; ++ex)
1640 for (
int j=0; j<3; ++j)
1643 for (
int dx = 0; dx < c_dofs1D; ++dx)
1645 s += Bo(ex, dx) * w2[j][dx][ey][ez];
1647 const int local_index = ez*c_dofs1D*o_dofs1D + ey*o_dofs1D + ex;
1648 y(local_index, e) += s * vk(j, local_index, e);
1657 for (
int ez = 0; ez < c_dofs1D; ++ez)
1659 for (
int dx = 0; dx < c_dofs1D; ++dx)
1661 for (
int dy = 0; dy < c_dofs1D; ++dy)
1663 for (
int j=0; j<3; ++j)
1665 w1[j][dx][dy][ez] = 0.0;
1666 for (
int dz = 0; dz < c_dofs1D; ++dz)
1668 w1[j][dx][dy][ez] += Bc(ez, dz) * x(dx, dy, dz, j, e);
1676 for (
int ez = 0; ez < c_dofs1D; ++ez)
1678 for (
int ey = 0; ey < o_dofs1D; ++ey)
1680 for (
int dx = 0; dx < c_dofs1D; ++dx)
1682 for (
int j=0; j<3; ++j)
1684 w2[j][dx][ey][ez] = 0.0;
1685 for (
int dy = 0; dy < c_dofs1D; ++dy)
1687 w2[j][dx][ey][ez] += Bo(ey, dy) * w1[j][dx][dy][ez];
1695 for (
int ez = 0; ez < c_dofs1D; ++ez)
1697 for (
int ey = 0; ey < o_dofs1D; ++ey)
1699 for (
int ex = 0; ex < c_dofs1D; ++ex)
1701 for (
int j=0; j<3; ++j)
1704 for (
int dx = 0; dx < c_dofs1D; ++dx)
1706 s += Bc(ex, dx) * w2[j][dx][ey][ez];
1708 const int local_index = c_dofs1D*c_dofs1D*o_dofs1D +
1709 ez*c_dofs1D*o_dofs1D + ey*c_dofs1D + ex;
1710 y(local_index, e) += s * vk(j, local_index, e);
1719 for (
int ez = 0; ez < o_dofs1D; ++ez)
1721 for (
int dx = 0; dx < c_dofs1D; ++dx)
1723 for (
int dy = 0; dy < c_dofs1D; ++dy)
1725 for (
int j=0; j<3; ++j)
1727 w1[j][dx][dy][ez] = 0.0;
1728 for (
int dz = 0; dz < c_dofs1D; ++dz)
1730 w1[j][dx][dy][ez] += Bo(ez, dz) * x(dx, dy, dz, j, e);
1738 for (
int ez = 0; ez < o_dofs1D; ++ez)
1740 for (
int ey = 0; ey < c_dofs1D; ++ey)
1742 for (
int dx = 0; dx < c_dofs1D; ++dx)
1744 for (
int j=0; j<3; ++j)
1746 w2[j][dx][ey][ez] = 0.0;
1747 for (
int dy = 0; dy < c_dofs1D; ++dy)
1749 w2[j][dx][ey][ez] += Bc(ey, dy) * w1[j][dx][dy][ez];
1757 for (
int ez = 0; ez < o_dofs1D; ++ez)
1759 for (
int ey = 0; ey < c_dofs1D; ++ey)
1761 for (
int ex = 0; ex < c_dofs1D; ++ex)
1763 for (
int j=0; j<3; ++j)
1766 for (
int dx = 0; dx < c_dofs1D; ++dx)
1768 s += Bc(ex, dx) * w2[j][dx][ey][ez];
1770 const int local_index = 2*c_dofs1D*c_dofs1D*o_dofs1D +
1771 ez*c_dofs1D*c_dofs1D + ey*c_dofs1D + ex;
1772 y(local_index, e) += s * vk(j, local_index, e);
1780static void PAHcurlVecH1IdentityApplyTranspose3D(
const int c_dofs1D,
1783 const Array<real_t> &Bclosed,
1784 const Array<real_t> &Bopen,
1785 const Vector &pa_data,
1789 auto Bc =
Reshape(Bclosed.Read(), c_dofs1D, c_dofs1D);
1790 auto Bo =
Reshape(Bopen.Read(), o_dofs1D, c_dofs1D);
1792 auto x =
Reshape(x_.Read(), (3 * c_dofs1D * c_dofs1D * o_dofs1D), NE);
1793 auto y =
Reshape(y_.ReadWrite(), c_dofs1D, c_dofs1D, c_dofs1D, 3, NE);
1795 auto vk =
Reshape(pa_data.Read(), 3, (3 * c_dofs1D * c_dofs1D * o_dofs1D),
1799 o_dofs1D <= c_dofs1D,
"");
1803 constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
1805 real_t w1[3][MAX_D1D][MAX_D1D][MAX_D1D];
1806 real_t w2[3][MAX_D1D][MAX_D1D][MAX_D1D];
1811 for (
int ez = 0; ez < c_dofs1D; ++ez)
1813 for (
int ey = 0; ey < c_dofs1D; ++ey)
1815 for (
int j=0; j<3; ++j)
1817 for (
int dx = 0; dx < c_dofs1D; ++dx)
1819 w2[j][dx][ey][ez] = 0.0;
1821 for (
int ex = 0; ex < o_dofs1D; ++ex)
1823 const int local_index = ez*c_dofs1D*o_dofs1D + ey*o_dofs1D + ex;
1824 const real_t xv = x(local_index, e) * vk(j, local_index, e);
1825 for (
int dx = 0; dx < c_dofs1D; ++dx)
1827 w2[j][dx][ey][ez] += xv * Bo(ex, dx);
1835 for (
int ez = 0; ez < c_dofs1D; ++ez)
1837 for (
int dx = 0; dx < c_dofs1D; ++dx)
1839 for (
int dy = 0; dy < c_dofs1D; ++dy)
1841 for (
int j=0; j<3; ++j)
1843 w1[j][dx][dy][ez] = 0.0;
1844 for (
int ey = 0; ey < c_dofs1D; ++ey)
1846 w1[j][dx][dy][ez] += w2[j][dx][ey][ez] * Bc(ey, dy);
1854 for (
int dx = 0; dx < c_dofs1D; ++dx)
1856 for (
int dy = 0; dy < c_dofs1D; ++dy)
1858 for (
int dz = 0; dz < c_dofs1D; ++dz)
1860 for (
int j=0; j<3; ++j)
1863 for (
int ez = 0; ez < c_dofs1D; ++ez)
1865 s += w1[j][dx][dy][ez] * Bc(ez, dz);
1867 y(dx, dy, dz, j, e) += s;
1876 for (
int ez = 0; ez < c_dofs1D; ++ez)
1878 for (
int ey = 0; ey < o_dofs1D; ++ey)
1880 for (
int j=0; j<3; ++j)
1882 for (
int dx = 0; dx < c_dofs1D; ++dx)
1884 w2[j][dx][ey][ez] = 0.0;
1886 for (
int ex = 0; ex < c_dofs1D; ++ex)
1888 const int local_index = c_dofs1D*c_dofs1D*o_dofs1D +
1889 ez*c_dofs1D*o_dofs1D + ey*c_dofs1D + ex;
1890 const real_t xv = x(local_index, e) * vk(j, local_index, e);
1891 for (
int dx = 0; dx < c_dofs1D; ++dx)
1893 w2[j][dx][ey][ez] += xv * Bc(ex, dx);
1901 for (
int ez = 0; ez < c_dofs1D; ++ez)
1903 for (
int dx = 0; dx < c_dofs1D; ++dx)
1905 for (
int dy = 0; dy < c_dofs1D; ++dy)
1907 for (
int j=0; j<3; ++j)
1909 w1[j][dx][dy][ez] = 0.0;
1910 for (
int ey = 0; ey < o_dofs1D; ++ey)
1912 w1[j][dx][dy][ez] += w2[j][dx][ey][ez] * Bo(ey, dy);
1920 for (
int dx = 0; dx < c_dofs1D; ++dx)
1922 for (
int dy = 0; dy < c_dofs1D; ++dy)
1924 for (
int dz = 0; dz < c_dofs1D; ++dz)
1926 for (
int j=0; j<3; ++j)
1929 for (
int ez = 0; ez < c_dofs1D; ++ez)
1931 s += w1[j][dx][dy][ez] * Bc(ez, dz);
1933 y(dx, dy, dz, j, e) += s;
1942 for (
int ez = 0; ez < o_dofs1D; ++ez)
1944 for (
int ey = 0; ey < c_dofs1D; ++ey)
1946 for (
int j=0; j<3; ++j)
1948 for (
int dx = 0; dx < c_dofs1D; ++dx)
1950 w2[j][dx][ey][ez] = 0.0;
1952 for (
int ex = 0; ex < c_dofs1D; ++ex)
1954 const int local_index = 2*c_dofs1D*c_dofs1D*o_dofs1D +
1955 ez*c_dofs1D*c_dofs1D + ey*c_dofs1D + ex;
1956 const real_t xv = x(local_index, e) * vk(j, local_index, e);
1957 for (
int dx = 0; dx < c_dofs1D; ++dx)
1959 w2[j][dx][ey][ez] += xv * Bc(ex, dx);
1967 for (
int ez = 0; ez < o_dofs1D; ++ez)
1969 for (
int dx = 0; dx < c_dofs1D; ++dx)
1971 for (
int dy = 0; dy < c_dofs1D; ++dy)
1973 for (
int j=0; j<3; ++j)
1975 w1[j][dx][dy][ez] = 0.0;
1976 for (
int ey = 0; ey < c_dofs1D; ++ey)
1978 w1[j][dx][dy][ez] += w2[j][dx][ey][ez] * Bc(ey, dy);
1986 for (
int dx = 0; dx < c_dofs1D; ++dx)
1988 for (
int dy = 0; dy < c_dofs1D; ++dy)
1990 for (
int dz = 0; dz < c_dofs1D; ++dz)
1992 for (
int j=0; j<3; ++j)
1995 for (
int ez = 0; ez < o_dofs1D; ++ez)
1997 s += w1[j][dx][dy][ez] * Bo(ez, dz);
1999 y(dx, dy, dz, j, e) += s;
2017 MFEM_VERIFY(trial_el != NULL,
"Only NodalTensorFiniteElement is supported!");
2021 MFEM_VERIFY(test_el != NULL,
"Only VectorTensorFiniteElement is supported!");
2023 const int dims = trial_el->
GetDim();
2024 MFEM_VERIFY(dims == 2 || dims == 3,
"");
2027 MFEM_VERIFY(dim == 2 || dim == 3,
"");
2031 MFEM_VERIFY(
vdim == 1,
"vdim != 1 with PA is not supported yet!");
2033 ne = trial_fes.
GetNE();
2035 const int order = trial_el->
GetOrder();
2048 o_dofs1D = maps_O_C->
nqpt;
2049 c_dofs1D = maps_C_C->
nqpt;
2050 MFEM_VERIFY(maps_O_C->
ndof == c_dofs1D &&
2051 maps_C_C->
ndof == c_dofs1D,
"Discrepancy in the number of DOFs");
2053 const int ndof_test = (dim == 3) ? 3 * c_dofs1D * c_dofs1D * o_dofs1D
2054 : 2 * c_dofs1D * o_dofs1D;
2059 auto op =
Reshape(pa_data.HostWrite(), dim, ndof_test, ne);
2069 const real_t tk[9] = { 1.,0.,0., 0.,1.,0., 0.,0.,1. };
2071 for (
int c=0; c<3; ++c)
2073 for (
int i=0; i<ndof_test/3; ++i)
2075 const int d = (c*ndof_test/3) + i;
2078 const int dof2tk = c;
2079 const int id = (dofmap[d] >= 0) ? dofmap[d] : -1 - dofmap[d];
2081 for (
int e=0; e<ne; ++e)
2085 tr->SetIntPoint(&Nodes.
IntPoint(
id));
2086 tr->Jacobian().Mult(tk + dof2tk*dim, v);
2088 for (
int j=0; j<3; ++j)
2098 const real_t tk[4] = { 1.,0., 0.,1. };
2099 for (
int c=0; c<2; ++c)
2101 for (
int i=0; i<ndof_test/2; ++i)
2103 const int d = (c*ndof_test/2) + i;
2106 const int dof2tk = c;
2107 const int id = (dofmap[d] >= 0) ? dofmap[d] : -1 - dofmap[d];
2109 for (
int e=0; e<ne; ++e)
2113 tr->SetIntPoint(&Nodes.
IntPoint(
id));
2114 tr->Jacobian().Mult(tk + dof2tk*dim, v);
2116 for (
int j=0; j<2; ++j)
2130 PAHcurlVecH1IdentityApply3D(c_dofs1D, o_dofs1D, ne, maps_C_C->
B, maps_O_C->
B,
2135 PAHcurlVecH1IdentityApply2D(c_dofs1D, o_dofs1D, ne, maps_C_C->
B, maps_O_C->
B,
2148 PAHcurlVecH1IdentityApplyTranspose3D(c_dofs1D, o_dofs1D, ne, maps_C_C->
B,
2149 maps_O_C->
B, pa_data, x, y);
2153 PAHcurlVecH1IdentityApplyTranspose2D(c_dofs1D, o_dofs1D, ne, maps_C_C->
B,
2154 maps_O_C->
B, pa_data, x, y);
2167 ne = dom_fes.
GetNE();
2169 MFEM_VERIFY(ne == ran_fes.
GetNE(),
2170 "Different meshes for domain and range spaces");
2177 const bool hcurl_to_scalar =
2182 const bool scalar_to_hdiv =
2188 MFEM_VERIFY(hcurl_to_scalar || scalar_to_hdiv,
2189 "2D CurlInterpolator PA supports H(curl)->scalar and scalar->H(div) only.");
2191 int closed_basis_type = -1;
2192 int open_basis_type = -1;
2193 if (hcurl_to_scalar)
2197 MFEM_VERIFY(trial_fec != NULL,
"H(curl) domain must use ND_FECollection.");
2198 MFEM_VERIFY(range_fec != NULL,
"Scalar range must use L2_FECollection.");
2200 "2D H(curl)->scalar CurlInterpolator PA supports integral-map scalar range spaces only.");
2201 closed_basis_type = trial_fec->GetClosedBasisType();
2202 open_basis_type = trial_fec->GetOpenBasisType();
2203 MFEM_VERIFY(range_fec->GetBasisType() == open_basis_type,
2204 "Domain/range open basis types do not match.");
2211 MFEM_VERIFY(trial_fec != NULL,
"Scalar domain must use H1_FECollection.");
2212 MFEM_VERIFY(range_fec != NULL,
"H(div) range must use RT_FECollection.");
2213 closed_basis_type = trial_fec->GetBasisType();
2214 open_basis_type = range_fec->GetOpenBasisType();
2215 MFEM_VERIFY(range_fec->GetClosedBasisType() == closed_basis_type,
2216 "Domain/range closed basis types do not match.");
2220 const int order = hcurl_to_scalar
2223 c_dofs1D = order + 1;
2242 MFEM_VERIFY(maps_C_C->
ndof == c_dofs1D && maps_C_C->
nqpt == c_dofs1D,
"");
2243 MFEM_VERIFY(maps_O_C->
ndof == c_dofs1D && maps_O_C->
nqpt == o_dofs1D,
"");
2244 MFEM_VERIFY(maps_O_O->
ndof == o_dofs1D && maps_O_O->
nqpt == o_dofs1D,
"");
2248 closed_dofquad_fe.reset();
2249 open_dofquad_fe.reset();
2258 MFEM_VERIFY(dom_el != NULL,
"Only VectorTensorFiniteElement is supported!");
2259 MFEM_VERIFY(ran_el != NULL,
"Only VectorTensorFiniteElement is supported!");
2261 "Domain space must be H(curl)");
2263 "Range space must be H(div)");
2265 const int dims = dom_el->
GetDim();
2266 MFEM_VERIFY(dims == 3,
"");
2269 int ndof_c = ndof_o + 1;
2271 int nquad_c = nquad_o + 1;
2274 std::vector<real_t> qc(nquad_c);
2275 std::vector<real_t> qo(nquad_o);
2279 for (
int i = 0; i < nquad_c; ++i)
2284 int offset = ndof_c * ndof_o * ndof_o;
2285 for (
int i = 0; i < nquad_o; ++i)
2295 pa_data.SetSize(ndof_c * nquad_o + ndof_c * nquad_c + ndof_o * nquad_o);
2296 auto ptr = pa_data.HostWrite();
2302 for (
int j = 0; j < nquad_o; ++j)
2304 cbasis1d.Eval(qo[j],
b, g);
2305 for (
int i = 0; i < ndof_c; ++i)
2307 ptr[j + i * nquad_o] = g[i];
2310 ptr += nquad_o * ndof_c;
2312 for (
int j = 0; j < nquad_c; ++j)
2314 cbasis1d.Eval(qc[j],
b);
2315 for (
int i = 0; i < ndof_c; ++i)
2317 ptr[j + i * nquad_c] =
b[i];
2320 ptr += ndof_c * nquad_c;
2323 for (
int j = 0; j < nquad_o; ++j)
2325 obasis1d.Eval(qo[j],
b);
2326 for (
int i = 0; i < ndof_o; ++i)
2328 ptr[j + i * nquad_o] =
b[i];
2333CurlInterpolator::Kernels::Kernels()
2348 MFEM_VERIFY(maps_C_C !=
nullptr && maps_O_C !=
nullptr,
2349 "2D CurlInterpolator PA data is not assembled.");
2350 if (pa_mode_2d == 1)
2352 MFEM_VERIFY(maps_O_O !=
nullptr,
2353 "2D CurlInterpolator scalar curl map is not assembled.");
2354 PAHcurlApplyCurl2D(c_dofs1D, o_dofs1D, ne, maps_O_O->
B, maps_O_C->
G,
2357 else if (pa_mode_2d == 2)
2359 PAHdivApplyCurl2D(c_dofs1D, o_dofs1D, ne, maps_C_C->
B, maps_O_C->
G,
2364 MFEM_ABORT(
"Unsupported 2D CurlInterpolator mode.");
2369 ApplyPAKernels::Run(dim, ndof_o, nquad_o, ne, ndof_o, nquad_o, pa_data, x, y);
2376 MFEM_VERIFY(maps_C_C !=
nullptr && maps_O_C !=
nullptr,
2377 "2D CurlInterpolator PA data is not assembled.");
2378 if (pa_mode_2d == 1)
2380 MFEM_VERIFY(maps_O_O !=
nullptr,
2381 "2D CurlInterpolator scalar curl map is not assembled.");
2382 PAHcurlApplyCurlTranspose2D(c_dofs1D, o_dofs1D, ne, maps_O_O->
B,
2385 else if (pa_mode_2d == 2)
2387 PAHdivApplyCurlTranspose2D(c_dofs1D, o_dofs1D, ne, maps_C_C->
B,
2392 MFEM_ABORT(
"Unsupported 2D CurlInterpolator mode.");
2397 ApplyTPAKernels::Run(dim, ndof_o, nquad_o, ne, ndof_o, nquad_o, pa_data, x, y);
2403CurlInterpolator::ApplyPAKernels::Fallback(
int DIM,
int,
int)
2407 return internal::CurlInterpolatorApply3DSmem<0, 0>;
2409 MFEM_ABORT(
"Bad dimension!");
2413CurlInterpolator::ApplyTPAKernels::Fallback(
int DIM,
int,
int)
2417 return internal::CurlInterpolatorTApply3DSmem<0, 0>;
2419 MFEM_ABORT(
"Bad dimension!");
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
@ GaussLobatto
Closed type.
void AddMultTransposePA(const Vector &x, Vector &y) const override
Method for partially assembled transposed action.
void AssemblePA(const FiniteElementSpace &dom_fes, const FiniteElementSpace &ran_fes) override
void AddMultPA(const Vector &x, Vector &y) const override
Method for partially assembled action.
static void AddSpecialization()
void(*)(const int ne, const int ndof_o, const int nquad_o, const Vector &pa, const Vector &x, Vector &y) ApplyKernelType
static MemoryType GetMemoryType()
(DEPRECATED) Equivalent to GetDeviceMemoryType().
Array< real_t > G
Gradients/divergences/curls of basis functions evaluated at quadrature points.
@ TENSOR
Tensor product representation using 1D matrices/tensors with dimensions using 1D number of quadrature...
Array< real_t > B
Basis functions evaluated at quadrature points.
int ndof
Number of degrees of freedom = number of basis functions. When mode is TENSOR, this is the 1D number.
int nqpt
Number of quadrature points. When mode is TENSOR, this is the 1D number.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
int GetNE() const
Returns number of elements in the mesh.
const FiniteElementCollection * FEColl() const
Mesh * GetMesh() const
Returns the mesh.
const FiniteElement * GetTypicalFE() const
Return GetFE(0) if the local mesh is not empty; otherwise return a typical FE based on the Geometry t...
Abstract class for all finite elements.
virtual const DofToQuad & GetDofToQuad(const IntegrationRule &ir, DofToQuad::Mode mode) const
Return a DofToQuad structure corresponding to the given IntegrationRule using the given DofToQuad::Mo...
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
int GetDerivType() const
Returns the FiniteElement::DerivType of the element describing the spatial derivative method implemen...
int GetDim() const
Returns the reference space dimension for the finite element.
int GetMapType() const
Returns the FiniteElement::MapType of the element describing how reference functions are mapped to ph...
int GetRangeType() const
Returns the FiniteElement::RangeType of the element, one of {SCALAR, VECTOR}.
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
@ DIV
Implements CalcDivShape methods.
@ CURL
Implements CalcCurlShape methods.
void AddMultPA(const Vector &x, Vector &y) const override
Method for partially assembled action.
void AddMultTransposePA(const Vector &x, Vector &y) const override
Method for partially assembled transposed action.
void AssemblePA(const FiniteElementSpace &trial_fes, const FiniteElementSpace &test_fes) override
Setup method for PA data.
Arbitrary order H1-conforming (continuous) finite elements.
Arbitrary order H1 elements in 1D.
void AddMultTransposePA(const Vector &x, Vector &y) const override
Method for partially assembled transposed action.
void AddMultPA(const Vector &x, Vector &y) const override
Method for partially assembled action.
void AssemblePA(const FiniteElementSpace &trial_fes, const FiniteElementSpace &test_fes) override
Class for an integration rule - an Array of IntegrationPoint.
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Arbitrary order "L2-conforming" discontinuous finite elements.
Arbitrary order L2 elements in 1D on a segment.
int Dimension() const
Dimension of the reference space used within the elements.
void GetElementTransformation(int i, IsoparametricTransformation *ElTr) const
Builds the transformation defining the i-th element in ElTr. ElTr must be allocated in advance and wi...
Arbitrary order H(curl)-conforming Nedelec finite elements.
A Class that defines 1-D numerical quadrature rules on [0,1].
static void GaussLegendre(const int np, IntegrationRule *ir)
static void GaussLobatto(const int np, IntegrationRule *ir)
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
const Array< int > & GetDofMap() const
Get an Array<int> that maps lexicographically ordered indices to the indices of the respective nodes/...
const Poly_1D::Basis & GetBasis1D() const
const Poly_1D::Basis & GetOpenBasis1D() const
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
virtual real_t * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
void SetSize(int s)
Resize the vector to size s.
void mfem_error(const char *msg)
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
MFEM_HOST_DEVICE int UnsignIndex(int i)
void forall(int N, lambda &&body)
static const DeviceDofQuadLimits & Get()
Return a const reference to the DeviceDofQuadLimits singleton.