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.