12 #include "../general/forall.hpp"
33 const int NQ = Q1D*Q1D;
42 for (
int q = 0; q < NQ; ++q)
44 const double J11 = J(q,0,0,e);
45 const double J21 = J(q,1,0,e);
46 const double J12 = J(q,0,1,e);
47 const double J22 = J(q,1,1,e);
48 const double c_detJ = W[q] * coeff(q, e) / ((J11*J22)-(J21*J12));
50 y(q,0,e) = c_detJ * (J11*J11 + J21*J21);
51 y(q,1,e) = c_detJ * (J11*J12 + J21*J22);
52 y(q,2,e) = c_detJ * (J12*J12 + J22*J22);
65 const int NQ = Q1D*Q1D*Q1D;
73 for (
int q = 0; q < NQ; ++q)
75 const double J11 = J(q,0,0,e);
76 const double J21 = J(q,1,0,e);
77 const double J31 = J(q,2,0,e);
78 const double J12 = J(q,0,1,e);
79 const double J22 = J(q,1,1,e);
80 const double J32 = J(q,2,1,e);
81 const double J13 = J(q,0,2,e);
82 const double J23 = J(q,1,2,e);
83 const double J33 = J(q,2,2,e);
84 const double detJ = J11 * (J22 * J33 - J32 * J23) -
85 J21 * (J12 * J33 - J32 * J13) +
86 J31 * (J12 * J23 - J22 * J13);
87 const double c_detJ = W[q] * coeff(q, e) / detJ;
89 y(q,0,e) = c_detJ * (J11*J11 + J21*J21 + J31*J31);
90 y(q,1,e) = c_detJ * (J12*J11 + J22*J21 + J32*J31);
91 y(q,2,e) = c_detJ * (J13*J11 + J23*J21 + J33*J31);
92 y(q,3,e) = c_detJ * (J12*J12 + J22*J22 + J32*J32);
93 y(q,4,e) = c_detJ * (J13*J12 + J23*J22 + J33*J32);
94 y(q,5,e) = c_detJ * (J13*J13 + J23*J23 + J33*J33);
110 constexpr
static int VDIM = 2;
126 for (
int qy = 0; qy < Q1D; ++qy)
128 for (
int qx = 0; qx < Q1D; ++qx)
130 for (
int c = 0; c < VDIM; ++c)
132 mass[qy][qx][c] = 0.0;
139 for (
int c = 0; c < VDIM; ++c)
141 const int D1Dx = (c == 1) ? D1D - 1 : D1D;
142 const int D1Dy = (c == 0) ? D1D - 1 : D1D;
144 for (
int dy = 0; dy < D1Dy; ++dy)
147 for (
int qx = 0; qx < Q1D; ++qx)
152 for (
int dx = 0; dx < D1Dx; ++dx)
154 const double t = x(dx + (dy * D1Dx) + osc, e);
155 for (
int qx = 0; qx < Q1D; ++qx)
157 massX[qx] += t * ((c == 0) ? Bc(qx,dx) : Bo(qx,dx));
161 for (
int qy = 0; qy < Q1D; ++qy)
163 const double wy = (c == 1) ? Bc(qy,dy) : Bo(qy,dy);
164 for (
int qx = 0; qx < Q1D; ++qx)
166 mass[qy][qx][c] += massX[qx] * wy;
175 for (
int qy = 0; qy < Q1D; ++qy)
177 for (
int qx = 0; qx < Q1D; ++qx)
179 const double O11 = op(qx,qy,0,e);
180 const double O12 = op(qx,qy,1,e);
181 const double O22 = op(qx,qy,2,e);
182 const double massX = mass[qy][qx][0];
183 const double massY = mass[qy][qx][1];
184 mass[qy][qx][0] = (O11*massX)+(O12*massY);
185 mass[qy][qx][1] = (O12*massX)+(O22*massY);
189 for (
int qy = 0; qy < Q1D; ++qy)
193 for (
int c = 0; c < VDIM; ++c)
195 const int D1Dx = (c == 1) ? D1D - 1 : D1D;
196 const int D1Dy = (c == 0) ? D1D - 1 : D1D;
199 for (
int dx = 0; dx < D1Dx; ++dx)
203 for (
int qx = 0; qx < Q1D; ++qx)
205 for (
int dx = 0; dx < D1Dx; ++dx)
207 massX[dx] += mass[qy][qx][c] * ((c == 0) ? Bct(dx,qx) :
212 for (
int dy = 0; dy < D1Dy; ++dy)
214 const double wy = (c == 1) ? Bct(dy,qy) : Bot(dy,qy);
216 for (
int dx = 0; dx < D1Dx; ++dx)
218 y(dx + (dy * D1Dx) + osc, e) += massX[dx] * wy;
236 constexpr
static int VDIM = 2;
248 for (
int c = 0; c < VDIM; ++c)
250 const int D1Dx = (c == 1) ? D1D - 1 : D1D;
251 const int D1Dy = (c == 0) ? D1D - 1 : D1D;
253 for (
int dy = 0; dy < D1Dy; ++dy)
256 for (
int qx = 0; qx < Q1D; ++qx)
259 for (
int qy = 0; qy < Q1D; ++qy)
261 const double wy = (c == 1) ? Bc(qy,dy) : Bo(qy,dy);
262 mass[qx] += wy*wy*((c == 0) ? op(qx,qy,0,e) : op(qx,qy,2,e));
266 for (
int dx = 0; dx < D1Dx; ++dx)
269 for (
int qx = 0; qx < Q1D; ++qx)
271 const double wx = (c == 0) ? Bc(qx,dx) : Bo(qx,dx);
272 val += mass[qx] * wx * wx;
274 diag(dx + (dy * D1Dx) + osc, e) += val;
291 MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D >
HDIV_MAX_D1D");
292 MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D >
HDIV_MAX_Q1D");
293 constexpr static int VDIM = 3;
295 auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
296 auto Bc = Reshape(Bc_.Read(), Q1D, D1D);
297 auto op = Reshape(op_.Read(), Q1D, Q1D, Q1D, 6, NE);
298 auto diag = Reshape(diag_.ReadWrite(), 3*(D1D-1)*(D1D-1)*D1D, NE);
304 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
306 const int D1Dz = (c == 2) ? D1D : D1D - 1;
307 const int D1Dy = (c == 1) ? D1D : D1D - 1;
308 const int D1Dx = (c == 0) ? D1D : D1D - 1;
310 const int opc = (c == 0) ? 0 : ((c == 1) ? 3 : 5);
312 double mass[HDIV_MAX_Q1D];
314 for (int dz = 0; dz < D1Dz; ++dz)
316 for (int dy = 0; dy < D1Dy; ++dy)
318 for (int qx = 0; qx < Q1D; ++qx)
321 for (int qy = 0; qy < Q1D; ++qy)
323 const double wy = (c == 1) ? Bc(qy,dy) : Bo(qy,dy);
324 for (int qz = 0; qz < Q1D; ++qz)
326 const double wz = (c == 2) ? Bc(qz,dz) : Bo(qz,dz);
327 mass[qx] += wy * wy * wz * wz * op(qx,qy,qz,opc,e);
332 for (int dx = 0; dx < D1Dx; ++dx)
335 for (int qx = 0; qx < Q1D; ++qx)
337 const double wx = (c == 0) ? Bc(qx,dx) : Bo(qx,dx);
338 val += mass[qx] * wx * wx;
340 diag(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e) += val;
345 osc += D1Dx * D1Dy * D1Dz;
347 }); // end of element loop
350 void PAHdivMassApply3D(const int D1D,
353 const Array<double> &Bo_,
354 const Array<double> &Bc_,
355 const Array<double> &Bot_,
356 const Array<double> &Bct_,
361 MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D >
HDIV_MAX_D1D");
362 MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D >
HDIV_MAX_Q1D");
363 constexpr static int VDIM = 3;
365 auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
366 auto Bc = Reshape(Bc_.Read(), Q1D, D1D);
367 auto Bot = Reshape(Bot_.Read(), D1D-1, Q1D);
368 auto Bct = Reshape(Bct_.Read(), D1D, Q1D);
369 auto op = Reshape(op_.Read(), Q1D, Q1D, Q1D, 6, NE);
370 auto x = Reshape(x_.Read(), 3*(D1D-1)*(D1D-1)*D1D, NE);
371 auto y = Reshape(y_.ReadWrite(), 3*(D1D-1)*(D1D-1)*D1D, NE);
375 double mass[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D][VDIM];
377 for (int qz = 0; qz < Q1D; ++qz)
379 for (int qy = 0; qy < Q1D; ++qy)
381 for (int qx = 0; qx < Q1D; ++qx)
383 for (int c = 0; c < VDIM; ++c)
385 mass[qz][qy][qx][c] = 0.0;
393 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
395 const int D1Dz = (c == 2) ? D1D : D1D - 1;
396 const int D1Dy = (c == 1) ? D1D : D1D - 1;
397 const int D1Dx = (c == 0) ? D1D : D1D - 1;
399 for (int dz = 0; dz < D1Dz; ++dz)
401 double massXY[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
402 for (int qy = 0; qy < Q1D; ++qy)
404 for (int qx = 0; qx < Q1D; ++qx)
406 massXY[qy][qx] = 0.0;
410 for (int dy = 0; dy < D1Dy; ++dy)
412 double massX[HDIV_MAX_Q1D];
413 for (int qx = 0; qx < Q1D; ++qx)
418 for (int dx = 0; dx < D1Dx; ++dx)
420 const double t = x(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
421 for (int qx = 0; qx < Q1D; ++qx)
423 massX[qx] += t * ((c == 0) ? Bc(qx,dx) : Bo(qx,dx));
427 for (int qy = 0; qy < Q1D; ++qy)
429 const double wy = (c == 1) ? Bc(qy,dy) : Bo(qy,dy);
430 for (int qx = 0; qx < Q1D; ++qx)
432 const double wx = massX[qx];
433 massXY[qy][qx] += wx * wy;
438 for (int qz = 0; qz < Q1D; ++qz)
440 const double wz = (c == 2) ? Bc(qz,dz) : Bo(qz,dz);
441 for (int qy = 0; qy < Q1D; ++qy)
443 for (int qx = 0; qx < Q1D; ++qx)
445 mass[qz][qy][qx][c] += massXY[qy][qx] * wz;
451 osc += D1Dx * D1Dy * D1Dz;
452 } // loop (c) over components
455 for (int qz = 0; qz < Q1D; ++qz)
457 for (int qy = 0; qy < Q1D; ++qy)
459 for (int qx = 0; qx < Q1D; ++qx)
461 const double O11 = op(qx,qy,qz,0,e);
462 const double O12 = op(qx,qy,qz,1,e);
463 const double O13 = op(qx,qy,qz,2,e);
464 const double O22 = op(qx,qy,qz,3,e);
465 const double O23 = op(qx,qy,qz,4,e);
466 const double O33 = op(qx,qy,qz,5,e);
467 const double massX = mass[qz][qy][qx][0];
468 const double massY = mass[qz][qy][qx][1];
469 const double massZ = mass[qz][qy][qx][2];
470 mass[qz][qy][qx][0] = (O11*massX)+(O12*massY)+(O13*massZ);
471 mass[qz][qy][qx][1] = (O12*massX)+(O22*massY)+(O23*massZ);
472 mass[qz][qy][qx][2] = (O13*massX)+(O23*massY)+(O33*massZ);
477 for (int qz = 0; qz < Q1D; ++qz)
479 double massXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
483 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
485 const int D1Dz = (c == 2) ? D1D : D1D - 1;
486 const int D1Dy = (c == 1) ? D1D : D1D - 1;
487 const int D1Dx = (c == 0) ? D1D : D1D - 1;
489 for (int dy = 0; dy < D1Dy; ++dy)
491 for (int dx = 0; dx < D1Dx; ++dx)
496 for (int qy = 0; qy < Q1D; ++qy)
498 double massX[HDIV_MAX_D1D];
499 for (int dx = 0; dx < D1Dx; ++dx)
503 for (int qx = 0; qx < Q1D; ++qx)
505 for (int dx = 0; dx < D1Dx; ++dx)
507 massX[dx] += mass[qz][qy][qx][c] *
508 ((c == 0) ? Bct(dx,qx) : Bot(dx,qx));
511 for (int dy = 0; dy < D1Dy; ++dy)
513 const double wy = (c == 1) ? Bct(dy,qy) : Bot(dy,qy);
514 for (int dx = 0; dx < D1Dx; ++dx)
516 massXY[dy][dx] += massX[dx] * wy;
521 for (int dz = 0; dz < D1Dz; ++dz)
523 const double wz = (c == 2) ? Bct(dz,qz) : Bot(dz,qz);
524 for (int dy = 0; dy < D1Dy; ++dy)
526 for (int dx = 0; dx < D1Dx; ++dx)
528 y(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e) +=
534 osc += D1Dx * D1Dy * D1Dz;
537 }); // end of element loop
540 // PA H(div) div-div assemble 2D kernel
541 // NOTE: this is identical to PACurlCurlSetup3D
542 static void PADivDivSetup2D(const int Q1D,
544 const Array<double> &w,
549 const int NQ = Q1D*Q1D;
551 auto J = Reshape(j.Read(), NQ, 2, 2, NE);
552 auto coeff = Reshape(coeff_.Read(), NQ, NE);
553 auto y = Reshape(op.Write(), NQ, NE);
556 for (int q = 0; q < NQ; ++q)
558 const double J11 = J(q,0,0,e);
559 const double J21 = J(q,1,0,e);
560 const double J12 = J(q,0,1,e);
561 const double J22 = J(q,1,1,e);
562 const double detJ = (J11*J22)-(J21*J12);
563 y(q,e) = W[q] * coeff(q,e) / detJ;
568 static void PADivDivSetup3D(const int Q1D,
570 const Array<double> &w,
575 const int NQ = Q1D*Q1D*Q1D;
577 auto J = Reshape(j.Read(), NQ, 3, 3, NE);
578 auto coeff = Reshape(coeff_.Read(), NQ, NE);
579 auto y = Reshape(op.Write(), NQ, NE);
583 for (int q = 0; q < NQ; ++q)
585 const double J11 = J(q,0,0,e);
586 const double J21 = J(q,1,0,e);
587 const double J31 = J(q,2,0,e);
588 const double J12 = J(q,0,1,e);
589 const double J22 = J(q,1,1,e);
590 const double J32 = J(q,2,1,e);
591 const double J13 = J(q,0,2,e);
592 const double J23 = J(q,1,2,e);
593 const double J33 = J(q,2,2,e);
594 const double detJ = J11 * (J22 * J33 - J32 * J23) -
595 /* */ J21 * (J12 * J33 - J32 * J13) +
596 /* */ J31 * (J12 * J23 - J22 * J13);
597 y(q,e) = W[q] * coeff(q, e) / detJ;
602 static void PADivDivApply2D(const int D1D,
605 const Array<double> &Bo_,
606 const Array<double> &Gc_,
607 const Array<double> &Bot_,
608 const Array<double> &Gct_,
613 constexpr static int VDIM = 2;
614 constexpr static int MAX_D1D = HDIV_MAX_D1D;
615 constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
617 auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
618 auto Bot = Reshape(Bot_.Read(), D1D-1, Q1D);
619 auto Gc = Reshape(Gc_.Read(), Q1D, D1D);
620 auto Gct = Reshape(Gct_.Read(), D1D, Q1D);
621 auto op = Reshape(op_.Read(), Q1D, Q1D, NE);
622 auto x = Reshape(x_.Read(), 2*(D1D-1)*D1D, NE);
623 auto y = Reshape(y_.ReadWrite(), 2*(D1D-1)*D1D, NE);
627 double div[MAX_Q1D][MAX_Q1D];
629 // div[qy][qx] will be computed as du_x/dx + duy_/dy
631 for (int qy = 0; qy < Q1D; ++qy)
633 for (int qx = 0; qx < Q1D; ++qx)
641 for (int c = 0; c < VDIM; ++c) // loop over x, y components
643 const int D1Dx = (c == 1) ? D1D - 1 : D1D;
644 const int D1Dy = (c == 0) ? D1D - 1 : D1D;
646 for (int dy = 0; dy < D1Dy; ++dy)
648 double gradX[MAX_Q1D];
649 for (int qx = 0; qx < Q1D; ++qx)
654 for (int dx = 0; dx < D1Dx; ++dx)
656 const double t = x(dx + (dy * D1Dx) + osc, e);
657 for (int qx = 0; qx < Q1D; ++qx)
659 gradX[qx] += t * ((c == 0) ? Gc(qx,dx) : Bo(qx,dx));
663 for (int qy = 0; qy < Q1D; ++qy)
665 const double wy = (c == 0) ? Bo(qy,dy) : Gc(qy,dy);
666 for (int qx = 0; qx < Q1D; ++qx)
668 div[qy][qx] += gradX[qx] * wy;
674 } // loop (c) over components
677 for (int qy = 0; qy < Q1D; ++qy)
679 for (int qx = 0; qx < Q1D; ++qx)
681 div[qy][qx] *= op(qx,qy,e);
685 for (int qy = 0; qy < Q1D; ++qy)
689 for (int c = 0; c < VDIM; ++c) // loop over x, y components
691 const int D1Dx = (c == 1) ? D1D - 1 : D1D;
692 const int D1Dy = (c == 0) ? D1D - 1 : D1D;
694 double gradX[MAX_D1D];
695 for (int dx = 0; dx < D1Dx; ++dx)
699 for (int qx = 0; qx < Q1D; ++qx)
701 for (int dx = 0; dx < D1Dx; ++dx)
703 gradX[dx] += div[qy][qx] * (c == 0 ? Gct(dx,qx) : Bot(dx,qx));
706 for (int dy = 0; dy < D1Dy; ++dy)
708 const double wy = (c == 0) ? Bot(dy,qy) : Gct(dy,qy);
709 for (int dx = 0; dx < D1Dx; ++dx)
711 y(dx + (dy * D1Dx) + osc, e) += gradX[dx] * wy;
718 }); // end of element loop
721 static void PADivDivApply3D(const int D1D,
724 const Array<double> &Bo_,
725 const Array<double> &Gc_,
726 const Array<double> &Bot_,
727 const Array<double> &Gct_,
732 MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D >
HDIV_MAX_D1D");
733 MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D >
HDIV_MAX_Q1D");
734 constexpr static int VDIM = 3;
736 auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
737 auto Gc = Reshape(Gc_.Read(), Q1D, D1D);
738 auto Bot = Reshape(Bot_.Read(), D1D-1, Q1D);
739 auto Gct = Reshape(Gct_.Read(), D1D, Q1D);
740 auto op = Reshape(op_.Read(), Q1D, Q1D, Q1D, NE);
741 auto x = Reshape(x_.Read(), 3*(D1D-1)*(D1D-1)*D1D, NE);
742 auto y = Reshape(y_.ReadWrite(), 3*(D1D-1)*(D1D-1)*D1D, NE);
746 double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D];
748 for (int qz = 0; qz < Q1D; ++qz)
750 for (int qy = 0; qy < Q1D; ++qy)
752 for (int qx = 0; qx < Q1D; ++qx)
754 div[qz][qy][qx] = 0.0;
761 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
763 const int D1Dz = (c == 2) ? D1D : D1D - 1;
764 const int D1Dy = (c == 1) ? D1D : D1D - 1;
765 const int D1Dx = (c == 0) ? D1D : D1D - 1;
767 for (int dz = 0; dz < D1Dz; ++dz)
769 double aXY[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
770 for (int qy = 0; qy < Q1D; ++qy)
772 for (int qx = 0; qx < Q1D; ++qx)
778 for (int dy = 0; dy < D1Dy; ++dy)
780 double aX[HDIV_MAX_Q1D];
781 for (int qx = 0; qx < Q1D; ++qx)
786 for (int dx = 0; dx < D1Dx; ++dx)
788 const double t = x(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
789 for (int qx = 0; qx < Q1D; ++qx)
791 aX[qx] += t * ((c == 0) ? Gc(qx,dx) : Bo(qx,dx));
795 for (int qy = 0; qy < Q1D; ++qy)
797 const double wy = (c == 1) ? Gc(qy,dy) : Bo(qy,dy);
798 for (int qx = 0; qx < Q1D; ++qx)
800 const double wx = aX[qx];
801 aXY[qy][qx] += wx * wy;
806 for (int qz = 0; qz < Q1D; ++qz)
808 const double wz = (c == 2) ? Gc(qz,dz) : Bo(qz,dz);
809 for (int qy = 0; qy < Q1D; ++qy)
811 for (int qx = 0; qx < Q1D; ++qx)
813 div[qz][qy][qx] += aXY[qy][qx] * wz;
819 osc += D1Dx * D1Dy * D1Dz;
820 } // loop (c) over components
823 for (int qz = 0; qz < Q1D; ++qz)
825 for (int qy = 0; qy < Q1D; ++qy)
827 for (int qx = 0; qx < Q1D; ++qx)
829 div[qz][qy][qx] *= op(qx,qy,qz,e);
834 for (int qz = 0; qz < Q1D; ++qz)
836 double aXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
840 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
842 const int D1Dz = (c == 2) ? D1D : D1D - 1;
843 const int D1Dy = (c == 1) ? D1D : D1D - 1;
844 const int D1Dx = (c == 0) ? D1D : D1D - 1;
846 for (int dy = 0; dy < D1Dy; ++dy)
848 for (int dx = 0; dx < D1Dx; ++dx)
853 for (int qy = 0; qy < Q1D; ++qy)
855 double aX[HDIV_MAX_D1D];
856 for (int dx = 0; dx < D1Dx; ++dx)
860 for (int qx = 0; qx < Q1D; ++qx)
862 for (int dx = 0; dx < D1Dx; ++dx)
864 aX[dx] += div[qz][qy][qx] *
865 (c == 0 ? Gct(dx,qx) : Bot(dx,qx));
868 for (int dy = 0; dy < D1Dy; ++dy)
870 const double wy = (c == 1) ? Gct(dy,qy) : Bot(dy,qy);
871 for (int dx = 0; dx < D1Dx; ++dx)
873 aXY[dy][dx] += aX[dx] * wy;
878 for (int dz = 0; dz < D1Dz; ++dz)
880 const double wz = (c == 2) ? Gct(dz,qz) : Bot(dz,qz);
881 for (int dy = 0; dy < D1Dy; ++dy)
883 for (int dx = 0; dx < D1Dx; ++dx)
885 y(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e) +=
891 osc += D1Dx * D1Dy * D1Dz;
894 }); // end of element loop
897 void DivDivIntegrator::AssemblePA(const FiniteElementSpace &fes)
899 // Assumes tensor-product elements
900 Mesh *mesh = fes.GetMesh();
901 const FiniteElement *fel = fes.GetFE(0);
903 const VectorTensorFiniteElement *el =
904 dynamic_cast<const VectorTensorFiniteElement*>(fel);
907 const IntegrationRule *ir = IntRule ? IntRule : &MassIntegrator::GetRule
908 (*el, *el, *mesh->GetElementTransformation(0));
910 const int dims = el->GetDim();
911 MFEM_VERIFY(dims == 2 || dims == 3, "");
913 const int nq = ir->GetNPoints();
914 dim = mesh->Dimension();
915 MFEM_VERIFY(dim == 2 || dim == 3, "");
918 geom = mesh->GetGeometricFactors(*ir, GeometricFactors::JACOBIANS);
919 mapsC = &el->GetDofToQuad(*ir, DofToQuad::TENSOR);
920 mapsO = &el->GetDofToQuadOpen(*ir, DofToQuad::TENSOR);
921 dofs1D = mapsC->ndof;
922 quad1D = mapsC->nqpt;
924 MFEM_VERIFY(dofs1D == mapsO->ndof + 1 && quad1D == mapsO->nqpt, "");
926 pa_data.SetSize(nq * ne, Device::GetMemoryType());
928 Vector coeff(ne * nq);
932 for (int e=0; e<ne; ++e)
934 ElementTransformation *tr = mesh->GetElementTransformation(e);
935 for (int p=0; p<nq; ++p)
937 coeff[p + (e * nq)] = Q->Eval(*tr, ir->IntPoint(p));
942 if (el->GetDerivType() == mfem::FiniteElement::DIV && dim == 3)
944 PADivDivSetup3D(quad1D, ne, ir->GetWeights(), geom->J, coeff, pa_data);
946 else if (el->GetDerivType() == mfem::FiniteElement::DIV && dim == 2)
948 PADivDivSetup2D(quad1D, ne, ir->GetWeights(), geom->J, coeff, pa_data);
952 MFEM_ABORT("Unknown kernel.
");
956 void DivDivIntegrator::AddMultPA(const Vector &x, Vector &y) const
959 PADivDivApply3D(dofs1D, quad1D, ne, mapsO->B, mapsC->G,
960 mapsO->Bt, mapsC->Gt, pa_data, x, y);
962 PADivDivApply2D(dofs1D, quad1D, ne, mapsO->B, mapsC->G,
963 mapsO->Bt, mapsC->Gt, pa_data, x, y);
966 MFEM_ABORT("Unsupported dimension!
");
970 static void PADivDivAssembleDiagonal2D(const int D1D,
973 const Array<double> &Bo_,
974 const Array<double> &Gc_,
978 constexpr static int VDIM = 2;
979 constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
981 auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
982 auto Gc = Reshape(Gc_.Read(), Q1D, D1D);
983 auto op = Reshape(op_.Read(), Q1D, Q1D, NE);
984 auto diag = Reshape(diag_.ReadWrite(), 2*(D1D-1)*D1D, NE);
990 for (int c = 0; c < VDIM; ++c) // loop over x, y components
992 const int D1Dx = (c == 1) ? D1D - 1 : D1D;
993 const int D1Dy = (c == 0) ? D1D - 1 : D1D;
997 for (int dy = 0; dy < D1Dy; ++dy)
999 for (int qx = 0; qx < Q1D; ++qx)
1002 for (int qy = 0; qy < Q1D; ++qy)
1004 const double wy = (c == 0) ? Bo(qy,dy) : Gc(qy,dy);
1005 div[qx] += wy * wy * op(qx,qy,e);
1009 for (int dx = 0; dx < D1Dx; ++dx)
1012 for (int qx = 0; qx < Q1D; ++qx)
1014 const double wx = (c == 0) ? Gc(qx,dx) : Bo(qx,dx);
1015 val += div[qx] * wx * wx;
1017 diag(dx + (dy * D1Dx) + osc, e) += val;
1026 static void PADivDivAssembleDiagonal3D(const int D1D,
1029 const Array<double> &Bo_,
1030 const Array<double> &Gc_,
1034 MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D >
HDIV_MAX_D1D");
1035 MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D >
HDIV_MAX_Q1D");
1036 constexpr static int VDIM = 3;
1038 auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
1039 auto Gc = Reshape(Gc_.Read(), Q1D, D1D);
1040 auto op = Reshape(op_.Read(), Q1D, Q1D, Q1D, NE);
1041 auto diag = Reshape(diag_.ReadWrite(), 3*(D1D-1)*(D1D-1)*D1D, NE);
1047 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
1049 const int D1Dz = (c == 2) ? D1D : D1D - 1;
1050 const int D1Dy = (c == 1) ? D1D : D1D - 1;
1051 const int D1Dx = (c == 0) ? D1D : D1D - 1;
1053 for (int dz = 0; dz < D1Dz; ++dz)
1055 for (int dy = 0; dy < D1Dy; ++dy)
1057 double a[HDIV_MAX_Q1D];
1059 for (int qx = 0; qx < Q1D; ++qx)
1062 for (int qy = 0; qy < Q1D; ++qy)
1064 const double wy = (c == 1) ? Gc(qy,dy) : Bo(qy,dy);
1066 for (int qz = 0; qz < Q1D; ++qz)
1068 const double wz = (c == 2) ? Gc(qz,dz) : Bo(qz,dz);
1069 a[qx] += wy * wy * wz * wz * op(qx,qy,qz,e);
1074 for (int dx = 0; dx < D1Dx; ++dx)
1077 for (int qx = 0; qx < Q1D; ++qx)
1079 const double wx = (c == 0) ? Gc(qx,dx) : Bo(qx,dx);
1080 val += a[qx] * wx * wx;
1082 diag(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e) += val;
1087 osc += D1Dx * D1Dy * D1Dz;
1089 }); // end of element loop
1092 void DivDivIntegrator::AssembleDiagonalPA(Vector& diag)
1096 PADivDivAssembleDiagonal3D(dofs1D, quad1D, ne,
1097 mapsO->B, mapsC->G, pa_data, diag);
1101 PADivDivAssembleDiagonal2D(dofs1D, quad1D, ne,
1102 mapsO->B, mapsC->G, pa_data, diag);
1106 // PA H(div)-L2 (div u, p) assemble 2D kernel
1107 static void PADivL2Setup2D(const int Q1D,
1109 const Array<double> &w,
1113 const int NQ = Q1D*Q1D;
1115 auto coeff = Reshape(coeff_.Read(), NQ, NE);
1116 auto y = Reshape(op.Write(), NQ, NE);
1119 for (int q = 0; q < NQ; ++q)
1121 y(q,e) = W[q] * coeff(q,e);
1126 static void PADivL2Setup3D(const int Q1D,
1128 const Array<double> &w,
1132 const int NQ = Q1D*Q1D*Q1D;
1134 auto coeff = Reshape(coeff_.Read(), NQ, NE);
1135 auto y = Reshape(op.Write(), NQ, NE);
1139 for (int q = 0; q < NQ; ++q)
1141 y(q,e) = W[q] * coeff(q, e);
1147 VectorFEDivergenceIntegrator::AssemblePA(const FiniteElementSpace &trial_fes,
1148 const FiniteElementSpace &test_fes)
1150 // Assumes tensor-product elements, with a vector test space and
1151 // scalar trial space.
1152 Mesh *mesh = trial_fes.GetMesh();
1153 const FiniteElement *trial_fel = trial_fes.GetFE(0);
1154 const FiniteElement *test_fel = test_fes.GetFE(0);
1156 const VectorTensorFiniteElement *trial_el =
1157 dynamic_cast<const VectorTensorFiniteElement*>(trial_fel);
1160 const NodalTensorFiniteElement *test_el =
1161 dynamic_cast<const NodalTensorFiniteElement*>(test_fel);
1164 const IntegrationRule *ir = IntRule ? IntRule : &MassIntegrator::GetRule(
1165 *trial_el, *trial_el,
1166 *mesh->GetElementTransformation(0));
1168 const int dims = trial_el->GetDim();
1169 MFEM_VERIFY(dims == 2 || dims == 3, "");
1171 const int nq = ir->GetNPoints();
1172 dim = mesh->Dimension();
1173 MFEM_VERIFY(dim == 2 || dim == 3, "");
1175 MFEM_VERIFY(trial_el->GetOrder() == test_el->GetOrder() + 1, "");
1177 ne = trial_fes.GetNE();
1178 mapsC = &trial_el->GetDofToQuad(*ir, DofToQuad::TENSOR);
1179 mapsO = &trial_el->GetDofToQuadOpen(*ir, DofToQuad::TENSOR);
1180 dofs1D = mapsC->ndof;
1181 quad1D = mapsC->nqpt;
1183 L2mapsO = &test_el->GetDofToQuad(*ir, DofToQuad::TENSOR);
1184 L2dofs1D = L2mapsO->ndof;
1186 MFEM_VERIFY(dofs1D == mapsO->ndof + 1 && quad1D == mapsO->nqpt, "");
1189 MFEM_VERIFY(nq == quad1D * quad1D, "");
1193 MFEM_VERIFY(nq == quad1D * quad1D * quad1D, "");
1196 pa_data.SetSize(nq * ne, Device::GetMemoryType());
1198 Vector coeff(ne * nq);
1202 for (int e=0; e<ne; ++e)
1204 ElementTransformation *tr = mesh->GetElementTransformation(e);
1205 for (int p=0; p<nq; ++p)
1207 coeff[p + (e * nq)] = Q->Eval(*tr, ir->IntPoint(p));
1212 if (trial_el->GetDerivType() == mfem::FiniteElement::DIV && dim == 3)
1214 PADivL2Setup3D(quad1D, ne, ir->GetWeights(), coeff, pa_data);
1216 else if (trial_el->GetDerivType() == mfem::FiniteElement::DIV && dim == 2)
1218 PADivL2Setup2D(quad1D, ne, ir->GetWeights(), coeff, pa_data);
1222 MFEM_ABORT("Unknown kernel.
");
1226 // Apply to x corresponding to DOF's in H(div) (trial), whose divergence is
1227 // integrated against L_2 test functions corresponding to y.
1228 static void PAHdivL2Apply3D(const int D1D,
1232 const Array<double> &Bo_,
1233 const Array<double> &Gc_,
1234 const Array<double> &L2Bot_,
1239 MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D >
HDIV_MAX_D1D");
1240 MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D >
HDIV_MAX_Q1D");
1241 constexpr static int VDIM = 3;
1243 auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
1244 auto Gc = Reshape(Gc_.Read(), Q1D, D1D);
1245 auto L2Bot = Reshape(L2Bot_.Read(), L2D1D, Q1D);
1246 auto op = Reshape(op_.Read(), Q1D, Q1D, Q1D, NE);
1247 auto x = Reshape(x_.Read(), 3*(D1D-1)*(D1D-1)*D1D, NE);
1248 auto y = Reshape(y_.ReadWrite(), L2D1D, L2D1D, L2D1D, NE);
1252 double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D];
1254 for (int qz = 0; qz < Q1D; ++qz)
1256 for (int qy = 0; qy < Q1D; ++qy)
1258 for (int qx = 0; qx < Q1D; ++qx)
1260 div[qz][qy][qx] = 0.0;
1267 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
1269 const int D1Dz = (c == 2) ? D1D : D1D - 1;
1270 const int D1Dy = (c == 1) ? D1D : D1D - 1;
1271 const int D1Dx = (c == 0) ? D1D : D1D - 1;
1273 for (int dz = 0; dz < D1Dz; ++dz)
1275 double aXY[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
1276 for (int qy = 0; qy < Q1D; ++qy)
1278 for (int qx = 0; qx < Q1D; ++qx)
1284 for (int dy = 0; dy < D1Dy; ++dy)
1286 double aX[HDIV_MAX_Q1D];
1287 for (int qx = 0; qx < Q1D; ++qx)
1292 for (int dx = 0; dx < D1Dx; ++dx)
1294 const double t = x(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
1295 for (int qx = 0; qx < Q1D; ++qx)
1297 aX[qx] += t * ((c == 0) ? Gc(qx,dx) : Bo(qx,dx));
1301 for (int qy = 0; qy < Q1D; ++qy)
1303 const double wy = (c == 1) ? Gc(qy,dy) : Bo(qy,dy);
1304 for (int qx = 0; qx < Q1D; ++qx)
1306 aXY[qy][qx] += aX[qx] * wy;
1311 for (int qz = 0; qz < Q1D; ++qz)
1313 const double wz = (c == 2) ? Gc(qz,dz) : Bo(qz,dz);
1314 for (int qy = 0; qy < Q1D; ++qy)
1316 for (int qx = 0; qx < Q1D; ++qx)
1318 div[qz][qy][qx] += aXY[qy][qx] * wz;
1324 osc += D1Dx * D1Dy * D1Dz;
1325 } // loop (c) over components
1327 // Apply D operator.
1328 for (int qz = 0; qz < Q1D; ++qz)
1330 for (int qy = 0; qy < Q1D; ++qy)
1332 for (int qx = 0; qx < Q1D; ++qx)
1334 div[qz][qy][qx] *= op(qx,qy,qz,e);
1339 for (int qz = 0; qz < Q1D; ++qz)
1341 double aXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
1343 for (int dy = 0; dy < L2D1D; ++dy)
1345 for (int dx = 0; dx < L2D1D; ++dx)
1350 for (int qy = 0; qy < Q1D; ++qy)
1352 double aX[HDIV_MAX_D1D];
1353 for (int dx = 0; dx < L2D1D; ++dx)
1357 for (int qx = 0; qx < Q1D; ++qx)
1359 for (int dx = 0; dx < L2D1D; ++dx)
1361 aX[dx] += div[qz][qy][qx] * L2Bot(dx,qx);
1364 for (int dy = 0; dy < L2D1D; ++dy)
1366 const double wy = L2Bot(dy,qy);
1367 for (int dx = 0; dx < L2D1D; ++dx)
1369 aXY[dy][dx] += aX[dx] * wy;
1374 for (int dz = 0; dz < L2D1D; ++dz)
1376 const double wz = L2Bot(dz,qz);
1377 for (int dy = 0; dy < L2D1D; ++dy)
1379 for (int dx = 0; dx < L2D1D; ++dx)
1381 y(dx,dy,dz,e) += aXY[dy][dx] * wz;
1386 }); // end of element loop
1389 // Apply to x corresponding to DOF's in H(div) (trial), whose divergence is
1390 // integrated against L_2 test functions corresponding to y.
1391 static void PAHdivL2Apply2D(const int D1D,
1395 const Array<double> &Bo_,
1396 const Array<double> &Gc_,
1397 const Array<double> &L2Bot_,
1402 constexpr static int VDIM = 2;
1403 constexpr static int MAX_D1D = HDIV_MAX_D1D;
1404 constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
1406 auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
1407 auto Gc = Reshape(Gc_.Read(), Q1D, D1D);
1408 auto L2Bot = Reshape(L2Bot_.Read(), L2D1D, Q1D);
1409 auto op = Reshape(op_.Read(), Q1D, Q1D, NE);
1410 auto x = Reshape(x_.Read(), 2*(D1D-1)*D1D, NE);
1411 auto y = Reshape(y_.ReadWrite(), L2D1D, L2D1D, NE);
1415 double div[MAX_Q1D][MAX_Q1D];
1417 for (int qy = 0; qy < Q1D; ++qy)
1419 for (int qx = 0; qx < Q1D; ++qx)
1427 for (int c = 0; c < VDIM; ++c) // loop over x, y components
1429 const int D1Dy = (c == 1) ? D1D : D1D - 1;
1430 const int D1Dx = (c == 0) ? D1D : D1D - 1;
1432 for (int dy = 0; dy < D1Dy; ++dy)
1435 for (int qx = 0; qx < Q1D; ++qx)
1440 for (int dx = 0; dx < D1Dx; ++dx)
1442 const double t = x(dx + (dy * D1Dx) + osc, e);
1443 for (int qx = 0; qx < Q1D; ++qx)
1445 aX[qx] += t * ((c == 0) ? Gc(qx,dx) : Bo(qx,dx));
1449 for (int qy = 0; qy < Q1D; ++qy)
1451 const double wy = (c == 1) ? Gc(qy,dy) : Bo(qy,dy);
1452 for (int qx = 0; qx < Q1D; ++qx)
1454 div[qy][qx] += aX[qx] * wy;
1460 } // loop (c) over components
1462 // Apply D operator.
1463 for (int qy = 0; qy < Q1D; ++qy)
1465 for (int qx = 0; qx < Q1D; ++qx)
1467 div[qy][qx] *= op(qx,qy,e);
1471 for (int qy = 0; qy < Q1D; ++qy)
1474 for (int dx = 0; dx < L2D1D; ++dx)
1478 for (int qx = 0; qx < Q1D; ++qx)
1480 for (int dx = 0; dx < L2D1D; ++dx)
1482 aX[dx] += div[qy][qx] * L2Bot(dx,qx);
1485 for (int dy = 0; dy < L2D1D; ++dy)
1487 const double wy = L2Bot(dy,qy);
1488 for (int dx = 0; dx < L2D1D; ++dx)
1490 y(dx,dy,e) += aX[dx] * wy;
1494 }); // end of element loop
1497 static void PAHdivL2ApplyTranspose3D(const int D1D,
1501 const Array<double> &L2Bo_,
1502 const Array<double> &Gct_,
1503 const Array<double> &Bot_,
1508 MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D >
HDIV_MAX_D1D");
1509 MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D >
HDIV_MAX_Q1D");
1510 constexpr static int VDIM = 3;
1512 auto L2Bo = Reshape(L2Bo_.Read(), Q1D, L2D1D);
1513 auto Gct = Reshape(Gct_.Read(), D1D, Q1D);
1514 auto Bot = Reshape(Bot_.Read(), D1D-1, Q1D);
1515 auto op = Reshape(op_.Read(), Q1D, Q1D, Q1D, NE);
1516 auto x = Reshape(x_.Read(), L2D1D, L2D1D, L2D1D, NE);
1517 auto y = Reshape(y_.ReadWrite(), 3*(D1D-1)*(D1D-1)*D1D, NE);
1521 double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D];
1523 for (int qz = 0; qz < Q1D; ++qz)
1525 for (int qy = 0; qy < Q1D; ++qy)
1527 for (int qx = 0; qx < Q1D; ++qx)
1529 div[qz][qy][qx] = 0.0;
1534 for (int dz = 0; dz < L2D1D; ++dz)
1536 double aXY[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
1537 for (int qy = 0; qy < Q1D; ++qy)
1539 for (int qx = 0; qx < Q1D; ++qx)
1545 for (int dy = 0; dy < L2D1D; ++dy)
1547 double aX[HDIV_MAX_Q1D];
1548 for (int qx = 0; qx < Q1D; ++qx)
1553 for (int dx = 0; dx < L2D1D; ++dx)
1555 const double t = x(dx,dy,dz,e);
1556 for (int qx = 0; qx < Q1D; ++qx)
1558 aX[qx] += t * L2Bo(qx,dx);
1562 for (int qy = 0; qy < Q1D; ++qy)
1564 const double wy = L2Bo(qy,dy);
1565 for (int qx = 0; qx < Q1D; ++qx)
1567 aXY[qy][qx] += aX[qx] * wy;
1572 for (int qz = 0; qz < Q1D; ++qz)
1574 const double wz = L2Bo(qz,dz);
1575 for (int qy = 0; qy < Q1D; ++qy)
1577 for (int qx = 0; qx < Q1D; ++qx)
1579 div[qz][qy][qx] += aXY[qy][qx] * wz;
1585 // Apply D operator.
1586 for (int qz = 0; qz < Q1D; ++qz)
1588 for (int qy = 0; qy < Q1D; ++qy)
1590 for (int qx = 0; qx < Q1D; ++qx)
1592 div[qz][qy][qx] *= op(qx,qy,qz,e);
1597 for (int qz = 0; qz < Q1D; ++qz)
1599 double aXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
1602 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
1604 const int D1Dz = (c == 2) ? D1D : D1D - 1;
1605 const int D1Dy = (c == 1) ? D1D : D1D - 1;
1606 const int D1Dx = (c == 0) ? D1D : D1D - 1;
1608 for (int dy = 0; dy < D1Dy; ++dy)
1610 for (int dx = 0; dx < D1Dx; ++dx)
1615 for (int qy = 0; qy < Q1D; ++qy)
1617 double aX[HDIV_MAX_D1D];
1618 for (int dx = 0; dx < D1Dx; ++dx)
1622 for (int qx = 0; qx < Q1D; ++qx)
1624 for (int dx = 0; dx < D1Dx; ++dx)
1626 aX[dx] += div[qz][qy][qx] * ((c == 0) ? Gct(dx,qx) :
1630 for (int dy = 0; dy < D1Dy; ++dy)
1632 const double wy = (c == 1) ? Gct(dy,qy) : Bot(dy,qy);
1633 for (int dx = 0; dx < D1Dx; ++dx)
1635 aXY[dy][dx] += aX[dx] * wy;
1640 for (int dz = 0; dz < D1Dz; ++dz)
1642 const double wz = (c == 2) ? Gct(dz,qz) : Bot(dz,qz);
1643 for (int dy = 0; dy < D1Dy; ++dy)
1645 for (int dx = 0; dx < D1Dx; ++dx)
1647 y(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e) +=
1653 osc += D1Dx * D1Dy * D1Dz;
1656 }); // end of element loop
1659 static void PAHdivL2ApplyTranspose2D(const int D1D,
1663 const Array<double> &L2Bo_,
1664 const Array<double> &Gct_,
1665 const Array<double> &Bot_,
1670 constexpr static int VDIM = 2;
1671 constexpr static int MAX_D1D = HDIV_MAX_D1D;
1672 constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
1674 auto L2Bo = Reshape(L2Bo_.Read(), Q1D, L2D1D);
1675 auto Gct = Reshape(Gct_.Read(), D1D, Q1D);
1676 auto Bot = Reshape(Bot_.Read(), D1D-1, Q1D);
1677 auto op = Reshape(op_.Read(), Q1D, Q1D, NE);
1678 auto x = Reshape(x_.Read(), L2D1D, L2D1D, NE);
1679 auto y = Reshape(y_.ReadWrite(), 2*(D1D-1)*D1D, NE);
1683 double div[MAX_Q1D][MAX_Q1D];
1685 for (int qy = 0; qy < Q1D; ++qy)
1687 for (int qx = 0; qx < Q1D; ++qx)
1693 for (int dy = 0; dy < L2D1D; ++dy)
1696 for (int qx = 0; qx < Q1D; ++qx)
1701 for (int dx = 0; dx < L2D1D; ++dx)
1703 const double t = x(dx,dy,e);
1704 for (int qx = 0; qx < Q1D; ++qx)
1706 aX[qx] += t * L2Bo(qx,dx);
1710 for (int qy = 0; qy < Q1D; ++qy)
1712 const double wy = L2Bo(qy,dy);
1713 for (int qx = 0; qx < Q1D; ++qx)
1715 div[qy][qx] += aX[qx] * wy;
1720 // Apply D operator.
1721 for (int qy = 0; qy < Q1D; ++qy)
1723 for (int qx = 0; qx < Q1D; ++qx)
1725 div[qy][qx] *= op(qx,qy,e);
1729 for (int qy = 0; qy < Q1D; ++qy)
1734 for (int c = 0; c < VDIM; ++c) // loop over x, y components
1736 const int D1Dy = (c == 1) ? D1D : D1D - 1;
1737 const int D1Dx = (c == 0) ? D1D : D1D - 1;
1739 for (int dx = 0; dx < D1Dx; ++dx)
1743 for (int qx = 0; qx < Q1D; ++qx)
1745 for (int dx = 0; dx < D1Dx; ++dx)
1747 aX[dx] += div[qy][qx] * ((c == 0) ? Gct(dx,qx) : Bot(dx,qx));
1750 for (int dy = 0; dy < D1Dy; ++dy)
1752 const double wy = (c == 0) ? Bot(dy,qy) : Gct(dy,qy);
1753 for (int dx = 0; dx < D1Dx; ++dx)
1755 y(dx + (dy * D1Dx) + osc, e) += aX[dx] * wy;
1762 }); // end of element loop
1765 void VectorFEDivergenceIntegrator::AddMultPA(const Vector &x, Vector &y) const
1768 PAHdivL2Apply3D(dofs1D, quad1D, L2dofs1D, ne, mapsO->B, mapsC->G,
1769 L2mapsO->Bt, pa_data, x, y);
1771 PAHdivL2Apply2D(dofs1D, quad1D, L2dofs1D, ne, mapsO->B, mapsC->G,
1772 L2mapsO->Bt, pa_data, x, y);
1775 MFEM_ABORT("Unsupported dimension!
");
1779 void VectorFEDivergenceIntegrator::AddMultTransposePA(const Vector &x,
1783 PAHdivL2ApplyTranspose3D(dofs1D, quad1D, L2dofs1D, ne, L2mapsO->B,
1784 mapsC->Gt, mapsO->Bt, pa_data, x, y);
1786 PAHdivL2ApplyTranspose2D(dofs1D, quad1D, L2dofs1D, ne, L2mapsO->B,
1787 mapsC->Gt, mapsO->Bt, pa_data, x, y);
1790 MFEM_ABORT("Unsupported dimension!
");
1794 static void PAHdivL2AssembleDiagonal_ADAt_3D(const int D1D,
1798 const Array<double> &L2Bo_,
1799 const Array<double> &Gct_,
1800 const Array<double> &Bot_,
1805 MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D >
HDIV_MAX_D1D");
1806 MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D >
HDIV_MAX_Q1D");
1807 constexpr static int VDIM = 3;
1809 auto L2Bo = Reshape(L2Bo_.Read(), Q1D, L2D1D);
1810 auto Gct = Reshape(Gct_.Read(), D1D, Q1D);
1811 auto Bot = Reshape(Bot_.Read(), D1D-1, Q1D);
1812 auto op = Reshape(op_.Read(), Q1D, Q1D, Q1D, NE);
1813 auto D = Reshape(D_.Read(), 3*(D1D-1)*(D1D-1)*D1D, NE);
1814 auto diag = Reshape(diag_.ReadWrite(), L2D1D, L2D1D, L2D1D, NE);
1818 for (int rz = 0; rz < L2D1D; ++rz)
1820 for (int ry = 0; ry < L2D1D; ++ry)
1822 for (int rx = 0; rx < L2D1D; ++rx)
1824 // Compute row (rx,ry,rz), assuming all contributions are from
1825 // a single element.
1827 double row[3*HDIV_MAX_D1D*(HDIV_MAX_D1D-1)*(HDIV_MAX_D1D-1)];
1828 double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D];
1830 for (int i=0; i<3*D1D*(D1D - 1)*(D1D - 1); ++i)
1835 for (int qz = 0; qz < Q1D; ++qz)
1837 for (int qy = 0; qy < Q1D; ++qy)
1839 for (int qx = 0; qx < Q1D; ++qx)
1841 div[qz][qy][qx] = op(qx,qy,qz,e) * L2Bo(qx,rx) *
1842 L2Bo(qy,ry) * L2Bo(qz,rz);
1847 for (int qz = 0; qz < Q1D; ++qz)
1849 double aXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
1852 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
1854 const int D1Dz = (c == 2) ? D1D : D1D - 1;
1855 const int D1Dy = (c == 1) ? D1D : D1D - 1;
1856 const int D1Dx = (c == 0) ? D1D : D1D - 1;
1858 for (int dy = 0; dy < D1Dy; ++dy)
1860 for (int dx = 0; dx < D1Dx; ++dx)
1865 for (int qy = 0; qy < Q1D; ++qy)
1867 double aX[HDIV_MAX_D1D];
1868 for (int dx = 0; dx < D1Dx; ++dx)
1872 for (int qx = 0; qx < Q1D; ++qx)
1874 for (int dx = 0; dx < D1Dx; ++dx)
1876 aX[dx] += div[qz][qy][qx] * ((c == 0) ? Gct(dx,qx)
1880 for (int dy = 0; dy < D1Dy; ++dy)
1882 const double wy = (c == 1) ? Gct(dy,qy) : Bot(dy,qy);
1883 for (int dx = 0; dx < D1Dx; ++dx)
1885 aXY[dy][dx] += aX[dx] * wy;
1890 for (int dz = 0; dz < D1Dz; ++dz)
1892 const double wz = (c == 2) ? Gct(dz,qz) : Bot(dz,qz);
1893 for (int dy = 0; dy < D1Dy; ++dy)
1895 for (int dx = 0; dx < D1Dx; ++dx)
1897 row[dx + ((dy + (dz * D1Dy)) * D1Dx) + osc] +=
1903 osc += D1Dx * D1Dy * D1Dz;
1908 for (int i=0; i<3*D1D*(D1D - 1)*(D1D - 1); ++i)
1910 val += row[i] * row[i] * D(i,e);
1912 diag(rx,ry,rz,e) += val;
1916 }); // end of element loop
1919 static void PAHdivL2AssembleDiagonal_ADAt_2D(const int D1D,
1923 const Array<double> &L2Bo_,
1924 const Array<double> &Gct_,
1925 const Array<double> &Bot_,
1930 constexpr static int VDIM = 2;
1932 auto L2Bo = Reshape(L2Bo_.Read(), Q1D, L2D1D);
1933 auto Gct = Reshape(Gct_.Read(), D1D, Q1D);
1934 auto Bot = Reshape(Bot_.Read(), D1D-1, Q1D);
1935 auto op = Reshape(op_.Read(), Q1D, Q1D, NE);
1936 auto D = Reshape(D_.Read(), 2*(D1D-1)*D1D, NE);
1937 auto diag = Reshape(diag_.ReadWrite(), L2D1D, L2D1D, NE);
1941 for (int ry = 0; ry < L2D1D; ++ry)
1943 for (int rx = 0; rx < L2D1D; ++rx)
1945 // Compute row (rx,ry), assuming all contributions are from
1946 // a single element.
1948 double row[2*HDIV_MAX_D1D*(HDIV_MAX_D1D-1)];
1949 double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
1951 for (int i=0; i<2*D1D*(D1D - 1); ++i)
1956 for (int qy = 0; qy < Q1D; ++qy)
1958 for (int qx = 0; qx < Q1D; ++qx)
1960 div[qy][qx] = op(qx,qy,e) * L2Bo(qx,rx) * L2Bo(qy,ry);
1964 for (int qy = 0; qy < Q1D; ++qy)
1967 for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
1969 const int D1Dy = (c == 1) ? D1D : D1D - 1;
1970 const int D1Dx = (c == 0) ? D1D : D1D - 1;
1972 double aX[HDIV_MAX_D1D];
1973 for (int dx = 0; dx < D1Dx; ++dx)
1977 for (int qx = 0; qx < Q1D; ++qx)
1979 for (int dx = 0; dx < D1Dx; ++dx)
1981 aX[dx] += div[qy][qx] * ((c == 0) ? Gct(dx,qx) :
1986 for (int dy = 0; dy < D1Dy; ++dy)
1988 const double wy = (c == 1) ? Gct(dy,qy) : Bot(dy,qy);
1990 for (int dx = 0; dx < D1Dx; ++dx)
1992 row[dx + (dy * D1Dx) + osc] += aX[dx] * wy;
2001 for (int i=0; i<2*D1D*(D1D - 1); ++i)
2003 val += row[i] * row[i] * D(i,e);
2005 diag(rx,ry,e) += val;
2008 }); // end of element loop
2011 void VectorFEDivergenceIntegrator::AssembleDiagonalPA_ADAt(const Vector &D,
2015 PAHdivL2AssembleDiagonal_ADAt_3D(dofs1D, quad1D, L2dofs1D, ne, L2mapsO->B,
2016 mapsC->Gt, mapsO->Bt, pa_data, D, diag);
2018 PAHdivL2AssembleDiagonal_ADAt_2D(dofs1D, quad1D, L2dofs1D, ne, L2mapsO->B,
2019 mapsC->Gt, mapsO->Bt, pa_data, D, diag);
2022 MFEM_ABORT("Unsupported dimension!
");
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_)
constexpr int HDIV_MAX_D1D
DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims...dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
virtual double * Write(bool on_dev=true)
Shortcut for mfem::Write(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 PAHdivSetup2D(const int Q1D, const int NE, const Array< double > &w, const Vector &j, Vector &coeff_, Vector &op)
virtual double * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
void PAHdivMassAssembleDiagonal2D(const int D1D, const int Q1D, const int NE, const Array< double > &Bo_, const Array< double > &Bc_, const Vector &op_, Vector &diag_)
constexpr int HDIV_MAX_Q1D
void PAHdivMassAssembleDiagonal3D(const int D1D, const int Q1D, const int NE, const Array< double > &Bo_, const Array< double > &Bc_, const Vector &op_, Vector &diag_)
virtual const double * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).