12 #include "../general/forall.hpp"
15 #include "libceed/mass.hpp"
34 const int NQ = Q1D*Q1D;
43 for (
int q = 0; q < NQ; ++q)
45 const double J11 = J(q,0,0,e);
46 const double J21 = J(q,1,0,e);
47 const double J12 = J(q,0,1,e);
48 const double J22 = J(q,1,1,e);
49 const double c_detJ = W[q] * coeff(q, e) / ((J11*J22)-(J21*J12));
51 y(q,0,e) = c_detJ * (J11*J11 + J21*J21);
52 y(q,1,e) = c_detJ * (J11*J12 + J21*J22);
53 y(q,2,e) = c_detJ * (J12*J12 + J22*J22);
66 const int NQ = Q1D*Q1D*Q1D;
74 for (
int q = 0; q < NQ; ++q)
76 const double J11 = J(q,0,0,e);
77 const double J21 = J(q,1,0,e);
78 const double J31 = J(q,2,0,e);
79 const double J12 = J(q,0,1,e);
80 const double J22 = J(q,1,1,e);
81 const double J32 = J(q,2,1,e);
82 const double J13 = J(q,0,2,e);
83 const double J23 = J(q,1,2,e);
84 const double J33 = J(q,2,2,e);
85 const double detJ = J11 * (J22 * J33 - J32 * J23) -
86 J21 * (J12 * J33 - J32 * J13) +
87 J31 * (J12 * J23 - J22 * J13);
88 const double c_detJ = W[q] * coeff(q, e) / detJ;
90 y(q,0,e) = c_detJ * (J11*J11 + J21*J21 + J31*J31);
91 y(q,1,e) = c_detJ * (J12*J11 + J22*J21 + J32*J31);
92 y(q,2,e) = c_detJ * (J13*J11 + J23*J21 + J33*J31);
93 y(q,3,e) = c_detJ * (J12*J12 + J22*J22 + J32*J32);
94 y(q,4,e) = c_detJ * (J13*J12 + J23*J22 + J33*J32);
95 y(q,5,e) = c_detJ * (J13*J13 + J23*J23 + J33*J33);
111 constexpr
static int VDIM = 2;
127 for (
int qy = 0; qy < Q1D; ++qy)
129 for (
int qx = 0; qx < Q1D; ++qx)
131 for (
int c = 0; c < VDIM; ++c)
133 mass[qy][qx][c] = 0.0;
140 for (
int c = 0; c < VDIM; ++c)
142 const int D1Dx = (c == 1) ? D1D - 1 : D1D;
143 const int D1Dy = (c == 0) ? D1D - 1 : D1D;
145 for (
int dy = 0; dy < D1Dy; ++dy)
148 for (
int qx = 0; qx < Q1D; ++qx)
153 for (
int dx = 0; dx < D1Dx; ++dx)
155 const double t = x(dx + (dy * D1Dx) + osc, e);
156 for (
int qx = 0; qx < Q1D; ++qx)
158 massX[qx] += t * ((c == 0) ? Bc(qx,dx) : Bo(qx,dx));
162 for (
int qy = 0; qy < Q1D; ++qy)
164 const double wy = (c == 1) ? Bc(qy,dy) : Bo(qy,dy);
165 for (
int qx = 0; qx < Q1D; ++qx)
167 mass[qy][qx][c] += massX[qx] * wy;
176 for (
int qy = 0; qy < Q1D; ++qy)
178 for (
int qx = 0; qx < Q1D; ++qx)
180 const double O11 = op(qx,qy,0,e);
181 const double O12 = op(qx,qy,1,e);
182 const double O22 = op(qx,qy,2,e);
183 const double massX = mass[qy][qx][0];
184 const double massY = mass[qy][qx][1];
185 mass[qy][qx][0] = (O11*massX)+(O12*massY);
186 mass[qy][qx][1] = (O12*massX)+(O22*massY);
190 for (
int qy = 0; qy < Q1D; ++qy)
194 for (
int c = 0; c < VDIM; ++c)
196 const int D1Dx = (c == 1) ? D1D - 1 : D1D;
197 const int D1Dy = (c == 0) ? D1D - 1 : D1D;
200 for (
int dx = 0; dx < D1Dx; ++dx)
204 for (
int qx = 0; qx < Q1D; ++qx)
206 for (
int dx = 0; dx < D1Dx; ++dx)
208 massX[dx] += mass[qy][qx][c] * ((c == 0) ? Bct(dx,qx) :
213 for (
int dy = 0; dy < D1Dy; ++dy)
215 const double wy = (c == 1) ? Bct(dy,qy) : Bot(dy,qy);
217 for (
int dx = 0; dx < D1Dx; ++dx)
219 y(dx + (dy * D1Dx) + osc, e) += massX[dx] * wy;
237 constexpr
static int VDIM = 2;
249 for (
int c = 0; c < VDIM; ++c)
251 const int D1Dx = (c == 1) ? D1D - 1 : D1D;
252 const int D1Dy = (c == 0) ? D1D - 1 : D1D;
254 for (
int dy = 0; dy < D1Dy; ++dy)
257 for (
int qx = 0; qx < Q1D; ++qx)
260 for (
int qy = 0; qy < Q1D; ++qy)
262 const double wy = (c == 1) ? Bc(qy,dy) : Bo(qy,dy);
263 mass[qx] += wy*wy*((c == 0) ? op(qx,qy,0,e) : op(qx,qy,2,e));
267 for (
int dx = 0; dx < D1Dx; ++dx)
270 for (
int qx = 0; qx < Q1D; ++qx)
272 const double wx = (c == 0) ? Bc(qx,dx) : Bo(qx,dx);
273 val += mass[qx] * wx * wx;
275 diag(dx + (dy * D1Dx) + osc, e) += val;
292 MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D >
HDIV_MAX_D1D");
293 MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D >
HDIV_MAX_Q1D");
294 constexpr static int VDIM = 3;
296 auto Bo = Reshape(_Bo.Read(), Q1D, D1D-1);
297 auto Bc = Reshape(_Bc.Read(), Q1D, D1D);
298 auto op = Reshape(_op.Read(), Q1D, Q1D, Q1D, 6, NE);
299 auto diag = Reshape(_diag.ReadWrite(), 3*(D1D-1)*(D1D-1)*D1D, NE);
305 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
307 const int D1Dz = (c == 2) ? D1D : D1D - 1;
308 const int D1Dy = (c == 1) ? D1D : D1D - 1;
309 const int D1Dx = (c == 0) ? D1D : D1D - 1;
311 const int opc = (c == 0) ? 0 : ((c == 1) ? 3 : 5);
313 double mass[HDIV_MAX_Q1D];
315 for (int dz = 0; dz < D1Dz; ++dz)
317 for (int dy = 0; dy < D1Dy; ++dy)
319 for (int qx = 0; qx < Q1D; ++qx)
322 for (int qy = 0; qy < Q1D; ++qy)
324 const double wy = (c == 1) ? Bc(qy,dy) : Bo(qy,dy);
325 for (int qz = 0; qz < Q1D; ++qz)
327 const double wz = (c == 2) ? Bc(qz,dz) : Bo(qz,dz);
328 mass[qx] += wy * wy * wz * wz * op(qx,qy,qz,opc,e);
333 for (int dx = 0; dx < D1Dx; ++dx)
336 for (int qx = 0; qx < Q1D; ++qx)
338 const double wx = (c == 0) ? Bc(qx,dx) : Bo(qx,dx);
339 val += mass[qx] * wx * wx;
341 diag(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e) += val;
346 osc += D1Dx * D1Dy * D1Dz;
348 }); // end of element loop
351 void PAHdivMassApply3D(const int D1D,
354 const Array<double> &_Bo,
355 const Array<double> &_Bc,
356 const Array<double> &_Bot,
357 const Array<double> &_Bct,
362 MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D >
HDIV_MAX_D1D");
363 MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D >
HDIV_MAX_Q1D");
364 constexpr static int VDIM = 3;
366 auto Bo = Reshape(_Bo.Read(), Q1D, D1D-1);
367 auto Bc = Reshape(_Bc.Read(), Q1D, D1D);
368 auto Bot = Reshape(_Bot.Read(), D1D-1, Q1D);
369 auto Bct = Reshape(_Bct.Read(), D1D, Q1D);
370 auto op = Reshape(_op.Read(), Q1D, Q1D, Q1D, 6, NE);
371 auto x = Reshape(_x.Read(), 3*(D1D-1)*(D1D-1)*D1D, NE);
372 auto y = Reshape(_y.ReadWrite(), 3*(D1D-1)*(D1D-1)*D1D, NE);
376 double mass[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D][VDIM];
378 for (int qz = 0; qz < Q1D; ++qz)
380 for (int qy = 0; qy < Q1D; ++qy)
382 for (int qx = 0; qx < Q1D; ++qx)
384 for (int c = 0; c < VDIM; ++c)
386 mass[qz][qy][qx][c] = 0.0;
394 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
396 const int D1Dz = (c == 2) ? D1D : D1D - 1;
397 const int D1Dy = (c == 1) ? D1D : D1D - 1;
398 const int D1Dx = (c == 0) ? D1D : D1D - 1;
400 for (int dz = 0; dz < D1Dz; ++dz)
402 double massXY[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
403 for (int qy = 0; qy < Q1D; ++qy)
405 for (int qx = 0; qx < Q1D; ++qx)
407 massXY[qy][qx] = 0.0;
411 for (int dy = 0; dy < D1Dy; ++dy)
413 double massX[HDIV_MAX_Q1D];
414 for (int qx = 0; qx < Q1D; ++qx)
419 for (int dx = 0; dx < D1Dx; ++dx)
421 const double t = x(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
422 for (int qx = 0; qx < Q1D; ++qx)
424 massX[qx] += t * ((c == 0) ? Bc(qx,dx) : Bo(qx,dx));
428 for (int qy = 0; qy < Q1D; ++qy)
430 const double wy = (c == 1) ? Bc(qy,dy) : Bo(qy,dy);
431 for (int qx = 0; qx < Q1D; ++qx)
433 const double wx = massX[qx];
434 massXY[qy][qx] += wx * wy;
439 for (int qz = 0; qz < Q1D; ++qz)
441 const double wz = (c == 2) ? Bc(qz,dz) : Bo(qz,dz);
442 for (int qy = 0; qy < Q1D; ++qy)
444 for (int qx = 0; qx < Q1D; ++qx)
446 mass[qz][qy][qx][c] += massXY[qy][qx] * wz;
452 osc += D1Dx * D1Dy * D1Dz;
453 } // loop (c) over components
456 for (int qz = 0; qz < Q1D; ++qz)
458 for (int qy = 0; qy < Q1D; ++qy)
460 for (int qx = 0; qx < Q1D; ++qx)
462 const double O11 = op(qx,qy,qz,0,e);
463 const double O12 = op(qx,qy,qz,1,e);
464 const double O13 = op(qx,qy,qz,2,e);
465 const double O22 = op(qx,qy,qz,3,e);
466 const double O23 = op(qx,qy,qz,4,e);
467 const double O33 = op(qx,qy,qz,5,e);
468 const double massX = mass[qz][qy][qx][0];
469 const double massY = mass[qz][qy][qx][1];
470 const double massZ = mass[qz][qy][qx][2];
471 mass[qz][qy][qx][0] = (O11*massX)+(O12*massY)+(O13*massZ);
472 mass[qz][qy][qx][1] = (O12*massX)+(O22*massY)+(O23*massZ);
473 mass[qz][qy][qx][2] = (O13*massX)+(O23*massY)+(O33*massZ);
478 for (int qz = 0; qz < Q1D; ++qz)
480 double massXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
484 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
486 const int D1Dz = (c == 2) ? D1D : D1D - 1;
487 const int D1Dy = (c == 1) ? D1D : D1D - 1;
488 const int D1Dx = (c == 0) ? D1D : D1D - 1;
490 for (int dy = 0; dy < D1Dy; ++dy)
492 for (int dx = 0; dx < D1Dx; ++dx)
497 for (int qy = 0; qy < Q1D; ++qy)
499 double massX[HDIV_MAX_D1D];
500 for (int dx = 0; dx < D1Dx; ++dx)
504 for (int qx = 0; qx < Q1D; ++qx)
506 for (int dx = 0; dx < D1Dx; ++dx)
508 massX[dx] += mass[qz][qy][qx][c] *
509 ((c == 0) ? Bct(dx,qx) : Bot(dx,qx));
512 for (int dy = 0; dy < D1Dy; ++dy)
514 const double wy = (c == 1) ? Bct(dy,qy) : Bot(dy,qy);
515 for (int dx = 0; dx < D1Dx; ++dx)
517 massXY[dy][dx] += massX[dx] * wy;
522 for (int dz = 0; dz < D1Dz; ++dz)
524 const double wz = (c == 2) ? Bct(dz,qz) : Bot(dz,qz);
525 for (int dy = 0; dy < D1Dy; ++dy)
527 for (int dx = 0; dx < D1Dx; ++dx)
529 y(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e) +=
535 osc += D1Dx * D1Dy * D1Dz;
538 }); // end of element loop
541 // PA H(div) div-div assemble 2D kernel
542 // NOTE: this is identical to PACurlCurlSetup3D
543 static void PADivDivSetup2D(const int Q1D,
545 const Array<double> &w,
550 const int NQ = Q1D*Q1D;
552 auto J = Reshape(j.Read(), NQ, 2, 2, NE);
553 auto coeff = Reshape(_coeff.Read(), NQ, NE);
554 auto y = Reshape(op.Write(), NQ, NE);
557 for (int q = 0; q < NQ; ++q)
559 const double J11 = J(q,0,0,e);
560 const double J21 = J(q,1,0,e);
561 const double J12 = J(q,0,1,e);
562 const double J22 = J(q,1,1,e);
563 const double detJ = (J11*J22)-(J21*J12);
564 y(q,e) = W[q] * coeff(q,e) / detJ;
569 static void PADivDivSetup3D(const int Q1D,
571 const Array<double> &w,
576 const int NQ = Q1D*Q1D*Q1D;
578 auto J = Reshape(j.Read(), NQ, 3, 3, NE);
579 auto coeff = Reshape(_coeff.Read(), NQ, NE);
580 auto y = Reshape(op.Write(), NQ, NE);
584 for (int q = 0; q < NQ; ++q)
586 const double J11 = J(q,0,0,e);
587 const double J21 = J(q,1,0,e);
588 const double J31 = J(q,2,0,e);
589 const double J12 = J(q,0,1,e);
590 const double J22 = J(q,1,1,e);
591 const double J32 = J(q,2,1,e);
592 const double J13 = J(q,0,2,e);
593 const double J23 = J(q,1,2,e);
594 const double J33 = J(q,2,2,e);
595 const double detJ = J11 * (J22 * J33 - J32 * J23) -
596 /* */ J21 * (J12 * J33 - J32 * J13) +
597 /* */ J31 * (J12 * J23 - J22 * J13);
598 y(q,e) = W[q] * coeff(q, e) / detJ;
603 static void PADivDivApply2D(const int D1D,
606 const Array<double> &_Bo,
607 const Array<double> &_Gc,
608 const Array<double> &_Bot,
609 const Array<double> &_Gct,
614 constexpr static int VDIM = 2;
615 constexpr static int MAX_D1D = HDIV_MAX_D1D;
616 constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
618 auto Bo = Reshape(_Bo.Read(), Q1D, D1D-1);
619 auto Bot = Reshape(_Bot.Read(), D1D-1, Q1D);
620 auto Gc = Reshape(_Gc.Read(), Q1D, D1D);
621 auto Gct = Reshape(_Gct.Read(), D1D, Q1D);
622 auto op = Reshape(_op.Read(), Q1D, Q1D, NE);
623 auto x = Reshape(_x.Read(), 2*(D1D-1)*D1D, NE);
624 auto y = Reshape(_y.ReadWrite(), 2*(D1D-1)*D1D, NE);
628 double div[MAX_Q1D][MAX_Q1D];
630 // div[qy][qx] will be computed as du_x/dx + du_y/dy
632 for (int qy = 0; qy < Q1D; ++qy)
634 for (int qx = 0; qx < Q1D; ++qx)
642 for (int c = 0; c < VDIM; ++c) // loop over x, y components
644 const int D1Dx = (c == 1) ? D1D - 1 : D1D;
645 const int D1Dy = (c == 0) ? D1D - 1 : D1D;
647 for (int dy = 0; dy < D1Dy; ++dy)
649 double gradX[MAX_Q1D];
650 for (int qx = 0; qx < Q1D; ++qx)
655 for (int dx = 0; dx < D1Dx; ++dx)
657 const double t = x(dx + (dy * D1Dx) + osc, e);
658 for (int qx = 0; qx < Q1D; ++qx)
660 gradX[qx] += t * ((c == 0) ? Gc(qx,dx) : Bo(qx,dx));
664 for (int qy = 0; qy < Q1D; ++qy)
666 const double wy = (c == 0) ? Bo(qy,dy) : Gc(qy,dy);
667 for (int qx = 0; qx < Q1D; ++qx)
669 div[qy][qx] += gradX[qx] * wy;
675 } // loop (c) over components
678 for (int qy = 0; qy < Q1D; ++qy)
680 for (int qx = 0; qx < Q1D; ++qx)
682 div[qy][qx] *= op(qx,qy,e);
686 for (int qy = 0; qy < Q1D; ++qy)
690 for (int c = 0; c < VDIM; ++c) // loop over x, y components
692 const int D1Dx = (c == 1) ? D1D - 1 : D1D;
693 const int D1Dy = (c == 0) ? D1D - 1 : D1D;
695 double gradX[MAX_D1D];
696 for (int dx = 0; dx < D1Dx; ++dx)
700 for (int qx = 0; qx < Q1D; ++qx)
702 for (int dx = 0; dx < D1Dx; ++dx)
704 gradX[dx] += div[qy][qx] * (c == 0 ? Gct(dx,qx) : Bot(dx,qx));
707 for (int dy = 0; dy < D1Dy; ++dy)
709 const double wy = (c == 0) ? Bot(dy,qy) : Gct(dy,qy);
710 for (int dx = 0; dx < D1Dx; ++dx)
712 y(dx + (dy * D1Dx) + osc, e) += gradX[dx] * wy;
719 }); // end of element loop
722 static void PADivDivApply3D(const int D1D,
725 const Array<double> &_Bo,
726 const Array<double> &_Gc,
727 const Array<double> &_Bot,
728 const Array<double> &_Gct,
733 MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D >
HDIV_MAX_D1D");
734 MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D >
HDIV_MAX_Q1D");
735 constexpr static int VDIM = 3;
737 auto Bo = Reshape(_Bo.Read(), Q1D, D1D-1);
738 auto Gc = Reshape(_Gc.Read(), Q1D, D1D);
739 auto Bot = Reshape(_Bot.Read(), D1D-1, Q1D);
740 auto Gct = Reshape(_Gct.Read(), D1D, Q1D);
741 auto op = Reshape(_op.Read(), Q1D, Q1D, Q1D, NE);
742 auto x = Reshape(_x.Read(), 3*(D1D-1)*(D1D-1)*D1D, NE);
743 auto y = Reshape(_y.ReadWrite(), 3*(D1D-1)*(D1D-1)*D1D, NE);
747 double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D];
749 for (int qz = 0; qz < Q1D; ++qz)
751 for (int qy = 0; qy < Q1D; ++qy)
753 for (int qx = 0; qx < Q1D; ++qx)
755 div[qz][qy][qx] = 0.0;
762 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
764 const int D1Dz = (c == 2) ? D1D : D1D - 1;
765 const int D1Dy = (c == 1) ? D1D : D1D - 1;
766 const int D1Dx = (c == 0) ? D1D : D1D - 1;
768 for (int dz = 0; dz < D1Dz; ++dz)
770 double aXY[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
771 for (int qy = 0; qy < Q1D; ++qy)
773 for (int qx = 0; qx < Q1D; ++qx)
779 for (int dy = 0; dy < D1Dy; ++dy)
781 double aX[HDIV_MAX_Q1D];
782 for (int qx = 0; qx < Q1D; ++qx)
787 for (int dx = 0; dx < D1Dx; ++dx)
789 const double t = x(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
790 for (int qx = 0; qx < Q1D; ++qx)
792 aX[qx] += t * ((c == 0) ? Gc(qx,dx) : Bo(qx,dx));
796 for (int qy = 0; qy < Q1D; ++qy)
798 const double wy = (c == 1) ? Gc(qy,dy) : Bo(qy,dy);
799 for (int qx = 0; qx < Q1D; ++qx)
801 const double wx = aX[qx];
802 aXY[qy][qx] += wx * wy;
807 for (int qz = 0; qz < Q1D; ++qz)
809 const double wz = (c == 2) ? Gc(qz,dz) : Bo(qz,dz);
810 for (int qy = 0; qy < Q1D; ++qy)
812 for (int qx = 0; qx < Q1D; ++qx)
814 div[qz][qy][qx] += aXY[qy][qx] * wz;
820 osc += D1Dx * D1Dy * D1Dz;
821 } // loop (c) over components
824 for (int qz = 0; qz < Q1D; ++qz)
826 for (int qy = 0; qy < Q1D; ++qy)
828 for (int qx = 0; qx < Q1D; ++qx)
830 div[qz][qy][qx] *= op(qx,qy,qz,e);
835 for (int qz = 0; qz < Q1D; ++qz)
837 double aXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
841 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
843 const int D1Dz = (c == 2) ? D1D : D1D - 1;
844 const int D1Dy = (c == 1) ? D1D : D1D - 1;
845 const int D1Dx = (c == 0) ? D1D : D1D - 1;
847 for (int dy = 0; dy < D1Dy; ++dy)
849 for (int dx = 0; dx < D1Dx; ++dx)
854 for (int qy = 0; qy < Q1D; ++qy)
856 double aX[HDIV_MAX_D1D];
857 for (int dx = 0; dx < D1Dx; ++dx)
861 for (int qx = 0; qx < Q1D; ++qx)
863 for (int dx = 0; dx < D1Dx; ++dx)
865 aX[dx] += div[qz][qy][qx] *
866 (c == 0 ? Gct(dx,qx) : Bot(dx,qx));
869 for (int dy = 0; dy < D1Dy; ++dy)
871 const double wy = (c == 1) ? Gct(dy,qy) : Bot(dy,qy);
872 for (int dx = 0; dx < D1Dx; ++dx)
874 aXY[dy][dx] += aX[dx] * wy;
879 for (int dz = 0; dz < D1Dz; ++dz)
881 const double wz = (c == 2) ? Gct(dz,qz) : Bot(dz,qz);
882 for (int dy = 0; dy < D1Dy; ++dy)
884 for (int dx = 0; dx < D1Dx; ++dx)
886 y(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e) +=
892 osc += D1Dx * D1Dy * D1Dz;
895 }); // end of element loop
898 void DivDivIntegrator::AssemblePA(const FiniteElementSpace &fes)
900 // Assumes tensor-product elements
901 Mesh *mesh = fes.GetMesh();
902 const FiniteElement *fel = fes.GetFE(0);
904 const VectorTensorFiniteElement *el =
905 dynamic_cast<const VectorTensorFiniteElement*>(fel);
908 const IntegrationRule *ir = IntRule ? IntRule : &MassIntegrator::GetRule
909 (*el, *el, *mesh->GetElementTransformation(0));
911 const int dims = el->GetDim();
912 MFEM_VERIFY(dims == 2 || dims == 3, "");
914 const int nq = ir->GetNPoints();
915 dim = mesh->Dimension();
916 MFEM_VERIFY(dim == 2 || dim == 3, "");
919 geom = mesh->GetGeometricFactors(*ir, GeometricFactors::JACOBIANS);
920 mapsC = &el->GetDofToQuad(*ir, DofToQuad::TENSOR);
921 mapsO = &el->GetDofToQuadOpen(*ir, DofToQuad::TENSOR);
922 dofs1D = mapsC->ndof;
923 quad1D = mapsC->nqpt;
925 MFEM_VERIFY(dofs1D == mapsO->ndof + 1 && quad1D == mapsO->nqpt, "");
927 pa_data.SetSize(nq * ne, Device::GetMemoryType());
929 Vector coeff(ne * nq);
933 for (int e=0; e<ne; ++e)
935 ElementTransformation *tr = mesh->GetElementTransformation(e);
936 for (int p=0; p<nq; ++p)
938 coeff[p + (e * nq)] = Q->Eval(*tr, ir->IntPoint(p));
943 if (el->GetDerivType() == mfem::FiniteElement::DIV && dim == 3)
945 PADivDivSetup3D(quad1D, ne, ir->GetWeights(), geom->J, coeff, pa_data);
947 else if (el->GetDerivType() == mfem::FiniteElement::DIV && dim == 2)
949 PADivDivSetup2D(quad1D, ne, ir->GetWeights(), geom->J, coeff, pa_data);
953 MFEM_ABORT("Unknown kernel.
");
957 void DivDivIntegrator::AddMultPA(const Vector &x, Vector &y) const
960 PADivDivApply3D(dofs1D, quad1D, ne, mapsO->B, mapsC->G,
961 mapsO->Bt, mapsC->Gt, pa_data, x, y);
963 PADivDivApply2D(dofs1D, quad1D, ne, mapsO->B, mapsC->G,
964 mapsO->Bt, mapsC->Gt, pa_data, x, y);
967 MFEM_ABORT("Unsupported dimension!
");
971 static void PADivDivAssembleDiagonal2D(const int D1D,
974 const Array<double> &_Bo,
975 const Array<double> &_Gc,
979 constexpr static int VDIM = 2;
980 constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
982 auto Bo = Reshape(_Bo.Read(), Q1D, D1D-1);
983 auto Gc = Reshape(_Gc.Read(), Q1D, D1D);
984 auto op = Reshape(_op.Read(), Q1D, Q1D, NE);
985 auto diag = Reshape(_diag.ReadWrite(), 2*(D1D-1)*D1D, NE);
991 for (int c = 0; c < VDIM; ++c) // loop over x, y components
993 const int D1Dx = (c == 1) ? D1D - 1 : D1D;
994 const int D1Dy = (c == 0) ? D1D - 1 : D1D;
998 for (int dy = 0; dy < D1Dy; ++dy)
1000 for (int qx = 0; qx < Q1D; ++qx)
1003 for (int qy = 0; qy < Q1D; ++qy)
1005 const double wy = (c == 0) ? Bo(qy,dy) : Gc(qy,dy);
1006 div[qx] += wy * wy * op(qx,qy,e);
1010 for (int dx = 0; dx < D1Dx; ++dx)
1013 for (int qx = 0; qx < Q1D; ++qx)
1015 const double wx = (c == 0) ? Gc(qx,dx) : Bo(qx,dx);
1016 val += div[qx] * wx * wx;
1018 diag(dx + (dy * D1Dx) + osc, e) += val;
1027 static void PADivDivAssembleDiagonal3D(const int D1D,
1030 const Array<double> &_Bo,
1031 const Array<double> &_Gc,
1035 MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D >
HDIV_MAX_D1D");
1036 MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D >
HDIV_MAX_Q1D");
1037 constexpr static int VDIM = 3;
1039 auto Bo = Reshape(_Bo.Read(), Q1D, D1D-1);
1040 auto Gc = Reshape(_Gc.Read(), Q1D, D1D);
1041 auto op = Reshape(_op.Read(), Q1D, Q1D, Q1D, NE);
1042 auto diag = Reshape(_diag.ReadWrite(), 3*(D1D-1)*(D1D-1)*D1D, NE);
1048 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
1050 const int D1Dz = (c == 2) ? D1D : D1D - 1;
1051 const int D1Dy = (c == 1) ? D1D : D1D - 1;
1052 const int D1Dx = (c == 0) ? D1D : D1D - 1;
1054 for (int dz = 0; dz < D1Dz; ++dz)
1056 for (int dy = 0; dy < D1Dy; ++dy)
1058 double a[HDIV_MAX_Q1D];
1060 for (int qx = 0; qx < Q1D; ++qx)
1063 for (int qy = 0; qy < Q1D; ++qy)
1065 const double wy = (c == 1) ? Gc(qy,dy) : Bo(qy,dy);
1067 for (int qz = 0; qz < Q1D; ++qz)
1069 const double wz = (c == 2) ? Gc(qz,dz) : Bo(qz,dz);
1070 a[qx] += wy * wy * wz * wz * op(qx,qy,qz,e);
1075 for (int dx = 0; dx < D1Dx; ++dx)
1078 for (int qx = 0; qx < Q1D; ++qx)
1080 const double wx = (c == 0) ? Gc(qx,dx) : Bo(qx,dx);
1081 val += a[qx] * wx * wx;
1083 diag(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e) += val;
1088 osc += D1Dx * D1Dy * D1Dz;
1090 }); // end of element loop
1093 void DivDivIntegrator::AssembleDiagonalPA(Vector& diag)
1097 PADivDivAssembleDiagonal3D(dofs1D, quad1D, ne,
1098 mapsO->B, mapsC->G, pa_data, diag);
1102 PADivDivAssembleDiagonal2D(dofs1D, quad1D, ne,
1103 mapsO->B, mapsC->G, pa_data, diag);
1107 // PA H(div)-L2 (div u, p) assemble 2D kernel
1108 static void PADivL2Setup2D(const int Q1D,
1110 const Array<double> &w,
1114 const int NQ = Q1D*Q1D;
1116 auto coeff = Reshape(_coeff.Read(), NQ, NE);
1117 auto y = Reshape(op.Write(), NQ, NE);
1120 for (int q = 0; q < NQ; ++q)
1122 y(q,e) = W[q] * coeff(q,e);
1127 static void PADivL2Setup3D(const int Q1D,
1129 const Array<double> &w,
1133 const int NQ = Q1D*Q1D*Q1D;
1135 auto coeff = Reshape(_coeff.Read(), NQ, NE);
1136 auto y = Reshape(op.Write(), NQ, NE);
1140 for (int q = 0; q < NQ; ++q)
1142 y(q,e) = W[q] * coeff(q, e);
1148 VectorFEDivergenceIntegrator::AssemblePA(const FiniteElementSpace &trial_fes,
1149 const FiniteElementSpace &test_fes)
1151 // Assumes tensor-product elements, with a vector test space and
1152 // scalar trial space.
1153 Mesh *mesh = trial_fes.GetMesh();
1154 const FiniteElement *trial_fel = trial_fes.GetFE(0);
1155 const FiniteElement *test_fel = test_fes.GetFE(0);
1157 const VectorTensorFiniteElement *trial_el =
1158 dynamic_cast<const VectorTensorFiniteElement*>(trial_fel);
1161 const NodalTensorFiniteElement *test_el =
1162 dynamic_cast<const NodalTensorFiniteElement*>(test_fel);
1165 const IntegrationRule *ir = IntRule ? IntRule : &MassIntegrator::GetRule(
1166 *trial_el, *trial_el,
1167 *mesh->GetElementTransformation(0));
1169 const int dims = trial_el->GetDim();
1170 MFEM_VERIFY(dims == 2 || dims == 3, "");
1172 const int nq = ir->GetNPoints();
1173 dim = mesh->Dimension();
1174 MFEM_VERIFY(dim == 2 || dim == 3, "");
1176 MFEM_VERIFY(trial_el->GetOrder() == test_el->GetOrder() + 1, "");
1178 ne = trial_fes.GetNE();
1179 mapsC = &trial_el->GetDofToQuad(*ir, DofToQuad::TENSOR);
1180 mapsO = &trial_el->GetDofToQuadOpen(*ir, DofToQuad::TENSOR);
1181 dofs1D = mapsC->ndof;
1182 quad1D = mapsC->nqpt;
1184 L2mapsO = &test_el->GetDofToQuad(*ir, DofToQuad::TENSOR);
1185 L2dofs1D = L2mapsO->ndof;
1187 MFEM_VERIFY(dofs1D == mapsO->ndof + 1 && quad1D == mapsO->nqpt, "");
1190 MFEM_VERIFY(nq == quad1D * quad1D, "");
1194 MFEM_VERIFY(nq == quad1D * quad1D * quad1D, "");
1197 pa_data.SetSize(nq * ne, Device::GetMemoryType());
1199 Vector coeff(ne * nq);
1203 for (int e=0; e<ne; ++e)
1205 ElementTransformation *tr = mesh->GetElementTransformation(e);
1206 for (int p=0; p<nq; ++p)
1208 coeff[p + (e * nq)] = Q->Eval(*tr, ir->IntPoint(p));
1213 if (trial_el->GetDerivType() == mfem::FiniteElement::DIV && dim == 3)
1215 PADivL2Setup3D(quad1D, ne, ir->GetWeights(), coeff, pa_data);
1217 else if (trial_el->GetDerivType() == mfem::FiniteElement::DIV && dim == 2)
1219 PADivL2Setup2D(quad1D, ne, ir->GetWeights(), coeff, pa_data);
1223 MFEM_ABORT("Unknown kernel.
");
1227 // Apply to x corresponding to DOF's in H(div) (trial), whose divergence is
1228 // integrated against L_2 test functions corresponding to y.
1229 static void PAHdivL2Apply3D(const int D1D,
1233 const Array<double> &_Bo,
1234 const Array<double> &_Gc,
1235 const Array<double> &_L2Bot,
1240 MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D >
HDIV_MAX_D1D");
1241 MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D >
HDIV_MAX_Q1D");
1242 constexpr static int VDIM = 3;
1244 auto Bo = Reshape(_Bo.Read(), Q1D, D1D-1);
1245 auto Gc = Reshape(_Gc.Read(), Q1D, D1D);
1246 auto L2Bot = Reshape(_L2Bot.Read(), L2D1D, Q1D);
1247 auto op = Reshape(_op.Read(), Q1D, Q1D, Q1D, NE);
1248 auto x = Reshape(_x.Read(), 3*(D1D-1)*(D1D-1)*D1D, NE);
1249 auto y = Reshape(_y.ReadWrite(), L2D1D, L2D1D, L2D1D, NE);
1253 double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D];
1255 for (int qz = 0; qz < Q1D; ++qz)
1257 for (int qy = 0; qy < Q1D; ++qy)
1259 for (int qx = 0; qx < Q1D; ++qx)
1261 div[qz][qy][qx] = 0.0;
1268 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
1270 const int D1Dz = (c == 2) ? D1D : D1D - 1;
1271 const int D1Dy = (c == 1) ? D1D : D1D - 1;
1272 const int D1Dx = (c == 0) ? D1D : D1D - 1;
1274 for (int dz = 0; dz < D1Dz; ++dz)
1276 double aXY[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
1277 for (int qy = 0; qy < Q1D; ++qy)
1279 for (int qx = 0; qx < Q1D; ++qx)
1285 for (int dy = 0; dy < D1Dy; ++dy)
1287 double aX[HDIV_MAX_Q1D];
1288 for (int qx = 0; qx < Q1D; ++qx)
1293 for (int dx = 0; dx < D1Dx; ++dx)
1295 const double t = x(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
1296 for (int qx = 0; qx < Q1D; ++qx)
1298 aX[qx] += t * ((c == 0) ? Gc(qx,dx) : Bo(qx,dx));
1302 for (int qy = 0; qy < Q1D; ++qy)
1304 const double wy = (c == 1) ? Gc(qy,dy) : Bo(qy,dy);
1305 for (int qx = 0; qx < Q1D; ++qx)
1307 aXY[qy][qx] += aX[qx] * wy;
1312 for (int qz = 0; qz < Q1D; ++qz)
1314 const double wz = (c == 2) ? Gc(qz,dz) : Bo(qz,dz);
1315 for (int qy = 0; qy < Q1D; ++qy)
1317 for (int qx = 0; qx < Q1D; ++qx)
1319 div[qz][qy][qx] += aXY[qy][qx] * wz;
1325 osc += D1Dx * D1Dy * D1Dz;
1326 } // loop (c) over components
1328 // Apply D operator.
1329 for (int qz = 0; qz < Q1D; ++qz)
1331 for (int qy = 0; qy < Q1D; ++qy)
1333 for (int qx = 0; qx < Q1D; ++qx)
1335 div[qz][qy][qx] *= op(qx,qy,qz,e);
1340 for (int qz = 0; qz < Q1D; ++qz)
1342 double aXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
1344 for (int dy = 0; dy < L2D1D; ++dy)
1346 for (int dx = 0; dx < L2D1D; ++dx)
1351 for (int qy = 0; qy < Q1D; ++qy)
1353 double aX[HDIV_MAX_D1D];
1354 for (int dx = 0; dx < L2D1D; ++dx)
1358 for (int qx = 0; qx < Q1D; ++qx)
1360 for (int dx = 0; dx < L2D1D; ++dx)
1362 aX[dx] += div[qz][qy][qx] * L2Bot(dx,qx);
1365 for (int dy = 0; dy < L2D1D; ++dy)
1367 const double wy = L2Bot(dy,qy);
1368 for (int dx = 0; dx < L2D1D; ++dx)
1370 aXY[dy][dx] += aX[dx] * wy;
1375 for (int dz = 0; dz < L2D1D; ++dz)
1377 const double wz = L2Bot(dz,qz);
1378 for (int dy = 0; dy < L2D1D; ++dy)
1380 for (int dx = 0; dx < L2D1D; ++dx)
1382 y(dx,dy,dz,e) += aXY[dy][dx] * wz;
1387 }); // end of element loop
1390 // Apply to x corresponding to DOF's in H(div) (trial), whose divergence is
1391 // integrated against L_2 test functions corresponding to y.
1392 static void PAHdivL2Apply2D(const int D1D,
1396 const Array<double> &_Bo,
1397 const Array<double> &_Gc,
1398 const Array<double> &_L2Bot,
1403 constexpr static int VDIM = 2;
1404 constexpr static int MAX_D1D = HDIV_MAX_D1D;
1405 constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
1407 auto Bo = Reshape(_Bo.Read(), Q1D, D1D-1);
1408 auto Gc = Reshape(_Gc.Read(), Q1D, D1D);
1409 auto L2Bot = Reshape(_L2Bot.Read(), L2D1D, Q1D);
1410 auto op = Reshape(_op.Read(), Q1D, Q1D, NE);
1411 auto x = Reshape(_x.Read(), 2*(D1D-1)*D1D, NE);
1412 auto y = Reshape(_y.ReadWrite(), L2D1D, L2D1D, NE);
1416 double div[MAX_Q1D][MAX_Q1D];
1418 for (int qy = 0; qy < Q1D; ++qy)
1420 for (int qx = 0; qx < Q1D; ++qx)
1428 for (int c = 0; c < VDIM; ++c) // loop over x, y components
1430 const int D1Dy = (c == 1) ? D1D : D1D - 1;
1431 const int D1Dx = (c == 0) ? D1D : D1D - 1;
1433 for (int dy = 0; dy < D1Dy; ++dy)
1436 for (int qx = 0; qx < Q1D; ++qx)
1441 for (int dx = 0; dx < D1Dx; ++dx)
1443 const double t = x(dx + (dy * D1Dx) + osc, e);
1444 for (int qx = 0; qx < Q1D; ++qx)
1446 aX[qx] += t * ((c == 0) ? Gc(qx,dx) : Bo(qx,dx));
1450 for (int qy = 0; qy < Q1D; ++qy)
1452 const double wy = (c == 1) ? Gc(qy,dy) : Bo(qy,dy);
1453 for (int qx = 0; qx < Q1D; ++qx)
1455 div[qy][qx] += aX[qx] * wy;
1461 } // loop (c) over components
1463 // Apply D operator.
1464 for (int qy = 0; qy < Q1D; ++qy)
1466 for (int qx = 0; qx < Q1D; ++qx)
1468 div[qy][qx] *= op(qx,qy,e);
1472 for (int qy = 0; qy < Q1D; ++qy)
1475 for (int dx = 0; dx < L2D1D; ++dx)
1479 for (int qx = 0; qx < Q1D; ++qx)
1481 for (int dx = 0; dx < L2D1D; ++dx)
1483 aX[dx] += div[qy][qx] * L2Bot(dx,qx);
1486 for (int dy = 0; dy < L2D1D; ++dy)
1488 const double wy = L2Bot(dy,qy);
1489 for (int dx = 0; dx < L2D1D; ++dx)
1491 y(dx,dy,e) += aX[dx] * wy;
1495 }); // end of element loop
1498 static void PAHdivL2ApplyTranspose3D(const int D1D,
1502 const Array<double> &_L2Bo,
1503 const Array<double> &_Gct,
1504 const Array<double> &_Bot,
1509 MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D >
HDIV_MAX_D1D");
1510 MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D >
HDIV_MAX_Q1D");
1511 constexpr static int VDIM = 3;
1513 auto L2Bo = Reshape(_L2Bo.Read(), Q1D, L2D1D);
1514 auto Gct = Reshape(_Gct.Read(), D1D, Q1D);
1515 auto Bot = Reshape(_Bot.Read(), D1D-1, Q1D);
1516 auto op = Reshape(_op.Read(), Q1D, Q1D, Q1D, NE);
1517 auto x = Reshape(_x.Read(), L2D1D, L2D1D, L2D1D, NE);
1518 auto y = Reshape(_y.ReadWrite(), 3*(D1D-1)*(D1D-1)*D1D, NE);
1522 double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D];
1524 for (int qz = 0; qz < Q1D; ++qz)
1526 for (int qy = 0; qy < Q1D; ++qy)
1528 for (int qx = 0; qx < Q1D; ++qx)
1530 div[qz][qy][qx] = 0.0;
1535 for (int dz = 0; dz < L2D1D; ++dz)
1537 double aXY[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
1538 for (int qy = 0; qy < Q1D; ++qy)
1540 for (int qx = 0; qx < Q1D; ++qx)
1546 for (int dy = 0; dy < L2D1D; ++dy)
1548 double aX[HDIV_MAX_Q1D];
1549 for (int qx = 0; qx < Q1D; ++qx)
1554 for (int dx = 0; dx < L2D1D; ++dx)
1556 const double t = x(dx,dy,dz,e);
1557 for (int qx = 0; qx < Q1D; ++qx)
1559 aX[qx] += t * L2Bo(qx,dx);
1563 for (int qy = 0; qy < Q1D; ++qy)
1565 const double wy = L2Bo(qy,dy);
1566 for (int qx = 0; qx < Q1D; ++qx)
1568 aXY[qy][qx] += aX[qx] * wy;
1573 for (int qz = 0; qz < Q1D; ++qz)
1575 const double wz = L2Bo(qz,dz);
1576 for (int qy = 0; qy < Q1D; ++qy)
1578 for (int qx = 0; qx < Q1D; ++qx)
1580 div[qz][qy][qx] += aXY[qy][qx] * wz;
1586 // Apply D operator.
1587 for (int qz = 0; qz < Q1D; ++qz)
1589 for (int qy = 0; qy < Q1D; ++qy)
1591 for (int qx = 0; qx < Q1D; ++qx)
1593 div[qz][qy][qx] *= op(qx,qy,qz,e);
1598 for (int qz = 0; qz < Q1D; ++qz)
1600 double aXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
1603 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
1605 const int D1Dz = (c == 2) ? D1D : D1D - 1;
1606 const int D1Dy = (c == 1) ? D1D : D1D - 1;
1607 const int D1Dx = (c == 0) ? D1D : D1D - 1;
1609 for (int dy = 0; dy < D1Dy; ++dy)
1611 for (int dx = 0; dx < D1Dx; ++dx)
1616 for (int qy = 0; qy < Q1D; ++qy)
1618 double aX[HDIV_MAX_D1D];
1619 for (int dx = 0; dx < D1Dx; ++dx)
1623 for (int qx = 0; qx < Q1D; ++qx)
1625 for (int dx = 0; dx < D1Dx; ++dx)
1627 aX[dx] += div[qz][qy][qx] * ((c == 0) ? Gct(dx,qx) :
1631 for (int dy = 0; dy < D1Dy; ++dy)
1633 const double wy = (c == 1) ? Gct(dy,qy) : Bot(dy,qy);
1634 for (int dx = 0; dx < D1Dx; ++dx)
1636 aXY[dy][dx] += aX[dx] * wy;
1641 for (int dz = 0; dz < D1Dz; ++dz)
1643 const double wz = (c == 2) ? Gct(dz,qz) : Bot(dz,qz);
1644 for (int dy = 0; dy < D1Dy; ++dy)
1646 for (int dx = 0; dx < D1Dx; ++dx)
1648 y(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e) +=
1654 osc += D1Dx * D1Dy * D1Dz;
1657 }); // end of element loop
1660 static void PAHdivL2ApplyTranspose2D(const int D1D,
1664 const Array<double> &_L2Bo,
1665 const Array<double> &_Gct,
1666 const Array<double> &_Bot,
1671 constexpr static int VDIM = 2;
1672 constexpr static int MAX_D1D = HDIV_MAX_D1D;
1673 constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
1675 auto L2Bo = Reshape(_L2Bo.Read(), Q1D, L2D1D);
1676 auto Gct = Reshape(_Gct.Read(), D1D, Q1D);
1677 auto Bot = Reshape(_Bot.Read(), D1D-1, Q1D);
1678 auto op = Reshape(_op.Read(), Q1D, Q1D, NE);
1679 auto x = Reshape(_x.Read(), L2D1D, L2D1D, NE);
1680 auto y = Reshape(_y.ReadWrite(), 2*(D1D-1)*D1D, NE);
1684 double div[MAX_Q1D][MAX_Q1D];
1686 for (int qy = 0; qy < Q1D; ++qy)
1688 for (int qx = 0; qx < Q1D; ++qx)
1694 for (int dy = 0; dy < L2D1D; ++dy)
1697 for (int qx = 0; qx < Q1D; ++qx)
1702 for (int dx = 0; dx < L2D1D; ++dx)
1704 const double t = x(dx,dy,e);
1705 for (int qx = 0; qx < Q1D; ++qx)
1707 aX[qx] += t * L2Bo(qx,dx);
1711 for (int qy = 0; qy < Q1D; ++qy)
1713 const double wy = L2Bo(qy,dy);
1714 for (int qx = 0; qx < Q1D; ++qx)
1716 div[qy][qx] += aX[qx] * wy;
1721 // Apply D operator.
1722 for (int qy = 0; qy < Q1D; ++qy)
1724 for (int qx = 0; qx < Q1D; ++qx)
1726 div[qy][qx] *= op(qx,qy,e);
1730 for (int qy = 0; qy < Q1D; ++qy)
1735 for (int c = 0; c < VDIM; ++c) // loop over x, y components
1737 const int D1Dy = (c == 1) ? D1D : D1D - 1;
1738 const int D1Dx = (c == 0) ? D1D : D1D - 1;
1740 for (int dx = 0; dx < D1Dx; ++dx)
1744 for (int qx = 0; qx < Q1D; ++qx)
1746 for (int dx = 0; dx < D1Dx; ++dx)
1748 aX[dx] += div[qy][qx] * ((c == 0) ? Gct(dx,qx) : Bot(dx,qx));
1751 for (int dy = 0; dy < D1Dy; ++dy)
1753 const double wy = (c == 0) ? Bot(dy,qy) : Gct(dy,qy);
1754 for (int dx = 0; dx < D1Dx; ++dx)
1756 y(dx + (dy * D1Dx) + osc, e) += aX[dx] * wy;
1763 }); // end of element loop
1766 void VectorFEDivergenceIntegrator::AddMultPA(const Vector &x, Vector &y) const
1769 PAHdivL2Apply3D(dofs1D, quad1D, L2dofs1D, ne, mapsO->B, mapsC->G,
1770 L2mapsO->Bt, pa_data, x, y);
1772 PAHdivL2Apply2D(dofs1D, quad1D, L2dofs1D, ne, mapsO->B, mapsC->G,
1773 L2mapsO->Bt, pa_data, x, y);
1776 MFEM_ABORT("Unsupported dimension!
");
1780 void VectorFEDivergenceIntegrator::AddMultTransposePA(const Vector &x,
1784 PAHdivL2ApplyTranspose3D(dofs1D, quad1D, L2dofs1D, ne, L2mapsO->B,
1785 mapsC->Gt, mapsO->Bt, pa_data, x, y);
1787 PAHdivL2ApplyTranspose2D(dofs1D, quad1D, L2dofs1D, ne, L2mapsO->B,
1788 mapsC->Gt, mapsO->Bt, pa_data, x, y);
1791 MFEM_ABORT("Unsupported dimension!
");
1795 static void PAHdivL2AssembleDiagonal_ADAt_3D(const int D1D,
1799 const Array<double> &_L2Bo,
1800 const Array<double> &_Gct,
1801 const Array<double> &_Bot,
1806 MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D >
HDIV_MAX_D1D");
1807 MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D >
HDIV_MAX_Q1D");
1808 constexpr static int VDIM = 3;
1810 auto L2Bo = Reshape(_L2Bo.Read(), Q1D, L2D1D);
1811 auto Gct = Reshape(_Gct.Read(), D1D, Q1D);
1812 auto Bot = Reshape(_Bot.Read(), D1D-1, Q1D);
1813 auto op = Reshape(_op.Read(), Q1D, Q1D, Q1D, NE);
1814 auto D = Reshape(_D.Read(), 3*(D1D-1)*(D1D-1)*D1D, NE);
1815 auto diag = Reshape(_diag.ReadWrite(), L2D1D, L2D1D, L2D1D, NE);
1819 for (int rz = 0; rz < L2D1D; ++rz)
1821 for (int ry = 0; ry < L2D1D; ++ry)
1823 for (int rx = 0; rx < L2D1D; ++rx)
1825 // Compute row (rx,ry,rz), assuming all contributions are from
1826 // a single element.
1828 double row[3*HDIV_MAX_D1D*(HDIV_MAX_D1D-1)*(HDIV_MAX_D1D-1)];
1829 double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D];
1831 for (int i=0; i<3*D1D*(D1D - 1)*(D1D - 1); ++i)
1836 for (int qz = 0; qz < Q1D; ++qz)
1838 for (int qy = 0; qy < Q1D; ++qy)
1840 for (int qx = 0; qx < Q1D; ++qx)
1842 div[qz][qy][qx] = op(qx,qy,qz,e) * L2Bo(qx,rx) *
1843 L2Bo(qy,ry) * L2Bo(qz,rz);
1848 for (int qz = 0; qz < Q1D; ++qz)
1850 double aXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
1853 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
1855 const int D1Dz = (c == 2) ? D1D : D1D - 1;
1856 const int D1Dy = (c == 1) ? D1D : D1D - 1;
1857 const int D1Dx = (c == 0) ? D1D : D1D - 1;
1859 for (int dy = 0; dy < D1Dy; ++dy)
1861 for (int dx = 0; dx < D1Dx; ++dx)
1866 for (int qy = 0; qy < Q1D; ++qy)
1868 double aX[HDIV_MAX_D1D];
1869 for (int dx = 0; dx < D1Dx; ++dx)
1873 for (int qx = 0; qx < Q1D; ++qx)
1875 for (int dx = 0; dx < D1Dx; ++dx)
1877 aX[dx] += div[qz][qy][qx] * ((c == 0) ? Gct(dx,qx)
1881 for (int dy = 0; dy < D1Dy; ++dy)
1883 const double wy = (c == 1) ? Gct(dy,qy) : Bot(dy,qy);
1884 for (int dx = 0; dx < D1Dx; ++dx)
1886 aXY[dy][dx] += aX[dx] * wy;
1891 for (int dz = 0; dz < D1Dz; ++dz)
1893 const double wz = (c == 2) ? Gct(dz,qz) : Bot(dz,qz);
1894 for (int dy = 0; dy < D1Dy; ++dy)
1896 for (int dx = 0; dx < D1Dx; ++dx)
1898 row[dx + ((dy + (dz * D1Dy)) * D1Dx) + osc] +=
1904 osc += D1Dx * D1Dy * D1Dz;
1909 for (int i=0; i<3*D1D*(D1D - 1)*(D1D - 1); ++i)
1911 val += row[i] * row[i] * D(i,e);
1913 diag(rx,ry,rz,e) += val;
1917 }); // end of element loop
1920 static void PAHdivL2AssembleDiagonal_ADAt_2D(const int D1D,
1924 const Array<double> &_L2Bo,
1925 const Array<double> &_Gct,
1926 const Array<double> &_Bot,
1931 constexpr static int VDIM = 2;
1933 auto L2Bo = Reshape(_L2Bo.Read(), Q1D, L2D1D);
1934 auto Gct = Reshape(_Gct.Read(), D1D, Q1D);
1935 auto Bot = Reshape(_Bot.Read(), D1D-1, Q1D);
1936 auto op = Reshape(_op.Read(), Q1D, Q1D, NE);
1937 auto D = Reshape(_D.Read(), 2*(D1D-1)*D1D, NE);
1938 auto diag = Reshape(_diag.ReadWrite(), L2D1D, L2D1D, NE);
1942 for (int ry = 0; ry < L2D1D; ++ry)
1944 for (int rx = 0; rx < L2D1D; ++rx)
1946 // Compute row (rx,ry), assuming all contributions are from
1947 // a single element.
1949 double row[2*HDIV_MAX_D1D*(HDIV_MAX_D1D-1)];
1950 double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
1952 for (int i=0; i<2*D1D*(D1D - 1); ++i)
1957 for (int qy = 0; qy < Q1D; ++qy)
1959 for (int qx = 0; qx < Q1D; ++qx)
1961 div[qy][qx] = op(qx,qy,e) * L2Bo(qx,rx) * L2Bo(qy,ry);
1965 for (int qy = 0; qy < Q1D; ++qy)
1968 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
1970 const int D1Dy = (c == 1) ? D1D : D1D - 1;
1971 const int D1Dx = (c == 0) ? D1D : D1D - 1;
1973 double aX[HDIV_MAX_D1D];
1974 for (int dx = 0; dx < D1Dx; ++dx)
1978 for (int qx = 0; qx < Q1D; ++qx)
1980 for (int dx = 0; dx < D1Dx; ++dx)
1982 aX[dx] += div[qy][qx] * ((c == 0) ? Gct(dx,qx) :
1987 for (int dy = 0; dy < D1Dy; ++dy)
1989 const double wy = (c == 1) ? Gct(dy,qy) : Bot(dy,qy);
1991 for (int dx = 0; dx < D1Dx; ++dx)
1993 row[dx + (dy * D1Dx) + osc] += aX[dx] * wy;
2002 for (int i=0; i<2*D1D*(D1D - 1); ++i)
2004 val += row[i] * row[i] * D(i,e);
2006 diag(rx,ry,e) += val;
2009 }); // end of element loop
2012 void VectorFEDivergenceIntegrator::AssembleDiagonalPA_ADAt(const Vector &D,
2016 PAHdivL2AssembleDiagonal_ADAt_3D(dofs1D, quad1D, L2dofs1D, ne, L2mapsO->B,
2017 mapsC->Gt, mapsO->Bt, pa_data, D, diag);
2019 PAHdivL2AssembleDiagonal_ADAt_2D(dofs1D, quad1D, L2dofs1D, ne, L2mapsO->B,
2020 mapsC->Gt, mapsO->Bt, pa_data, D, diag);
2023 MFEM_ABORT("Unsupported dimension!
");
constexpr int HDIV_MAX_D1D
void PAHdivMassAssembleDiagonal2D(const int D1D, const int Q1D, const int NE, const Array< double > &_Bo, const Array< double > &_Bc, const Vector &_op, Vector &_diag)
double * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
void PAHdivMassAssembleDiagonal3D(const int D1D, const int Q1D, const int NE, const Array< double > &_Bo, const Array< double > &_Bc, const Vector &_op, Vector &_diag)
DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims...dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
double * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
void PAHdivSetup3D(const int Q1D, const int NE, const Array< double > &w, const Vector &j, Vector &_coeff, Vector &op)
void PAHdivMassApply2D(const int D1D, const int Q1D, const int NE, const Array< double > &_Bo, const Array< double > &_Bc, const Array< double > &_Bot, const Array< double > &_Bct, const Vector &_op, const Vector &_x, Vector &_y)
void PAHdivSetup2D(const int Q1D, const int NE, const Array< double > &w, const Vector &j, Vector &_coeff, Vector &op)
const double * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
constexpr int HDIV_MAX_Q1D