23static void PADGDiffusionSetup2D(
const int Q1D,
26 const Array<real_t> &w,
27 const GeometricFactors &el_geom,
28 const FaceGeometricFactors &face_geom,
29 const FaceNeighborGeometricFactors *nbr_geom,
34 const Array<int> &face_info_)
36 const auto J_loc =
Reshape(el_geom.J.Read(), Q1D, Q1D, 2, 2, NE);
37 const auto detJe_loc =
Reshape(el_geom.detJ.Read(), Q1D, Q1D, NE);
39 const int n_nbr = nbr_geom ? nbr_geom->num_neighbor_elems : 0;
40 const auto J_shared =
Reshape(nbr_geom ? nbr_geom->J.Read() : nullptr,
41 Q1D, Q1D, 2, 2, n_nbr);
42 const auto detJ_shared =
Reshape(nbr_geom ? nbr_geom->detJ.Read() : nullptr,
45 const auto detJf =
Reshape(face_geom.detJ.Read(), Q1D, NF);
46 const auto n =
Reshape(face_geom.normal.Read(), Q1D, 2, NF);
48 const bool const_q = (q.Size() == 1);
51 const auto W = w.Read();
54 const auto face_info =
Reshape(face_info_.Read(), 6, NF);
57 auto pa =
Reshape(pa_data.Write(), 6, Q1D, NF);
61 const int normal_dir[] = {face_info(0,
f), face_info(1,
f)};
62 const int fid[] = {face_info(4,
f), face_info(5,
f)};
64 int el[] = {face_info(2,
f), face_info(3,
f)};
65 const bool interior = el[1] >= 0;
66 const int nsides = (interior) ? 2 : 1;
67 const real_t factor = interior ? 0.5 : 1.0;
69 const bool shared = el[1] >= NE;
70 el[1] = shared ? el[1] - NE : el[1];
72 const int sgn0 = (fid[0] == 0 || fid[0] == 1) ? 1 : -1;
73 const int sgn1 = (fid[1] == 0 || fid[1] == 1) ? 1 : -1;
75 for (
int p = 0;
p < Q1D; ++
p)
77 const real_t Qp = const_q ? Q(0,0) : Q(
p,
f);
81 for (
int side = 0; side < nsides; ++side)
84 internal::FaceIdxToVolIdx2D(
p, Q1D, fid[0], fid[1], side, i, j);
88 const int sgn = (side == 1) ? -1*sgn0*sgn1 : 1;
90 const int e = el[side];
91 const auto &J = (side == 1 && shared) ? J_shared : J_loc;
92 const auto &detJ = (side == 1 && shared) ? detJ_shared : detJe_loc;
95 nJi[0] = n(
p,0,
f)*J(i,j, 1,1, e) - n(
p,1,
f)*J(i,j,0,1,e);
96 nJi[1] = -n(
p,0,
f)*J(i,j,1,0, e) + n(
p,1,
f)*J(i,j,0,0,e);
98 const real_t dJe = detJ(i,j,e);
101 const real_t w = factor * Qp * W[
p] * dJf / dJe;
103 const int ni = normal_dir[side];
104 const int ti = 1 - ni;
107 pa(2 + 2*side + 0,
p,
f) = w * nJi[ni];
109 pa(2 + 2*side + 1,
p,
f) = sgn * w * nJi[ti];
111 hi += factor * dJf / dJe;
125static void PADGDiffusionSetup3D(
const int Q1D,
128 const Array<real_t> &w,
129 const GeometricFactors &el_geom,
130 const FaceGeometricFactors &face_geom,
131 const FaceNeighborGeometricFactors *nbr_geom,
136 const Array<int> &face_info_)
138 const auto J_loc =
Reshape(el_geom.J.Read(), Q1D, Q1D, Q1D, 3, 3, NE);
139 const auto detJe_loc =
Reshape(el_geom.detJ.Read(), Q1D, Q1D, Q1D, NE);
141 const int n_nbr = nbr_geom ? nbr_geom->num_neighbor_elems : 0;
142 const auto J_shared =
Reshape(nbr_geom ? nbr_geom->J.Read() : nullptr,
143 Q1D, Q1D, Q1D, 3, 3, n_nbr);
144 const auto detJ_shared =
Reshape(nbr_geom ? nbr_geom->detJ.Read() : nullptr,
145 Q1D, Q1D, Q1D, n_nbr);
147 const auto detJf =
Reshape(face_geom.detJ.Read(), Q1D, Q1D, NF);
148 const auto n =
Reshape(face_geom.normal.Read(), Q1D, Q1D, 3, NF);
150 const bool const_q = (q.Size() == 1);
151 const auto Q = const_q ?
Reshape(q.Read(), 1, 1, 1)
154 const auto W =
Reshape(w.Read(), Q1D, Q1D);
157 const auto face_info =
Reshape(face_info_.Read(), 6, 2, NF);
158 constexpr int _el_ = 3;
159 constexpr int _fid_ = 4;
160 constexpr int _or_ = 5;
163 const auto pa =
Reshape(pa_data.Write(), 7, Q1D, Q1D, NF);
167 MFEM_SHARED
int perm[2][3];
168 MFEM_SHARED
int el[2];
169 MFEM_SHARED
bool shared[2];
170 MFEM_SHARED
int fid[2];
171 MFEM_SHARED
int ortn[2];
173 MFEM_FOREACH_THREAD(side, x, 2)
175 MFEM_FOREACH_THREAD(i, y, 3)
177 perm[side][i] = face_info(i, side,
f);
180 if (MFEM_THREAD_ID(y) == 0)
182 el[side] = face_info(_el_, side,
f);
183 fid[side] = face_info(_fid_, side,
f);
184 ortn[side] = face_info(_or_, side,
f);
188 shared[side] = (el[side] >= NE);
189 el[side] = shared[side] ? el[side] - NE : el[side];
195 const bool interior = el[1] >= 0;
196 const int nsides = interior ? 2 : 1;
197 const real_t factor = interior ? 0.5 : 1.0;
199 MFEM_FOREACH_THREAD(p1, x, Q1D)
201 MFEM_FOREACH_THREAD(p2, y, Q1D)
203 const real_t Qp = const_q ? Q(0,0,0) : Q(p1, p2,
f);
204 const real_t dJf = detJf(p1,p2,
f);
208 for (
int side = 0; side < nsides; ++side)
211 internal::FaceIdxToVolIdx3D(
212 p1 + Q1D*p2, Q1D, fid[0], fid[1], side, ortn[1], i, j, k);
214 const int e = el[side];
215 const auto &J = shared[side] ? J_shared : J_loc;
216 const auto &detJe = shared[side] ? detJ_shared : detJe_loc;
220 nJi[0] = ( -J(i,j,k, 1,2, e)*J(i,j,k, 2,1, e) + J(i,j,k, 1,1, e)*J(i,j,k, 2,2, e)) * n(p1,p2, 0,
f)
221 + ( J(i,j,k, 0,2, e)*J(i,j,k, 2,1, e) - J(i,j,k, 0,1, e)*J(i,j,k, 2,2, e)) * n(p1,p2, 1,
f)
222 + (-J(i,j,k, 0,2, e)*J(i,j,k, 1,1, e) + J(i,j,k, 0,1, e)*J(i,j,k, 1,2, e)) * n(p1,p2, 2,
f);
224 nJi[1] = ( J(i,j,k, 1,2, e)*J(i,j,k, 2,0, e) - J(i,j,k, 1,0, e)*J(i,j,k, 2,2, e)) * n(p1,p2, 0,
f)
225 + (-J(i,j,k, 0,2, e)*J(i,j,k, 2,0, e) + J(i,j,k, 0,0, e)*J(i,j,k, 2,2, e)) * n(p1,p2, 1,
f)
226 + ( J(i,j,k, 0,2, e)*J(i,j,k, 1,0, e) - J(i,j,k, 0,0, e)*J(i,j,k, 1,2, e)) * n(p1,p2, 2,
f);
228 nJi[2] = ( -J(i,j,k, 1,1, e)*J(i,j,k, 2,0, e) + J(i,j,k, 1,0, e)*J(i,j,k, 2,1, e)) * n(p1,p2, 0,
f)
229 + ( J(i,j,k, 0,1, e)*J(i,j,k, 2,0, e) - J(i,j,k, 0,0, e)*J(i,j,k, 2,1, e)) * n(p1,p2, 1,
f)
230 + (-J(i,j,k, 0,1, e)*J(i,j,k, 1,0, e) + J(i,j,k, 0,0, e)*J(i,j,k, 1,1, e)) * n(p1,p2, 2,
f);
233 const real_t dJe = detJe(i,j,k,e);
234 const real_t val = factor * Qp * W(p1, p2) * dJf / dJe;
236 for (
int d = 0; d < 3; ++d)
238 const int idx = std::abs(perm[side][d]) - 1;
239 const int sgn = (perm[side][d] < 0) ? -1 : 1;
240 pa(3*side + d, p1, p2,
f) = sgn * val * nJi[idx];
243 hi += factor * dJf / dJe;
248 pa(3, p1, p2,
f) = 0.0;
249 pa(4, p1, p2,
f) = 0.0;
250 pa(5, p1, p2,
f) = 0.0;
253 pa(6, p1, p2,
f) =
kappa * hi * Qp * W(p1, p2) * dJf;
259static void PADGDiffusionSetupFaceInfo2D(
const int nf,
const Mesh &mesh,
260 const FaceType type, Array<int> &face_info_)
262 const int ne = mesh.GetNE();
265 face_info_.SetSize(nf * 6);
272 auto face_info =
Reshape(face_info_.HostWrite(), 6, nf);
273 for (
int f = 0;
f < mesh.GetNumFaces(); ++
f)
275 auto f_info = mesh.GetFaceInformation(
f);
277 if (f_info.IsOfFaceType(type))
279 const int face_id_1 = f_info.element[0].local_face_id;
280 face_info(0, fidx) = (face_id_1 == 1 || face_id_1 == 3) ? 0 : 1;
281 face_info(2, fidx) = f_info.element[0].index;
282 face_info(4, fidx) = face_id_1;
284 if (f_info.IsInterior())
286 const int face_id_2 = f_info.element[1].local_face_id;
287 face_info(1, fidx) = (face_id_2 == 1 || face_id_2 == 3) ? 0 : 1;
288 if (f_info.IsShared())
290 face_info(3, fidx) = ne + f_info.element[1].index;
294 face_info(3, fidx) = f_info.element[1].index;
296 face_info(5, fidx) = face_id_2;
300 face_info(1, fidx) = -1;
301 face_info(3, fidx) = -1;
302 face_info(5, fidx) = -1;
318 const bool xy_plane = (face_id == 0 || face_id == 5);
319 const bool xz_plane = (face_id == 1 || face_id == 3);
322 perm[0] = (xy_plane) ? 3 : (xz_plane) ? 2 : 1;
323 perm[1] = (xy_plane || xz_plane) ? 1 : 2;
324 perm[2] = (xy_plane) ? 2 : 3;
332 const int orientation)
337 if (face_id2 == 3 || face_id2 == 4)
341 else if (face_id2 == 0)
349 std::swap(perm[1], perm[2]);
352 std::swap(perm[1], perm[2]);
363 std::swap(perm[1], perm[2]);
368 std::swap(perm[1], perm[2]);
378 if (face_id1 == 3 || face_id1 == 4)
382 else if (face_id1 == 0)
388static void PADGDiffusionSetupFaceInfo3D(
const int nf,
const Mesh &mesh,
389 const FaceType type, Array<int> &face_info_)
391 const int ne = mesh.GetNE();
396 face_info_.SetSize(nf * 12);
397 constexpr int _e_ = 3;
398 constexpr int _fid_ = 4;
399 constexpr int _or_ = 5;
401 auto face_info =
Reshape(face_info_.HostWrite(), 6, 2, nf);
402 for (
int f = 0;
f < mesh.GetNumFaces(); ++
f)
404 auto f_info = mesh.GetFaceInformation(
f);
406 if (f_info.IsOfFaceType(type))
408 const int fid0 = f_info.element[0].local_face_id;
409 const int or0 = f_info.element[0].orientation;
411 face_info( _e_, 0, fidx) = f_info.element[0].index;
412 face_info(_fid_, 0, fidx) = fid0;
413 face_info( _or_, 0, fidx) = or0;
417 if (f_info.IsInterior())
419 const int fid1 = f_info.element[1].local_face_id;
420 const int or1 = f_info.element[1].orientation;
422 if (f_info.IsShared())
424 face_info( _e_, 1, fidx) = ne + f_info.element[1].index;
428 face_info( _e_, 1, fidx) = f_info.element[1].index;
430 face_info(_fid_, 1, fidx) = fid1;
431 face_info( _or_, 1, fidx) = or1;
437 for (
int i = 0; i < 6; ++i)
439 face_info(i, 1, fidx) = -1;
448void DGDiffusionIntegrator::SetupPA(
const FiniteElementSpace &fes,
454 const int ne = fes.GetNE();
455 nf = fes.GetNFbyType(type);
458 Mesh &mesh = *fes.GetMesh();
459 const Geometry::Type face_geom_type = mesh.GetTypicalFaceGeometry();
460 const FiniteElement &el = *fes.GetTypicalTraceElement();
463 const IntegrationRule &ir =
irs.
Get(face_geom_type, ir_order);
464 dim = mesh.Dimension();
465 const int q1d = (ir.GetOrder() + 3)/2;
466 MFEM_ASSERT(q1d == pow(
real_t(ir.Size()), 1.0/(
dim - 1)),
"");
468 const auto vol_ir =
irs.
Get(mesh.GetTypicalElementGeometry(), ir_order);
471 const auto el_geom = mesh.GetGeometricFactors(vol_ir, geom_flags, mt);
473 std::unique_ptr<FaceNeighborGeometricFactors> nbr_geom;
476 nbr_geom.reset(
new FaceNeighborGeometricFactors(*el_geom));
481 auto face_geom = mesh.GetFaceGeometricFactors(ir, face_geom_flags, type, mt);
486 const int pa_size = (
dim == 2) ? (6 * q1d *
nf) : (7 * q1d * q1d *
nf);
490 FaceQuadratureSpace fqs(mesh, ir, type);
492 if (
Q) { q.Project(*
Q); }
493 else if (
MQ) { MFEM_ABORT(
"Not yet implemented"); }
494 else { q.SetConstant(1.0); }
496 Array<int> face_info;
499 MFEM_ABORT(
"dim==1 not supported in PADGTraceSetup");
503 PADGDiffusionSetupFaceInfo2D(
nf, mesh, type, face_info);
504 PADGDiffusionSetup2D(
quad1D, ne,
nf, ir.GetWeights(), *el_geom, *face_geom,
509 PADGDiffusionSetupFaceInfo3D(
nf, mesh, type, face_info);
510 PADGDiffusionSetup3D(
quad1D, ne,
nf, ir.GetWeights(), *el_geom, *face_geom,
527template<
int T_D1D = 0,
int T_Q1D = 0>
static
528void PADGDiffusionApply2D(
const int NF,
542 const int D1D = T_D1D ? T_D1D : d1d;
543 const int Q1D = T_Q1D ? T_Q1D : q1d;
547 auto B_ =
Reshape(
b.Read(), Q1D, D1D);
557 const int NBX = std::max(D1D, Q1D);
561 constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
562 constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
564 MFEM_SHARED
real_t u0[max_D1D];
565 MFEM_SHARED
real_t u1[max_D1D];
566 MFEM_SHARED
real_t du0[max_D1D];
567 MFEM_SHARED
real_t du1[max_D1D];
569 MFEM_SHARED
real_t Bu0[max_Q1D];
570 MFEM_SHARED
real_t Bu1[max_Q1D];
571 MFEM_SHARED
real_t Bdu0[max_Q1D];
572 MFEM_SHARED
real_t Bdu1[max_Q1D];
574 MFEM_SHARED
real_t r[max_Q1D];
576 MFEM_SHARED
real_t BG[2*max_D1D*max_Q1D];
580 if (MFEM_THREAD_ID(y) == 0)
582 MFEM_FOREACH_THREAD(
p,x,Q1D)
584 for (
int d = 0; d < D1D; ++d)
594 MFEM_FOREACH_THREAD(side,y,2)
596 real_t *
u = (side == 0) ? u0 : u1;
597 real_t *du = (side == 0) ? du0 : du1;
598 MFEM_FOREACH_THREAD(d,x,D1D)
600 u[d] = x(d, side,
f);
601 du[d] = dxdn(d, side,
f);
607 MFEM_FOREACH_THREAD(side,y,2)
609 real_t *
u = (side == 0) ? u0 : u1;
610 real_t *du = (side == 0) ? du0 : du1;
611 real_t *Bu = (side == 0) ? Bu0 : Bu1;
612 real_t *Bdu = (side == 0) ? Bdu0 : Bdu1;
614 MFEM_FOREACH_THREAD(
p,x,Q1D)
616 const real_t Je_side[] = {pa(2 + 2*side,
p,
f), pa(2 + 2*side + 1,
p,
f)};
621 for (
int d = 0; d < D1D; ++d)
627 Bdu[
p] += Je_side[0] *
b * du[d] + Je_side[1] * g *
u[d];
634 if (MFEM_THREAD_ID(y) == 0)
636 MFEM_FOREACH_THREAD(
p,x,Q1D)
640 const real_t jump = Bu0[
p] - Bu1[
p];
641 const real_t avg = Bdu0[
p] + Bdu1[
p];
642 r[
p] = -avg + hi * q * jump;
647 MFEM_FOREACH_THREAD(d,x,D1D)
651 for (
int p = 0;
p < Q1D; ++
p)
653 Br += B(
p, d) * r[
p];
662 MFEM_FOREACH_THREAD(side,y,2)
664 real_t *du = (side == 0) ? du0 : du1;
665 MFEM_FOREACH_THREAD(d,x,D1D)
673 MFEM_FOREACH_THREAD(side,y,2)
675 real_t *
const du = (side == 0) ? du0 : du1;
676 real_t *
const u = (side == 0) ? u0 : u1;
678 MFEM_FOREACH_THREAD(d,x,D1D)
680 for (
int p = 0;
p < Q1D; ++
p)
682 const real_t Je[] = {pa(2 + 2*side,
p,
f), pa(2 + 2*side + 1,
p,
f)};
683 const real_t jump = Bu0[
p] - Bu1[
p];
684 const real_t r_p = Je[0] * jump;
685 const real_t w_p = Je[1] * jump;
686 du[d] +=
sigma * B(
p, d) * r_p;
693 MFEM_FOREACH_THREAD(side,y,2)
695 real_t *
u = (side == 0) ? u0 : u1;
696 real_t *du = (side == 0) ? du0 : du1;
697 MFEM_FOREACH_THREAD(d,x,D1D)
699 y(d, side,
f) +=
u[d];
700 dydn(d, side,
f) += du[d];
706template <
int T_D1D = 0,
int T_Q1D = 0>
707static void PADGDiffusionApply3D(
const int NF,
708 const Array<real_t>&
b,
709 const Array<real_t>& bt,
710 const Array<real_t>& g,
711 const Array<real_t>& gt,
713 const Vector& pa_data,
721 const int D1D = T_D1D ? T_D1D : d1d;
722 const int Q1D = T_Q1D ? T_Q1D : q1d;
726 auto B_ =
Reshape(
b.Read(), Q1D, D1D);
727 auto G_ =
Reshape(g.Read(), Q1D, D1D);
730 auto pa =
Reshape(pa_data.Read(), 7, Q1D, Q1D, NF);
732 auto x =
Reshape(x_.Read(), D1D, D1D, 2, NF);
733 auto y =
Reshape(y_.ReadWrite(), D1D, D1D, 2, NF);
734 auto dxdn =
Reshape(dxdn_.Read(), D1D, D1D, 2, NF);
735 auto dydn =
Reshape(dydn_.ReadWrite(), D1D, D1D, 2, NF);
737 const int NBX = std::max(D1D, Q1D);
741 constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
742 constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
744 MFEM_SHARED
real_t u0[max_Q1D][max_Q1D];
745 MFEM_SHARED
real_t u1[max_Q1D][max_Q1D];
747 MFEM_SHARED
real_t du0[max_Q1D][max_Q1D];
748 MFEM_SHARED
real_t du1[max_Q1D][max_Q1D];
750 MFEM_SHARED
real_t Gu0[max_Q1D][max_Q1D];
751 MFEM_SHARED
real_t Gu1[max_Q1D][max_Q1D];
753 MFEM_SHARED
real_t Bu0[max_Q1D][max_Q1D];
754 MFEM_SHARED
real_t Bu1[max_Q1D][max_Q1D];
756 MFEM_SHARED
real_t Bdu0[max_Q1D][max_Q1D];
757 MFEM_SHARED
real_t Bdu1[max_Q1D][max_Q1D];
759 MFEM_SHARED
real_t kappa_Qh[max_Q1D][max_Q1D];
761 MFEM_SHARED
real_t nJe[2][max_Q1D][max_Q1D][3];
762 MFEM_SHARED
real_t BG[2*max_D1D*max_Q1D];
765 real_t (*Bj0)[max_Q1D] = Bu0;
766 real_t (*Bj1)[max_Q1D] = Bu1;
767 real_t (*Bjn0)[max_Q1D] = Bdu0;
768 real_t (*Bjn1)[max_Q1D] = Bdu1;
769 real_t (*Gj0)[max_Q1D] = Gu0;
770 real_t (*Gj1)[max_Q1D] = Gu1;
776 MFEM_FOREACH_THREAD(side, z, 2)
778 real_t (*
u)[max_Q1D] = (side == 0) ? u0 : u1;
779 real_t (*du)[max_Q1D] = (side == 0) ? du0 : du1;
781 MFEM_FOREACH_THREAD(d2, x, D1D)
783 MFEM_FOREACH_THREAD(d1, y, D1D)
785 u[d2][d1] = x(d1, d2, side,
f);
786 du[d2][d1] = dxdn(d1, d2, side,
f);
790 MFEM_FOREACH_THREAD(p1, x, Q1D)
792 MFEM_FOREACH_THREAD(p2, y, Q1D)
794 for (
int l=0; l < 3; ++l)
796 nJe[side][p2][p1][l] = pa(3*side + l, p1, p2,
f);
801 kappa_Qh[p2][p1] = pa(6, p1, p2,
f);
808 MFEM_FOREACH_THREAD(
p, x, Q1D)
810 MFEM_FOREACH_THREAD(d, y, D1D)
821 MFEM_FOREACH_THREAD(side, z, 2)
823 real_t (*
u)[max_Q1D] = (side == 0) ? u0 : u1;
824 real_t (*du)[max_Q1D] = (side == 0) ? du0 : du1;
825 real_t (*Bu)[max_Q1D] = (side == 0) ? Bu0 : Bu1;
826 real_t (*Bdu)[max_Q1D] = (side == 0) ? Bdu0 : Bdu1;
827 real_t (*Gu)[max_Q1D] = (side == 0) ? Gu0 : Gu1;
829 MFEM_FOREACH_THREAD(p1, x, Q1D)
831 MFEM_FOREACH_THREAD(d2, y, D1D)
837 for (
int d1=0; d1 < D1D; ++d1)
840 const real_t g = G(p1, d1);
843 bdu +=
b * du[d2][d1];
855 MFEM_FOREACH_THREAD(side, z, 2)
857 real_t (*
u)[max_Q1D] = (side == 0) ? u0 : u1;
858 real_t (*du)[max_Q1D] = (side == 0) ? du0 : du1;
859 real_t (*Bu)[max_Q1D] = (side == 0) ? Bu0 : Bu1;
860 real_t (*Gu)[max_Q1D] = (side == 0) ? Gu0 : Gu1;
861 real_t (*Bdu)[max_Q1D] = (side == 0) ? Bdu0 : Bdu1;
863 MFEM_FOREACH_THREAD(p2, x, Q1D)
865 MFEM_FOREACH_THREAD(p1, y, Q1D)
867 const real_t * Je = nJe[side][p2][p1];
874 for (
int d2 = 0; d2 < D1D; ++d2)
877 const real_t g = G(p2, d2);
878 bbu +=
b * Bu[p1][d2];
879 gbu += g * Bu[p1][d2];
880 bgu +=
b * Gu[p1][d2];
881 bbdu +=
b * Bdu[p1][d2];
886 du[p2][p1] = Je[0] * bbdu + Je[1] * bgu + Je[2] * gbu;
892 MFEM_FOREACH_THREAD(side, z, 2)
894 real_t (*Bj)[max_Q1D] = (side == 0) ? Bj0 : Bj1;
895 real_t (*Bjn)[max_Q1D] = (side == 0) ? Bjn0 : Bjn1;
896 real_t (*Gj)[max_Q1D] = (side == 0) ? Gj0 : Gj1;
898 MFEM_FOREACH_THREAD(d1, x, D1D)
900 MFEM_FOREACH_THREAD(p2, y, Q1D)
907 for (
int p1 = 0; p1 < Q1D; ++p1)
910 const real_t g = G(p1, d1);
912 const real_t * Je = nJe[side][p2][p1];
914 const real_t jump = u0[p2][p1] - u1[p2][p1];
915 const real_t avg = du0[p2][p1] + du1[p2][p1];
918 const real_t r = -avg + kappa_Qh[p2][p1] * jump;
921 bj +=
b * Je[0] * jump;
922 gj += g * Je[1] * jump;
923 bjn +=
b * Je[2] * jump;
928 Bj[d1][p2] =
sigma * bj;
929 Bjn[d1][p2] =
sigma * bjn;
933 const real_t sgn = (side == 0) ? 1.0 : -1.0;
934 Gj[d1][p2] = sgn * br +
sigma * gj;
940 MFEM_FOREACH_THREAD(side, z, 2)
942 real_t (*
u)[max_Q1D] = (side == 0) ? u0 : u1;
943 real_t (*du)[max_Q1D] = (side == 0) ? du0 : du1;
944 real_t (*Bj)[max_Q1D] = (side == 0) ? Bj0 : Bj1;
945 real_t (*Bjn)[max_Q1D] = (side == 0) ? Bjn0 : Bjn1;
946 real_t (*Gj)[max_Q1D] = (side == 0) ? Gj0 : Gj1;
948 MFEM_FOREACH_THREAD(d2, x, D1D)
950 MFEM_FOREACH_THREAD(d1, y, D1D)
956 for (
int p2 = 0; p2 < Q1D; ++p2)
959 const real_t g = G(p2, d2);
961 bbj +=
b * Bj[d1][p2];
962 bgj +=
b * Gj[d1][p2];
963 gbj += g * Bjn[d1][p2];
967 u[d2][d1] = bgj + gbj;
974 MFEM_FOREACH_THREAD(side, z, 2)
976 const real_t (*
u)[max_Q1D] = (side == 0) ? u0 : u1;
977 const real_t (*du)[max_Q1D] = (side == 0) ? du0 : du1;
979 MFEM_FOREACH_THREAD(d2, x, D1D)
981 MFEM_FOREACH_THREAD(d1, y, D1D)
983 y(d1, d2, side,
f) +=
u[d2][d1];
984 dydn(d1, d2, side,
f) += du[d2][d1];
991static void PADGDiffusionApply(
const int dim,
995 const Array<real_t> &B,
996 const Array<real_t> &Bt,
997 const Array<real_t> &G,
998 const Array<real_t> &Gt,
1000 const Vector &pa_data,
1008 auto kernel = PADGDiffusionApply2D<0,0>;
1009 switch ((D1D << 4 ) | Q1D)
1011 case 0x23: kernel = PADGDiffusionApply2D<2,3>;
break;
1012 case 0x34: kernel = PADGDiffusionApply2D<3,4>;
break;
1013 case 0x45: kernel = PADGDiffusionApply2D<4,5>;
break;
1014 case 0x56: kernel = PADGDiffusionApply2D<5,6>;
break;
1015 case 0x67: kernel = PADGDiffusionApply2D<6,7>;
break;
1016 case 0x78: kernel = PADGDiffusionApply2D<7,8>;
break;
1017 case 0x89: kernel = PADGDiffusionApply2D<8,9>;
break;
1018 case 0x9A: kernel = PADGDiffusionApply2D<9,10>;
break;
1020 kernel(NF, B, Bt, G, Gt,
sigma, pa_data, x, dxdn, y, dydn, D1D, Q1D);
1024 auto kernel = PADGDiffusionApply3D<0,0>;
1025 switch ((D1D << 4) | Q1D)
1027 case 0x24: kernel = PADGDiffusionApply3D<2,4>;
break;
1028 case 0x35: kernel = PADGDiffusionApply3D<3,5>;
break;
1029 case 0x46: kernel = PADGDiffusionApply3D<4,6>;
break;
1030 case 0x57: kernel = PADGDiffusionApply3D<5,7>;
break;
1031 case 0x68: kernel = PADGDiffusionApply3D<6,8>;
break;
1032 case 0x79: kernel = PADGDiffusionApply3D<7,9>;
break;
1033 case 0x8A: kernel = PADGDiffusionApply3D<8,10>;
break;
1034 case 0x9B: kernel = PADGDiffusionApply3D<9,11>;
break;
1036 kernel(NF, B, Bt, G, Gt,
sigma, pa_data, x, dxdn, y, dydn, D1D, Q1D);
1040 MFEM_ABORT(
"Unsupported dimension");
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
void AssemblePAInteriorFaces(const FiniteElementSpace &fes) override
const IntegrationRule & GetRule(int order, FaceElementTransformations &T)
void AddMultPAFaceNormalDerivatives(const Vector &x, const Vector &dxdn, Vector &y, Vector &dydn) const override
Method for partially assembled action.
void AssemblePABoundaryFaces(const FiniteElementSpace &fes) override
const DofToQuad * maps
Not owned.
A basic generic Tensor class, appropriate for use on the GPU.
static MemoryType GetMemoryType()
(DEPRECATED) Equivalent to GetDeviceMemoryType().
static MemoryType GetDeviceMemoryType()
Get the current Device MemoryType. This is the MemoryType used by most MFEM classes when allocating m...
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.
Array< real_t > Gt
Transpose of G.
int nqpt
Number of quadrature points. When mode is TENSOR, this is the 1D number.
Array< real_t > Bt
Transpose of B.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
int GetOrder() const
Returns the order of the integration rule.
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
const IntegrationRule * IntRule
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.
real_t sigma(const Vector &x)
const T * Read(const Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for read access to mem with the mfem::Device's DeviceMemoryClass, if on_dev = true,...
real_t u(const Vector &xvec)
DeviceTensor< 2, real_t > DeviceMatrix
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
void SignedFaceNormalPermutation(int perm[3], const int face_id1, const int face_id2, const int orientation)
void FaceNormalPermutation(int perm[3], const int face_id)
@ COMPRESSED
Enable all above compressions.
void forall_2D(int N, int X, int Y, lambda &&body)
void forall_3D(int N, int X, int Y, int Z, lambda &&body)
MemoryType
Memory types supported by MFEM.
std::function< real_t(const Vector &)> f(real_t mass_coeff)
void forall(int N, lambda &&body)
real_t p(const Vector &x, real_t t)
static const DeviceDofQuadLimits & Get()
Return a const reference to the DeviceDofQuadLimits singleton.