23static void PADGDiffusionSetup2D(
const int Q1D,
const int NE,
const int NF,
24 const Array<real_t> &w,
25 const GeometricFactors &el_geom,
26 const FaceGeometricFactors &face_geom,
27 const FaceNeighborGeometricFactors *nbr_geom,
28 const Vector &q,
const int coeff_dim,
30 Vector &pa_data,
const Array<int> &face_info_)
32 const auto J_loc =
Reshape(el_geom.J.Read(), Q1D, Q1D, 2, 2, NE);
33 const auto detJe_loc =
Reshape(el_geom.detJ.Read(), Q1D, Q1D, NE);
35 const int n_nbr = nbr_geom ? nbr_geom->num_neighbor_elems : 0;
37 Reshape(nbr_geom ? nbr_geom->J.Read() : nullptr, Q1D, Q1D, 2, 2, n_nbr);
38 const auto detJ_shared =
39 Reshape(nbr_geom ? nbr_geom->detJ.Read() : nullptr, Q1D, Q1D, n_nbr);
41 const auto detJf =
Reshape(face_geom.detJ.Read(), Q1D, NF);
42 const auto n =
Reshape(face_geom.normal.Read(), Q1D, 2, NF);
44 const bool const_q = (q.Size() == coeff_dim);
45 const auto Q = const_q ?
Reshape(q.Read(), coeff_dim, 1, 1)
48 const auto W = w.Read();
51 const auto face_info =
Reshape(face_info_.Read(), 6, NF);
54 auto pa =
Reshape(pa_data.Write(), 6, Q1D, NF);
56 auto get_coeff = [const_q] MFEM_HOST_DEVICE (
const decltype(Q) &Q,
int i,
59 return const_q ? Q(i,0,0) : Q(i,qx,e);
64 const int normal_dir[] = {face_info(0,
f), face_info(1,
f)};
65 const int fid[] = {face_info(4,
f), face_info(5,
f)};
67 int el[] = {face_info(2,
f), face_info(3,
f)};
68 const bool interior = el[1] >= 0;
69 const int nsides = (interior) ? 2 : 1;
70 const real_t factor = interior ? 0.5 : 1.0;
72 const bool shared = el[1] >= NE;
73 el[1] = shared ? el[1] - NE : el[1];
75 const int sgn0 = (fid[0] == 0 || fid[0] == 1) ? 1 : -1;
76 const int sgn1 = (fid[1] == 0 || fid[1] == 1) ? 1 : -1;
78 for (
int p = 0;
p < Q1D; ++
p)
87 Qtn[0] = get_coeff(Q,0,
p,
f)*n(
p,0,
f) + get_coeff(Q,1,
p,
f)*n(
p,1,
f);
88 Qtn[1] = get_coeff(Q,2,
p,
f)*n(
p,0,
f) + get_coeff(Q,3,
p,
f)*n(
p,1,
f);
89 qh = Qtn[0]*n(
p,0,
f) + Qtn[1]*n(
p,1,
f);
93 qh = get_coeff(Q, 0,
p,
f);
100 for (
int side = 0; side < nsides; ++side)
103 internal::FaceIdxToVolIdx2D(
p, Q1D, fid[0], fid[1], side, i, j);
107 const int sgn = (side == 1) ? -1 * sgn0 * sgn1 : 1;
109 const int e = el[side];
110 const auto &J = (side == 1 && shared) ? J_shared : J_loc;
111 const auto &detJ = (side == 1 && shared) ? detJ_shared : detJe_loc;
114 nJi[0] = Qtn[0]*J(i, j, 1, 1, e) - Qtn[1]*J(i, j, 0, 1, e);
115 nJi[1] = -Qtn[0]*J(i, j, 1, 0, e) + Qtn[1]*J(i, j, 0, 0, e);
117 const real_t dJe = detJ(i, j, e);
120 const real_t w = factor * W[
p] * dJf / dJe;
122 const int ni = normal_dir[side];
123 const int ti = 1 - ni;
126 pa(2 + 2 * side + 0,
p,
f) = w * nJi[ni];
128 pa(2 + 2 * side + 1,
p,
f) = sgn * w * nJi[ti];
130 hi += factor * dJf / dJe;
144static void PADGDiffusionSetup3D(
const int Q1D,
const int NE,
const int NF,
145 const Array<real_t> &w,
146 const GeometricFactors &el_geom,
147 const FaceGeometricFactors &face_geom,
148 const FaceNeighborGeometricFactors *nbr_geom,
149 const Vector &q,
const int coeff_dim,
151 Vector &pa_data,
const Array<int> &face_info_)
153 const auto J_loc =
Reshape(el_geom.J.Read(), Q1D, Q1D, Q1D, 3, 3, NE);
154 const auto detJe_loc =
Reshape(el_geom.detJ.Read(), Q1D, Q1D, Q1D, NE);
156 const int n_nbr = nbr_geom ? nbr_geom->num_neighbor_elems : 0;
157 const auto J_shared =
Reshape(nbr_geom ? nbr_geom->J.Read() : nullptr, Q1D,
158 Q1D, Q1D, 3, 3, n_nbr);
159 const auto detJ_shared =
160 Reshape(nbr_geom ? nbr_geom->detJ.Read() : nullptr, Q1D, Q1D, Q1D, n_nbr);
162 const auto detJf =
Reshape(face_geom.detJ.Read(), Q1D, Q1D, NF);
163 const auto n =
Reshape(face_geom.normal.Read(), Q1D, Q1D, 3, NF);
165 const bool const_q = (q.Size() == coeff_dim);
166 const auto Q = const_q ?
Reshape(q.Read(), coeff_dim, 1, 1, 1)
169 const auto W =
Reshape(w.Read(), Q1D, Q1D);
172 const auto face_info =
Reshape(face_info_.Read(), 6, 2, NF);
173 constexpr int _el_ = 3;
174 constexpr int _fid_ = 4;
175 constexpr int _or_ = 5;
178 const auto pa =
Reshape(pa_data.Write(), 7, Q1D, Q1D, NF);
180 auto get_coeff = [const_q] MFEM_HOST_DEVICE (
const decltype(Q) &Q,
int i,
181 int qx,
int qy,
int e)
183 return const_q ? Q(i,0,0,0) : Q(i,qx,qy,e);
188 MFEM_SHARED
int perm[2][3];
189 MFEM_SHARED
int el[2];
190 MFEM_SHARED
bool shared[2];
191 MFEM_SHARED
int fid[2];
192 MFEM_SHARED
int ortn[2];
194 MFEM_FOREACH_THREAD(side, x, 2)
196 MFEM_FOREACH_THREAD(i, y, 3) { perm[side][i] = face_info(i, side,
f); }
198 if (MFEM_THREAD_ID(y) == 0)
200 el[side] = face_info(_el_, side,
f);
201 fid[side] = face_info(_fid_, side,
f);
202 ortn[side] = face_info(_or_, side,
f);
206 shared[side] = (el[side] >= NE);
207 el[side] = shared[side] ? el[side] - NE : el[side];
213 const bool interior = el[1] >= 0;
214 const int nsides = interior ? 2 : 1;
215 const real_t factor = interior ? 0.5 : 1.0;
217 MFEM_FOREACH_THREAD(p1, x, Q1D)
219 MFEM_FOREACH_THREAD(p2, y, Q1D)
221 const real_t dJf = detJf(p1, p2,
f);
231 for (
int d = 0; d < 3; ++d)
233 Qtn[d] = get_coeff(Q,0+3*d,p1,p2,
f)*n(p1,p2,0,
f)
234 + get_coeff(Q,1+3*d,p1,p2,
f)*n(p1,p2,1,
f)
235 + get_coeff(Q,2+3*d,p1,p2,
f)*n(p1,p2,2,
f);
236 qh += Qtn[d] * n(p1,p2,d,
f);
241 qh = get_coeff(Q,0,p1,p2,
f);
242 Qtn[0] = qh * n(p1,p2,0,
f);
243 Qtn[1] = qh * n(p1,p2,1,
f);
244 Qtn[2] = qh * n(p1,p2,2,
f);
247 for (
int side = 0; side < nsides; ++side)
250 internal::FaceIdxToVolIdx3D(p1 + Q1D * p2, Q1D, fid[0], fid[1],
251 side, ortn[1], i, j, k);
253 const int e = el[side];
254 const auto &J = shared[side] ? J_shared : J_loc;
255 const auto &detJe = shared[side] ? detJ_shared : detJe_loc;
259 nJi[0] = (-J(i, j, k, 1, 2, e) * J(i, j, k, 2, 1, e) +
260 J(i, j, k, 1, 1, e) * J(i, j, k, 2, 2, e)) * Qtn[0] +
261 (J(i, j, k, 0, 2, e) * J(i, j, k, 2, 1, e) -
262 J(i, j, k, 0, 1, e) * J(i, j, k, 2, 2, e)) * Qtn[1] +
263 (-J(i, j, k, 0, 2, e) * J(i, j, k, 1, 1, e) +
264 J(i, j, k, 0, 1, e) * J(i, j, k, 1, 2, e)) * Qtn[2];
266 nJi[1] = (J(i, j, k, 1, 2, e) * J(i, j, k, 2, 0, e) -
267 J(i, j, k, 1, 0, e) * J(i, j, k, 2, 2, e)) * Qtn[0] +
268 (-J(i, j, k, 0, 2, e) * J(i, j, k, 2, 0, e) +
269 J(i, j, k, 0, 0, e) * J(i, j, k, 2, 2, e)) * Qtn[1] +
270 (J(i, j, k, 0, 2, e) * J(i, j, k, 1, 0, e) -
271 J(i, j, k, 0, 0, e) * J(i, j, k, 1, 2, e)) * Qtn[2];
273 nJi[2] = (-J(i, j, k, 1, 1, e) * J(i, j, k, 2, 0, e) +
274 J(i, j, k, 1, 0, e) * J(i, j, k, 2, 1, e)) * Qtn[0] +
275 (J(i, j, k, 0, 1, e) * J(i, j, k, 2, 0, e) -
276 J(i, j, k, 0, 0, e) * J(i, j, k, 2, 1, e)) * Qtn[1] +
277 (-J(i, j, k, 0, 1, e) * J(i, j, k, 1, 0, e) +
278 J(i, j, k, 0, 0, e) * J(i, j, k, 1, 1, e)) * Qtn[2];
281 const real_t dJe = detJe(i, j, k, e);
282 const real_t val = factor * W(p1, p2) * dJf / dJe;
284 for (
int d = 0; d < 3; ++d)
286 const int idx = std::abs(perm[side][d]) - 1;
287 const int sgn = (perm[side][d] < 0) ? -1 : 1;
288 pa(3 * side + d, p1, p2,
f) = sgn * val * nJi[idx];
291 hi += factor * dJf / dJe;
296 pa(3, p1, p2,
f) = 0.0;
297 pa(4, p1, p2,
f) = 0.0;
298 pa(5, p1, p2,
f) = 0.0;
301 pa(6, p1, p2,
f) =
kappa * hi * qh * W(p1, p2) * dJf;
307static void PADGDiffusionSetupFaceInfo2D(
const int nf,
const Mesh &mesh,
309 Array<int> &face_info_)
311 const int ne = mesh.GetNE();
314 face_info_.SetSize(nf * 6);
321 auto face_info =
Reshape(face_info_.HostWrite(), 6, nf);
322 for (
int f = 0;
f < mesh.GetNumFaces(); ++
f)
324 auto f_info = mesh.GetFaceInformation(
f);
326 if (f_info.IsOfFaceType(type))
328 const int face_id_1 = f_info.element[0].local_face_id;
329 face_info(0, fidx) = (face_id_1 == 1 || face_id_1 == 3) ? 0 : 1;
330 face_info(2, fidx) = f_info.element[0].index;
331 face_info(4, fidx) = face_id_1;
333 if (f_info.IsInterior())
335 const int face_id_2 = f_info.element[1].local_face_id;
336 face_info(1, fidx) = (face_id_2 == 1 || face_id_2 == 3) ? 0 : 1;
337 if (f_info.IsShared())
339 face_info(3, fidx) = ne + f_info.element[1].index;
343 face_info(3, fidx) = f_info.element[1].index;
345 face_info(5, fidx) = face_id_2;
349 face_info(1, fidx) = -1;
350 face_info(3, fidx) = -1;
351 face_info(5, fidx) = -1;
367 const bool xy_plane = (face_id == 0 || face_id == 5);
368 const bool xz_plane = (face_id == 1 || face_id == 3);
371 perm[0] = (xy_plane) ? 3 : (xz_plane) ? 2 : 1;
372 perm[1] = (xy_plane || xz_plane) ? 1 : 2;
373 perm[2] = (xy_plane) ? 2 : 3;
380 const int orientation)
385 if (face_id2 == 3 || face_id2 == 4)
389 else if (face_id2 == 0)
397 std::swap(perm[1], perm[2]);
400 std::swap(perm[1], perm[2]);
411 std::swap(perm[1], perm[2]);
416 std::swap(perm[1], perm[2]);
426 if (face_id1 == 3 || face_id1 == 4)
430 else if (face_id1 == 0)
436static void PADGDiffusionSetupFaceInfo3D(
const int nf,
const Mesh &mesh,
438 Array<int> &face_info_)
440 const int ne = mesh.GetNE();
446 face_info_.SetSize(nf * 12);
447 constexpr int _e_ = 3;
448 constexpr int _fid_ = 4;
449 constexpr int _or_ = 5;
451 auto face_info =
Reshape(face_info_.HostWrite(), 6, 2, nf);
452 for (
int f = 0;
f < mesh.GetNumFaces(); ++
f)
454 auto f_info = mesh.GetFaceInformation(
f);
456 if (f_info.IsOfFaceType(type))
458 const int fid0 = f_info.element[0].local_face_id;
459 const int or0 = f_info.element[0].orientation;
461 face_info(_e_, 0, fidx) = f_info.element[0].index;
462 face_info(_fid_, 0, fidx) = fid0;
463 face_info(_or_, 0, fidx) = or0;
467 if (f_info.IsInterior())
469 const int fid1 = f_info.element[1].local_face_id;
470 const int or1 = f_info.element[1].orientation;
472 if (f_info.IsShared())
474 face_info(_e_, 1, fidx) = ne + f_info.element[1].index;
478 face_info(_e_, 1, fidx) = f_info.element[1].index;
480 face_info(_fid_, 1, fidx) = fid1;
481 face_info(_or_, 1, fidx) = or1;
488 for (
int i = 0; i < 6; ++i)
490 face_info(i, 1, fidx) = -1;
499void DGDiffusionIntegrator::SetupPA(
const FiniteElementSpace &fes,
505 const int ne = fes.GetNE();
506 nf = fes.GetNFbyType(type);
509 Mesh &mesh = *fes.GetMesh();
510 const Geometry::Type face_geom_type = mesh.GetTypicalFaceGeometry();
511 const FiniteElement &el = *fes.GetTypicalTraceElement();
515 const IntegrationRule &ir =
irs.
Get(face_geom_type, ir_order);
516 dim = mesh.Dimension();
517 const int q1d = (ir.GetOrder() + 3) / 2;
518 MFEM_ASSERT(q1d ==
pow(
real_t(ir.Size()), 1.0 / (
dim - 1)),
"");
520 const auto vol_ir =
irs.
Get(mesh.GetTypicalElementGeometry(), ir_order);
521 const auto geom_flags =
523 const auto el_geom = mesh.GetGeometricFactors(vol_ir, geom_flags, mt);
525 std::unique_ptr<FaceNeighborGeometricFactors> nbr_geom;
528 nbr_geom.reset(
new FaceNeighborGeometricFactors(*el_geom));
531 const auto face_geom_flags =
533 auto face_geom = mesh.GetFaceGeometricFactors(ir, face_geom_flags, type, mt);
538 const int pa_size = (
dim == 2) ? (6 * q1d *
nf) : (7 * q1d * q1d *
nf);
542 FaceQuadratureSpace fqs(mesh, ir, type);
544 if (
Q) { q.Project(*
Q); }
545 else if (
MQ) { q.Project(*
MQ); }
546 else { q.SetConstant(1.0); }
548 const int coeff_dim = q.GetVDim();
550 Array<int> face_info;
553 MFEM_ABORT(
"dim==1 not supported in PADGTraceSetup");
557 PADGDiffusionSetupFaceInfo2D(
nf, mesh, type, face_info);
558 PADGDiffusionSetup2D(
quad1D, ne,
nf, ir.GetWeights(), *el_geom,
559 *face_geom, nbr_geom.get(), q, coeff_dim,
sigma,
564 PADGDiffusionSetupFaceInfo3D(
nf, mesh, type, face_info);
565 PADGDiffusionSetup3D(
quad1D, ne,
nf, ir.GetWeights(), *el_geom,
566 *face_geom, nbr_geom.get(), q, coeff_dim,
sigma,
616DGDiffusionIntegrator::ApplyPAKernels::Fallback(
int dim,
int,
int)
620 return internal::PADGDiffusionApply2D;
624 return internal::PADGDiffusionApply3D;
632DGDiffusionIntegrator::Kernels::Kernels()
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
void AssemblePAInteriorFaces(const FiniteElementSpace &fes) override
const IntegrationRule & GetRule(int order, FaceElementTransformations &T)
DGDiffusionIntegrator(const real_t s, const real_t k)
static void AddSpecialization()
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
void(*)(const int, const Array< real_t > &, const Array< real_t > &, const Array< real_t > &, const Array< real_t > &, const real_t, const Vector &, const Vector &_, const Vector &, Vector &, Vector &, const int, const int) ApplyKernelType
const DofToQuad * maps
Not owned.
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
Base class for Matrix Coefficients that optionally depend on time and space.
void SetSize(int s)
Resize the vector to size s.
real_t sigma(const Vector &x)
MFEM_HOST_DEVICE dual< value_type, gradient_type > pow(dual< value_type, gradient_type > a, dual< value_type, gradient_type > b)
implementation of a (dual) raised to the b (dual) power
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,...
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)
@ CONSTANTS
Store constants using only vdim entries.
void forall_2D(int N, int X, int Y, 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)