13 #include "../general/forall.hpp"
14 #include "../linalg/dtensor.hpp"
15 #include "../linalg/kernels.hpp"
21 static void GetSigns(
const FiniteElementSpace &fes,
const FaceType type,
24 const Mesh &mesh = *fes.GetMesh();
25 const int dim = mesh.SpaceDimension();
28 for (
int f = 0;
f < mesh.GetNumFacesWithGhost(); ++
f)
30 Mesh::FaceInformation face = mesh.GetFaceInformation(
f);
31 face_id = face.element[0].local_face_id;
32 if (face.IsNonconformingCoarse())
38 else if ( face.IsOfFaceType(type) )
42 if (face_id==2 || face_id==3)
53 if (face_id==0 || face_id==3 || face_id==4)
70 : type(type_), nf(fes.GetNFbyType(type)), signs(nf)
77 GetSigns(*
fespace, type, signs);
83 MFEM_VERIFY(sfe != NULL,
"Only scalar finite elements are supported");
84 MFEM_VERIFY(tfe != NULL &&
87 "Only Gauss-Lobatto and Bernstein basis are supported in "
88 "FaceQuadratureInterpolator.");
91 template<const
int T_VDIM, const
int T_ND1D, const
int T_NQ1D>
102 const int eval_flags)
104 const int nd1d = maps.
ndof;
105 const int nq1d = maps.
nqpt;
106 const int ND1D = T_ND1D ? T_ND1D : nd1d;
107 const int NQ1D = T_NQ1D ? T_NQ1D : nq1d;
108 const int VDIM = T_VDIM ? T_VDIM : vdim;
111 MFEM_VERIFY(VDIM == 2 || !(eval_flags &
DETERMINANTS),
"");
115 auto sign = signs.
Read();
121 "Derivatives on the faces are not yet supported.");
125 const int ND1D = T_ND1D ? T_ND1D : nd1d;
126 const int NQ1D = T_NQ1D ? T_NQ1D : nq1d;
127 const int VDIM = T_VDIM ? T_VDIM : vdim;
128 constexpr
int max_ND1D = T_ND1D ? T_ND1D :
MAX_ND1D;
129 constexpr
int max_VDIM = T_VDIM ? T_VDIM :
MAX_VDIM2D;
130 double r_F[max_ND1D][max_VDIM];
131 for (
int d = 0; d < ND1D; d++)
133 for (
int c = 0; c < VDIM; c++)
135 r_F[d][c] = F(d,c,
f);
138 for (
int q = 0; q < NQ1D; ++q)
143 for (
int c = 0; c < VDIM; c++) { ed[c] = 0.0; }
144 for (
int d = 0; d < ND1D; ++d)
146 const double b = B(q,d);
147 for (
int c = 0; c < VDIM; c++) { ed[c] += b*r_F[d][c]; }
149 for (
int c = 0; c < VDIM; c++) { val(q,c,
f) = ed[c]; }
152 || (eval_flags & DETERMINANTS)
156 for (
int i = 0; i < VDIM; i++) { D[i] = 0.0; }
157 for (
int d = 0; d < ND1D; ++d)
159 const double w = G(q,d);
160 for (
int c = 0; c < VDIM; c++)
162 double s_e = r_F[d][c];
167 ((eval_flags & NORMALS)
168 || (eval_flags & DETERMINANTS)))
170 const double norm =
sqrt(D[0]*D[0]+D[1]*D[1]);
171 if (eval_flags & DETERMINANTS)
175 if (eval_flags & NORMALS)
177 const double s = sign[
f] ? -1.0 : 1.0;
178 n(q,0,
f) = s*D[1]/norm;
179 n(q,1,
f) = -s*D[0]/norm;
187 template<const
int T_VDIM, const
int T_ND1D, const
int T_NQ1D>
198 const int eval_flags)
200 const int nd1d = maps.
ndof;
201 const int nq1d = maps.
nqpt;
202 const int ND1D = T_ND1D ? T_ND1D : nd1d;
203 const int NQ1D = T_NQ1D ? T_NQ1D : nq1d;
204 const int VDIM = T_VDIM ? T_VDIM : vdim;
207 MFEM_VERIFY(VDIM == 3 || !(eval_flags &
DETERMINANTS),
"");
210 auto F =
Reshape(e_vec.
Read(), ND1D, ND1D, VDIM, NF);
211 auto sign = signs.
Read();
212 auto val =
Reshape(q_val.
Write(), NQ1D, NQ1D, VDIM, NF);
217 "Derivatives on the faces are not yet supported.");
220 const int ND1D = T_ND1D ? T_ND1D : nd1d;
221 const int NQ1D = T_NQ1D ? T_NQ1D : nq1d;
222 const int VDIM = T_VDIM ? T_VDIM : vdim;
223 constexpr
int max_ND1D = T_ND1D ? T_ND1D :
MAX_ND1D;
224 constexpr
int max_NQ1D = T_NQ1D ? T_NQ1D :
MAX_NQ1D;
225 constexpr
int max_VDIM = T_VDIM ? T_VDIM :
MAX_VDIM3D;
226 double r_F[max_ND1D][max_ND1D][max_VDIM];
227 for (
int d1 = 0; d1 < ND1D; d1++)
229 for (
int d2 = 0; d2 < ND1D; d2++)
231 for (
int c = 0; c < VDIM; c++)
233 r_F[d1][d2][c] = F(d1,d2,c,
f);
239 double Bu[max_NQ1D][max_ND1D][max_VDIM];
240 for (
int d2 = 0; d2 < ND1D; ++d2)
242 for (
int q = 0; q < NQ1D; ++q)
244 for (
int c = 0; c < VDIM; c++) { Bu[q][d2][c] = 0.0; }
245 for (
int d1 = 0; d1 < ND1D; ++d1)
247 const double b = B(q,d1);
248 for (
int c = 0; c < VDIM; c++)
250 Bu[q][d2][c] += b*r_F[d1][d2][c];
255 double BBu[max_NQ1D][max_NQ1D][max_VDIM];
256 for (
int q2 = 0; q2 < NQ1D; ++q2)
258 for (
int q1 = 0; q1 < NQ1D; ++q1)
260 for (
int c = 0; c < VDIM; c++) { BBu[q2][q1][c] = 0.0; }
261 for (
int d2 = 0; d2 < ND1D; ++d2)
263 const double b = B(q2,d2);
264 for (
int c = 0; c < VDIM; c++)
266 BBu[q2][q1][c] += b*Bu[q1][d2][c];
269 for (
int c = 0; c < VDIM; c++)
271 val(q1,q2,c,
f) = BBu[q2][q1][c];
277 || (eval_flags & DETERMINANTS)
281 double Gu[max_NQ1D][max_ND1D][max_VDIM];
282 double Bu[max_NQ1D][max_ND1D][max_VDIM];
283 for (
int d2 = 0; d2 < ND1D; ++d2)
285 for (
int q = 0; q < NQ1D; ++q)
287 for (
int c = 0; c < VDIM; c++)
292 for (
int d1 = 0; d1 < ND1D; ++d1)
294 const double b = B(q,d1);
295 const double g = G(q,d1);
296 for (
int c = 0; c < VDIM; c++)
298 const double u = r_F[d1][d2][c];
305 double BGu[max_NQ1D][max_NQ1D][max_VDIM];
306 double GBu[max_NQ1D][max_NQ1D][max_VDIM];
307 for (
int q2 = 0; q2 < NQ1D; ++q2)
309 for (
int q1 = 0; q1 < NQ1D; ++q1)
311 for (
int c = 0; c < VDIM; c++)
313 BGu[q2][q1][c] = 0.0;
314 GBu[q2][q1][c] = 0.0;
316 for (
int d2 = 0; d2 < ND1D; ++d2)
318 const double b = B(q2,d2);
319 const double g = G(q2,d2);
320 for (
int c = 0; c < VDIM; c++)
322 BGu[q2][q1][c] += b*Gu[q1][d2][c];
323 GBu[q2][q1][c] += g*Bu[q1][d2][c];
328 if (VDIM == 3 && ((eval_flags & NORMALS) ||
329 (eval_flags & DETERMINANTS)))
332 for (
int q2 = 0; q2 < NQ1D; ++q2)
334 for (
int q1 = 0; q1 < NQ1D; ++q1)
336 const double s = sign[
f] ? -1.0 : 1.0;
337 n[0] = s*( BGu[q2][q1][1]*GBu[q2][q1][2]-GBu[q2][q1][1]*
339 n[1] = s*(-BGu[q2][q1][0]*GBu[q2][q1][2]+GBu[q2][q1][0]*
341 n[2] = s*( BGu[q2][q1][0]*GBu[q2][q1][1]-GBu[q2][q1][0]*
343 const double norm =
sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);
344 if (eval_flags & DETERMINANTS) { det(q1,q2,
f) = norm; }
345 if (eval_flags & NORMALS)
347 nor(q1,q2,0,
f) = n[0]/norm;
348 nor(q1,q2,1,
f) = n[1]/norm;
349 nor(q1,q2,2,
f) = n[2]/norm;
359 const Vector &e_vec,
unsigned eval_flags,
362 if (nf == 0) {
return; }
369 const int nd1d = maps.
ndof;
370 const int nq1d = maps.
nqpt;
381 const int eval_flags) = NULL;
386 switch (10*nd1d + nq1d)
389 case 11: eval_func = &Eval2D<1,1,1>;
break;
390 case 12: eval_func = &Eval2D<1,1,2>;
break;
392 case 22: eval_func = &Eval2D<1,2,2>;
break;
393 case 23: eval_func = &Eval2D<1,2,3>;
break;
395 case 33: eval_func = &Eval2D<1,3,3>;
break;
396 case 34: eval_func = &Eval2D<1,3,4>;
break;
398 case 44: eval_func = &Eval2D<1,4,4>;
break;
399 case 45: eval_func = &Eval2D<1,4,5>;
break;
400 case 46: eval_func = &Eval2D<1,4,6>;
break;
402 case 55: eval_func = &Eval2D<1,5,5>;
break;
403 case 56: eval_func = &Eval2D<1,5,6>;
break;
404 case 57: eval_func = &Eval2D<1,5,7>;
break;
405 case 58: eval_func = &Eval2D<1,5,8>;
break;
407 if (nq1d >= 10 || !eval_func)
409 eval_func = &Eval2D<1>;
414 switch (10*nd1d + nq1d)
417 case 11: eval_func = &Eval3D<1,1,1>;
break;
418 case 12: eval_func = &Eval3D<1,1,2>;
break;
420 case 22: eval_func = &Eval3D<1,2,2>;
break;
421 case 23: eval_func = &Eval3D<1,2,3>;
break;
423 case 33: eval_func = &Eval3D<1,3,3>;
break;
424 case 34: eval_func = &Eval3D<1,3,4>;
break;
426 case 44: eval_func = &Eval3D<1,4,4>;
break;
427 case 45: eval_func = &Eval3D<1,4,5>;
break;
428 case 46: eval_func = &Eval3D<1,4,6>;
break;
430 case 55: eval_func = &Eval3D<1,5,5>;
break;
431 case 56: eval_func = &Eval3D<1,5,6>;
break;
433 if (nq1d >= 10 || !eval_func)
435 eval_func = &Eval3D<1>;
439 else if (vdim == dim)
443 switch (10*nd1d + nq1d)
446 case 22: eval_func = &Eval2D<2,2,2>;
break;
447 case 23: eval_func = &Eval2D<2,2,3>;
break;
449 case 33: eval_func = &Eval2D<2,3,3>;
break;
450 case 34: eval_func = &Eval2D<2,3,4>;
break;
452 case 44: eval_func = &Eval2D<2,4,4>;
break;
453 case 45: eval_func = &Eval2D<2,4,5>;
break;
454 case 46: eval_func = &Eval2D<2,4,6>;
break;
456 case 55: eval_func = &Eval2D<2,5,5>;
break;
457 case 56: eval_func = &Eval2D<2,5,6>;
break;
458 case 57: eval_func = &Eval2D<2,5,7>;
break;
459 case 58: eval_func = &Eval2D<2,5,8>;
break;
461 if (nq1d >= 10 || !eval_func)
463 eval_func = &Eval2D<2>;
468 switch (10*nd1d + nq1d)
471 case 22: eval_func = &Eval3D<3,2,2>;
break;
472 case 23: eval_func = &Eval3D<3,2,3>;
break;
474 case 33: eval_func = &Eval3D<3,3,3>;
break;
475 case 34: eval_func = &Eval3D<3,3,4>;
break;
477 case 44: eval_func = &Eval3D<3,4,4>;
break;
478 case 45: eval_func = &Eval3D<3,4,5>;
break;
479 case 46: eval_func = &Eval3D<3,4,6>;
break;
481 case 55: eval_func = &Eval3D<3,5,5>;
break;
482 case 56: eval_func = &Eval3D<3,5,6>;
break;
484 if (nq1d >= 10 || !eval_func)
486 eval_func = &Eval3D<3>;
492 eval_func(nf, vdim, maps, signs, e_vec,
493 q_val, q_der, q_det, q_nor, eval_flags);
497 MFEM_ABORT(
"case not supported yet");
504 Vector q_der, q_det, q_nor;
505 Mult(e_vec,
VALUES, q_val, q_der, q_det, q_nor);
Abstract class for all finite elements.
Class for an integration rule - an Array of IntegrationPoint.
static void Eval3D(const int NF, const int vdim, 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.
Tensor product representation using 1D matrices/tensors with dimensions using 1D number of quadrature...
FaceQuadratureInterpolator(const FiniteElementSpace &fes, const IntegrationRule &ir, FaceType type)
const FiniteElement * GetTraceElement(int i, Geometry::Type geom_type) const
Return the trace element from element 'i' to the given 'geom_type'.
int nqpt
Number of quadrature points. When mode is TENSOR, this is the 1D number.
int ndof
Number of degrees of freedom = number of basis functions. When mode is TENSOR, this is the 1D number...
Geometry::Type GetFaceBaseGeometry(int i) const
const IntegrationRule * IntRule
Not owned.
DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims...dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
int GetNE() const
Returns number of elements in the mesh.
Class for finite elements with basis functions that return scalar values.
double f(const Vector &xvec)
static const int MAX_ND1D
Mesh * GetMesh() const
Returns the mesh.
virtual double * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
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 T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
int GetVDim() const
Returns vector dimension.
void Values(const Vector &e_vec, Vector &q_val) const
Interpolate the values of the E-vector e_vec at quadrature points.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Structure representing the matrices/tensors needed to evaluate (in reference space) the values...
static const int MAX_VDIM3D
Evaluate the values at quadrature points.
Array< double > B
Basis functions evaluated at quadrature points.
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...
FDualNumber< tbase > sqrt(const FDualNumber< tbase > &f)
sqrt([dual number])
static const int MAX_NQ1D
Array< double > G
Gradients/divergences/curls of basis functions evaluated at quadrature points.
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
static void Eval2D(const int NF, const int vdim, 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.
Evaluate the derivatives at quadrature points.
void f_vec(const Vector &xvec, Vector &f)
double u(const Vector &xvec)
Assuming the derivative at quadrature points form a matrix, this flag can be used to compute and stor...
const FiniteElementSpace * fespace
Not owned.
static const int MAX_VDIM2D
virtual const double * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).