22static void GetSigns(
const FiniteElementSpace &fes,
const FaceType type,
25 const Mesh &mesh = *fes.GetMesh();
26 const int dim = mesh.SpaceDimension();
29 for (
int f = 0;
f < mesh.GetNumFacesWithGhost(); ++
f)
31 Mesh::FaceInformation face = mesh.GetFaceInformation(
f);
32 face_id = face.element[0].local_face_id;
33 if (face.IsNonconformingCoarse())
39 else if ( face.IsOfFaceType(type) )
43 if (face_id==2 || face_id==3)
54 if (face_id==0 || face_id==3 || face_id==4)
71 : type(type_), nf(fes.GetNFbyType(type)), signs(nf),
79 GetSigns(*
fespace, type, signs);
85 MFEM_VERIFY(sfe != NULL,
"Only scalar finite elements are supported");
86 MFEM_VERIFY(tfe != NULL &&
89 "Only Gauss-Lobatto and Bernstein basis are supported in "
90 "FaceQuadratureInterpolator.");
93template<const
int T_VDIM, const
int T_ND1D, const
int T_NQ1D>
105 const int eval_flags)
107 const int nd1d = maps.
ndof;
108 const int nq1d = maps.
nqpt;
109 const int ND1D = T_ND1D ? T_ND1D : nd1d;
110 const int NQ1D = T_NQ1D ? T_NQ1D : nq1d;
111 const int VDIM = T_VDIM ? T_VDIM : vdim;
114 MFEM_VERIFY(VDIM == 2 || !(eval_flags &
DETERMINANTS),
"");
118 auto sign = signs.
Read();
128 "Derivatives on the faces are not yet supported.");
132 const int ND1D = T_ND1D ? T_ND1D : nd1d;
133 const int NQ1D = T_NQ1D ? T_NQ1D : nq1d;
134 const int VDIM = T_VDIM ? T_VDIM : vdim;
135 constexpr int max_ND1D = T_ND1D ? T_ND1D :
MAX_ND1D;
136 constexpr int max_VDIM = T_VDIM ? T_VDIM :
MAX_VDIM2D;
137 real_t r_F[max_ND1D][max_VDIM];
138 for (
int d = 0; d < ND1D; d++)
140 for (
int c = 0; c < VDIM; c++)
142 r_F[d][c] = F(d,c,
f);
145 for (
int q = 0; q < NQ1D; ++q)
150 for (
int c = 0; c < VDIM; c++) { ed[c] = 0.0; }
151 for (
int d = 0; d < ND1D; ++d)
154 for (
int c = 0; c < VDIM; c++) { ed[c] +=
b*r_F[d][c]; }
156 for (
int c = 0; c < VDIM; c++)
167 for (
int i = 0; i < VDIM; i++) { D[i] = 0.0; }
168 for (
int d = 0; d < ND1D; ++d)
171 for (
int c = 0; c < VDIM; c++)
181 const real_t norm = sqrt(D[0]*D[0]+D[1]*D[1]);
188 const real_t s = sign[
f] ? -1.0 : 1.0;
191 n(0,q,
f) =
s*D[1]/norm;
192 n(1,q,
f) = -
s*D[0]/norm;
196 n(q,0,
f) =
s*D[1]/norm;
197 n(q,1,
f) = -
s*D[0]/norm;
206template<const
int T_VDIM, const
int T_ND1D, const
int T_NQ1D>
218 const int eval_flags)
220 const int nd1d = maps.
ndof;
221 const int nq1d = maps.
nqpt;
222 const int ND1D = T_ND1D ? T_ND1D : nd1d;
223 const int NQ1D = T_NQ1D ? T_NQ1D : nq1d;
224 const int VDIM = T_VDIM ? T_VDIM : vdim;
227 MFEM_VERIFY(VDIM == 3 || !(eval_flags &
DETERMINANTS),
"");
230 auto F =
Reshape(e_vec.
Read(), ND1D, ND1D, VDIM, NF);
231 auto sign = signs.
Read();
241 "Derivatives on the faces are not yet supported.");
244 constexpr int max_ND1D = T_ND1D ? T_ND1D :
MAX_ND1D;
245 constexpr int max_NQ1D = T_NQ1D ? T_NQ1D :
MAX_NQ1D;
246 constexpr int max_VDIM = T_VDIM ? T_VDIM :
MAX_VDIM3D;
247 real_t r_F[max_ND1D][max_ND1D][max_VDIM];
248 for (
int d1 = 0; d1 < ND1D; d1++)
250 for (
int d2 = 0; d2 < ND1D; d2++)
252 for (
int c = 0; c < VDIM; c++)
254 r_F[d1][d2][c] = F(d1,d2,c,
f);
260 real_t Bu[max_NQ1D][max_ND1D][max_VDIM];
261 for (
int d2 = 0; d2 < ND1D; ++d2)
263 for (
int q = 0; q < NQ1D; ++q)
265 for (
int c = 0; c < VDIM; c++) { Bu[q][d2][c] = 0.0; }
266 for (
int d1 = 0; d1 < ND1D; ++d1)
269 for (
int c = 0; c < VDIM; c++)
271 Bu[q][d2][c] +=
b*r_F[d1][d2][c];
276 real_t BBu[max_NQ1D][max_NQ1D][max_VDIM];
277 for (
int q2 = 0; q2 < NQ1D; ++q2)
279 for (
int q1 = 0; q1 < NQ1D; ++q1)
281 for (
int c = 0; c < VDIM; c++) { BBu[q2][q1][c] = 0.0; }
282 for (
int d2 = 0; d2 < ND1D; ++d2)
285 for (
int c = 0; c < VDIM; c++)
287 BBu[q2][q1][c] +=
b*Bu[q1][d2][c];
290 for (
int c = 0; c < VDIM; c++)
292 const real_t v = BBu[q2][q1][c];
304 real_t Gu[max_NQ1D][max_ND1D][max_VDIM];
305 real_t Bu[max_NQ1D][max_ND1D][max_VDIM];
306 for (
int d2 = 0; d2 < ND1D; ++d2)
308 for (
int q = 0; q < NQ1D; ++q)
310 for (
int c = 0; c < VDIM; c++)
315 for (
int d1 = 0; d1 < ND1D; ++d1)
319 for (
int c = 0; c < VDIM; c++)
321 const real_t u = r_F[d1][d2][c];
328 real_t BGu[max_NQ1D][max_NQ1D][max_VDIM];
329 real_t GBu[max_NQ1D][max_NQ1D][max_VDIM];
330 for (
int q2 = 0; q2 < NQ1D; ++q2)
332 for (
int q1 = 0; q1 < NQ1D; ++q1)
334 for (
int c = 0; c < VDIM; c++)
336 BGu[q2][q1][c] = 0.0;
337 GBu[q2][q1][c] = 0.0;
339 for (
int d2 = 0; d2 < ND1D; ++d2)
342 const real_t g = G(q2,d2);
343 for (
int c = 0; c < VDIM; c++)
345 BGu[q2][q1][c] +=
b*Gu[q1][d2][c];
346 GBu[q2][q1][c] += g*Bu[q1][d2][c];
351 if (VDIM == 3 && ((eval_flags &
NORMALS) ||
355 for (
int q2 = 0; q2 < NQ1D; ++q2)
357 for (
int q1 = 0; q1 < NQ1D; ++q1)
359 const real_t s = sign[
f] ? -1.0 : 1.0;
360 n[0] =
s*( BGu[q2][q1][1]*GBu[q2][q1][2]-GBu[q2][q1][1]*
362 n[1] =
s*(-BGu[q2][q1][0]*GBu[q2][q1][2]+GBu[q2][q1][0]*
364 n[2] =
s*( BGu[q2][q1][0]*GBu[q2][q1][1]-GBu[q2][q1][0]*
366 const real_t norm = sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);
372 nor(0,q1,q2,
f) = n[0]/norm;
373 nor(1,q1,q2,
f) = n[1]/norm;
374 nor(2,q1,q2,
f) = n[2]/norm;
378 nor(q1,q2,0,
f) = n[0]/norm;
379 nor(q1,q2,1,
f) = n[1]/norm;
380 nor(q1,q2,2,
f) = n[2]/norm;
390template<const
int T_VDIM, const
int T_ND1D, const
int T_NQ1D>
402 const int eval_flags)
404 MFEM_PERF_SCOPE(
"FaceQuadInterpolator::SmemEval3D");
405 const int nd1d = maps.
ndof;
406 const int nq1d = maps.
nqpt;
407 const int ND1D = T_ND1D ? T_ND1D : nd1d;
408 const int NQ1D = T_NQ1D ? T_NQ1D : nq1d;
409 const int VDIM = T_VDIM ? T_VDIM : vdim;
412 MFEM_VERIFY(VDIM == 3 || !(eval_flags &
DETERMINANTS),
"");
415 auto F =
Reshape(e_vec.
Read(), ND1D, ND1D, VDIM, NF);
416 auto sign = signs.
Read();
426 "Derivatives on the faces are not yet supported.");
430 constexpr int max_ND1D = T_ND1D ? T_ND1D :
MAX_ND1D;
431 constexpr int max_NQ1D = T_NQ1D ? T_NQ1D :
MAX_NQ1D;
432 constexpr int max_VDIM = T_VDIM ? T_VDIM :
MAX_VDIM3D;
434 MFEM_SHARED
real_t sm1[max_NQ1D*max_NQ1D*max_VDIM];
435 MFEM_SHARED
real_t sm2[max_NQ1D*max_ND1D*max_VDIM];
437 auto s_F = (
real_t(*)[max_ND1D][max_VDIM])sm1;
438 MFEM_FOREACH_THREAD(d1,x,ND1D)
440 MFEM_FOREACH_THREAD(d2,y,ND1D)
442 MFEM_FOREACH_THREAD(c,z,VDIM)
444 s_F[d1][d2][c] = F(d1,d2,c,
f);
452 auto Bu = (
real_t (*)[max_ND1D][max_VDIM])sm2;
453 MFEM_FOREACH_THREAD(d2,x,ND1D)
455 MFEM_FOREACH_THREAD(q1,y,NQ1D)
457 MFEM_FOREACH_THREAD(c,z,VDIM)
460 for (
int d1 = 0; d1 < ND1D; ++d1)
462 thrdBu += B(q1,d1)*s_F[d1][d2][c];
464 Bu[q1][d2][c] = thrdBu;
470 MFEM_FOREACH_THREAD(q2,x,NQ1D)
472 MFEM_FOREACH_THREAD(q1,y,NQ1D)
474 MFEM_FOREACH_THREAD(c,z,VDIM)
477 for (
int d2 = 0; d2 < ND1D; ++d2)
479 v += B(q2,d2)*Bu[q1][d2][c];
493 auto Gu = (
real_t (*)[max_ND1D][max_VDIM])sm2;
494 MFEM_SHARED
real_t Bu[max_NQ1D][max_ND1D][max_VDIM];
495 MFEM_FOREACH_THREAD(d2,x,ND1D)
497 MFEM_FOREACH_THREAD(q1,y,NQ1D)
499 MFEM_FOREACH_THREAD(c,z,VDIM)
503 for (
int d1 = 0; d1 < ND1D; ++d1)
505 const real_t u = s_F[d1][d2][c];
506 thrdBu += B(q1,d1)*
u;
507 thrdGu += G(q1,d1)*
u;
509 Gu[q1][d2][c] = thrdGu;
510 Bu[q1][d2][c] = thrdBu;
516 auto BGu = (
real_t (*)[max_NQ1D][max_VDIM])sm1;
517 MFEM_SHARED
real_t GBu[max_NQ1D][max_NQ1D][max_VDIM];
518 MFEM_FOREACH_THREAD(q2,x,NQ1D)
520 MFEM_FOREACH_THREAD(q1,y,NQ1D)
522 MFEM_FOREACH_THREAD(c,z,VDIM)
526 for (
int d2 = 0; d2 < ND1D; ++d2)
528 thrdBGu += B(q2,d2)*Gu[q1][d2][c];
529 thrdGBu += G(q2,d2)*Bu[q1][d2][c];
531 BGu[q2][q1][c] = thrdBGu;
532 GBu[q2][q1][c] = thrdGBu;
538 if (VDIM == 3 && ((eval_flags &
NORMALS) ||
542 MFEM_FOREACH_THREAD(q2,x,NQ1D)
544 MFEM_FOREACH_THREAD(q1,y,NQ1D)
546 if (MFEM_THREAD_ID(z) == 0)
548 const real_t s = sign[
f] ? -1.0 : 1.0;
549 n[0] =
s*( BGu[q2][q1][1]*GBu[q2][q1][2]-GBu[q2][q1][1]*
551 n[1] =
s*(-BGu[q2][q1][0]*GBu[q2][q1][2]+GBu[q2][q1][0]*
553 n[2] =
s*( BGu[q2][q1][0]*GBu[q2][q1][1]-GBu[q2][q1][0]*
556 const real_t norm = sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);
564 nor(0,q1,q2,
f) = n[0]/norm;
565 nor(1,q1,q2,
f) = n[1]/norm;
566 nor(2,q1,q2,
f) = n[2]/norm;
570 nor(q1,q2,0,
f) = n[0]/norm;
571 nor(q1,q2,1,
f) = n[1]/norm;
572 nor(q1,q2,2,
f) = n[2]/norm;
584 const Vector &e_vec,
unsigned eval_flags,
587 if (nf == 0) {
return; }
594 const int nd1d = maps.
ndof;
595 const int nq1d = maps.
nqpt;
607 const int eval_flags) = NULL;
612 switch (10*nd1d + nq1d)
633 if (nq1d >= 10 || !eval_func)
640 switch (10*nd1d + nq1d)
660 if (nq1d >= 10 || !eval_func)
666 else if (vdim ==
dim)
670 switch (10*nd1d + nq1d)
688 if (nq1d >= 10 || !eval_func)
695 switch (10*nd1d + nq1d)
712 if (nq1d >= 10 || !eval_func)
720 eval_func(nf, vdim,
q_layout, maps, signs, e_vec,
721 q_val, q_der, q_det, q_nor, eval_flags);
725 MFEM_ABORT(
"case not supported yet");
732 Vector q_der, q_det, q_nor;
733 Mult(e_vec,
VALUES, q_val, q_der, q_det, q_nor);
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
@ GaussLobatto
Closed type.
@ Positive
Bernstein polynomials.
Structure representing the matrices/tensors needed to evaluate (in reference space) the values,...
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.
int nqpt
Number of quadrature points. When mode is TENSOR, this is the 1D number.
@ DERIVATIVES
Evaluate the derivatives at quadrature points.
@ DETERMINANTS
Assuming the derivative at quadrature points form a matrix, this flag can be used to compute and stor...
@ VALUES
Evaluate the values at quadrature points.
void Values(const Vector &e_vec, Vector &q_val) const
Interpolate the values of the E-vector e_vec at quadrature points.
static const int MAX_VDIM2D
const FiniteElementSpace * fespace
Not owned.
static const int MAX_NQ1D
static void Eval3D(const int NF, const int vdim, const QVectorLayout q_layout, const DofToQuad &maps, const Array< bool > &signs, const Vector &e_vec, Vector &q_val, Vector &q_der, Vector &q_det, Vector &q_nor, const int eval_flags)
Template compute kernel for 3D.
FaceQuadratureInterpolator(const FiniteElementSpace &fes, const IntegrationRule &ir, FaceType type)
QVectorLayout q_layout
Output Q-vector layout.
static const int MAX_VDIM3D
void Mult(const Vector &e_vec, unsigned eval_flags, Vector &q_val, Vector &q_der, Vector &q_det, Vector &q_nor) const
Interpolate the E-vector e_vec to quadrature points.
const IntegrationRule * IntRule
Not owned.
static void SmemEval3D(const int NF, const int vdim, const QVectorLayout q_layout, const DofToQuad &maps, const Array< bool > &signs, const Vector &e_vec, Vector &q_val, Vector &q_der, Vector &q_det, Vector &q_nor, const int eval_flags)
static void Eval2D(const int NF, const int vdim, const QVectorLayout q_layout, const DofToQuad &maps, const Array< bool > &signs, const Vector &e_vec, Vector &q_val, Vector &q_der, Vector &q_det, Vector &q_nor, const int eval_flags)
Template compute kernel for 2D.
static const int MAX_ND1D
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
int GetNE() const
Returns number of elements in the mesh.
const FiniteElement * GetTraceElement(int i, Geometry::Type geom_type) const
Return the trace element from element 'i' to the given 'geom_type'.
Mesh * GetMesh() const
Returns the mesh.
int GetVDim() const
Returns vector dimension.
Abstract class for all finite elements.
virtual const DofToQuad & GetDofToQuad(const IntegrationRule &ir, DofToQuad::Mode mode) const
Return a DofToQuad structure corresponding to the given IntegrationRule using the given DofToQuad::Mo...
Class for an integration rule - an Array of IntegrationPoint.
Geometry::Type GetFaceGeometry(int i) const
Return the Geometry::Type associated with face i.
int Dimension() const
Dimension of the reference space used within the elements.
Class for finite elements with basis functions that return scalar values.
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
virtual real_t * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
real_t u(const Vector &xvec)
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
std::function< void(const Vector &, Vector &)> f_vec(bool grad_div_problem)
void forall_3D(int N, int X, int Y, int Z, lambda &&body)
QVectorLayout
Type describing possible layouts for Q-vectors.
@ byNODES
NQPT x VDIM x NE (values) / NQPT x VDIM x DIM x NE (grads)
@ byVDIM
VDIM x NQPT x NE (values) / VDIM x DIM x NQPT x NE (grads)
std::function< real_t(const Vector &)> f(real_t mass_coeff)
void forall(int N, lambda &&body)