15 #include "../general/forall.hpp"
24 ndof(ne > 0 ? fes.GetFE(0)->GetDof() : 0),
35 const bool t = byvdim;
36 auto d_x =
Reshape(x.
Read(), t?vd:ndofs, t?ndofs:vd);
41 const int dof = idx % nd;
42 const int e = idx / nd;
43 for (
int c = 0; c < vd; ++c)
45 d_y(dof, c, e) = d_x(t?c:idx, t?idx:c);
54 const bool t = byvdim;
60 const int dof = idx % nd;
61 const int e = idx / nd;
62 for (
int c = 0; c < vd; ++c)
64 d_y(t?c:idx,t?idx:c) = d_x(dof, c, e);
75 ndofs(fes.GetNDofs()),
76 dof(ne > 0 ? fes.GetFE(0)->GetDof() : 0),
86 const int *dof_map = NULL;
87 if (dof_reorder &&
ne > 0)
89 for (
int e = 0; e <
ne; ++e)
95 mfem_error(
"Finite element not suitable for lexicographic ordering");
101 MFEM_VERIFY(fe_dof_map.
Size() > 0,
"invalid dof map");
102 dof_map = fe_dof_map.
GetData();
105 const int* elementMap = e2dTable.
GetJ();
107 for (
int i = 0; i <=
ndofs; ++i)
111 for (
int e = 0; e <
ne; ++e)
113 for (
int d = 0; d <
dof; ++d)
115 const int sgid = elementMap[dof*e + d];
116 const int gid = (sgid >= 0) ? sgid : -1 - sgid;
121 for (
int i = 1; i <=
ndofs; ++i)
126 for (
int e = 0; e <
ne; ++e)
128 for (
int d = 0; d <
dof; ++d)
130 const int sdid = dof_reorder ? dof_map[d] : 0;
131 const int did = (!dof_reorder)?d:(sdid >= 0 ? sdid : -1-sdid);
132 const int sgid = elementMap[dof*e + did];
133 const int gid = (sgid >= 0) ? sgid : -1-sgid;
134 const int lid = dof*e + d;
135 const bool plus = (sgid >= 0 && sdid >= 0) || (sgid < 0 && sdid < 0);
142 for (
int i =
ndofs; i > 0; --i)
158 MFEM_FORALL(i,
dof*
ne,
160 const int gid = d_gatherMap[i];
161 const bool plus = gid >= 0;
162 const int j = plus ? gid : -1-gid;
163 for (
int c = 0; c < vd; ++c)
165 const double dofValue = d_x(t?c:j, t?j:c);
166 d_y(i % nd, c, i / nd) = plus ? dofValue : -dofValue;
181 MFEM_FORALL(i,
ndofs,
183 const int offset = d_offsets[i];
184 const int nextOffset = d_offsets[i + 1];
185 for (
int c = 0; c < vd; ++c)
188 for (
int j = offset; j < nextOffset; ++j)
190 const int idx_j = (d_indices[j] >= 0) ? d_indices[j] : -1 - d_indices[j];
191 dofValue += (d_indices[j] >= 0) ? d_x(idx_j % nd, c,
192 idx_j / nd) : -d_x(idx_j % nd, c, idx_j / nd);
194 d_y(t?c:i,t?i:c) = dofValue;
209 MFEM_FORALL(i,
ndofs,
211 const int offset = d_offsets[i];
212 const int nextOffset = d_offsets[i + 1];
213 for (
int c = 0; c < vd; ++c)
216 for (
int j = offset; j < nextOffset; ++j)
218 const int idx_j = (d_indices[j] >= 0) ? d_indices[j] : -1 - d_indices[j];
219 dofValue += d_x(idx_j % nd, c, idx_j / nd);
221 d_y(t?c:i,t?i:c) = dofValue;
239 faceMap[0] = dof1d-1;
247 for (
int i = 0; i < dof1d; ++i)
253 for (
int i = 0; i < dof1d; ++i)
255 faceMap[i] = dof1d-1 + i*dof1d;
259 for (
int i = 0; i < dof1d; ++i)
261 faceMap[i] = (dof1d-1)*dof1d + i;
265 for (
int i = 0; i < dof1d; ++i)
267 faceMap[i] = i*dof1d;
276 for (
int i = 0; i < dof1d; ++i)
278 for (
int j = 0; j < dof1d; ++j)
280 faceMap[i+j*dof1d] = i + j*dof1d;
285 for (
int i = 0; i < dof1d; ++i)
287 for (
int j = 0; j < dof1d; ++j)
289 faceMap[i+j*dof1d] = i + j*dof1d*dof1d;
294 for (
int i = 0; i < dof1d; ++i)
296 for (
int j = 0; j < dof1d; ++j)
298 faceMap[i+j*dof1d] = dof1d-1 + i*dof1d + j*dof1d*dof1d;
303 for (
int i = 0; i < dof1d; ++i)
305 for (
int j = 0; j < dof1d; ++j)
307 faceMap[i+j*dof1d] = (dof1d-1)*dof1d + i + j*dof1d*dof1d;
312 for (
int i = 0; i < dof1d; ++i)
314 for (
int j = 0; j < dof1d; ++j)
316 faceMap[i+j*dof1d] = i*dof1d + j*dof1d*dof1d;
321 for (
int i = 0; i < dof1d; ++i)
323 for (
int j = 0; j < dof1d; ++j)
325 faceMap[i+j*dof1d] = (dof1d-1)*dof1d*dof1d + i + j*dof1d;
338 nf(fes.GetNFbyType(type)),
341 ndofs(fes.GetNDofs()),
342 dof(nf > 0 ? fes.GetFaceElement(0)->GetDof() : 0),
344 scatter_indices(nf*dof),
346 gather_indices(nf*dof)
348 if (
nf==0) {
return; }
352 MFEM_VERIFY(tfe != NULL &&
355 "Only Gauss-Lobatto and Bernstein basis are supported in "
356 "H1FaceRestriction.");
358 "Non-conforming meshes not yet supported with partial assembly.");
363 if (dof_reorder &&
nf > 0)
365 for (
int f = 0; f < fes.
GetNF(); ++f)
370 if (el) {
continue; }
371 mfem_error(
"Finite element not suitable for lexicographic ordering");
377 MFEM_VERIFY(fe_dof_map.
Size() > 0,
"invalid dof map");
383 const int* elementMap = e2dTable.
GetJ();
394 for (
int f = 0; f < fes.
GetNF(); ++f)
398 orientation = inf1 % 64;
406 if (orientation != 0)
408 mfem_error(
"FaceRestriction used on degenerated mesh.");
414 mfem_error(
"FaceRestriction not yet implemented for this type of "
418 for (
int d = 0; d <
dof; ++d)
420 const int face_dof = faceMap[d];
421 const int did = (!dof_reorder)?face_dof:dof_map[face_dof];
422 const int gid = elementMap[e1*elem_dofs + did];
423 const int lid = dof*f_ind + d;
429 MFEM_VERIFY(f_ind==
nf,
"Unexpected number of faces.");
431 for (
int i = 0; i <=
ndofs; ++i)
436 for (
int f = 0; f < fes.
GetNF(); ++f)
440 orientation = inf1 % 64;
446 for (
int d = 0; d <
dof; ++d)
448 const int face_dof = faceMap[d];
449 const int did = (!dof_reorder)?face_dof:dof_map[face_dof];
450 const int gid = elementMap[e1*elem_dofs + did];
456 MFEM_VERIFY(f_ind==
nf,
"Unexpected number of faces.");
457 for (
int i = 1; i <=
ndofs; ++i)
462 for (
int f = 0; f < fes.
GetNF(); ++f)
466 orientation = inf1 % 64;
472 for (
int d = 0; d <
dof; ++d)
474 const int face_dof = faceMap[d];
475 const int did = (!dof_reorder)?face_dof:dof_map[face_dof];
476 const int gid = elementMap[e1*elem_dofs + did];
477 const int lid = dof*f_ind + d;
483 MFEM_VERIFY(f_ind==
nf,
"Unexpected number of faces.");
484 for (
int i =
ndofs; i > 0; --i)
502 const int idx = d_indices[i];
503 const int dof = i % nd;
504 const int face = i / nd;
505 for (
int c = 0; c < vd; ++c)
507 d_y(dof, c, face) = d_x(t?c:idx, t?idx:c);
522 MFEM_FORALL(i,
ndofs,
524 const int offset = d_offsets[i];
525 const int nextOffset = d_offsets[i + 1];
526 for (
int c = 0; c < vd; ++c)
529 for (
int j = offset; j < nextOffset; ++j)
531 const int idx_j = d_indices[j];
532 dofValue += d_x(idx_j % nd, c, idx_j / nd);
534 d_y(t?c:i,t?i:c) += dofValue;
539 static int ToLexOrdering2D(
const int face_id,
const int size1d,
const int i)
541 if (face_id==2 || face_id==3)
551 static int PermuteFace2D(
const int face_id1,
const int face_id2,
552 const int orientation,
553 const int size1d,
const int index)
557 if (face_id1==2 || face_id1==3)
559 new_index = size1d-1-
index;
568 new_index = size1d-1-new_index;
570 return ToLexOrdering2D(face_id2, size1d, new_index);
573 static int ToLexOrdering3D(
const int face_id,
const int size1d,
const int i,
576 if (face_id==2 || face_id==1 || face_id==5)
580 else if (face_id==3 || face_id==4)
582 return (size1d-1-i) + j*size1d;
586 return i + (size1d-1-j)*size1d;
590 static int PermuteFace3D(
const int face_id1,
const int face_id2,
591 const int orientation,
592 const int size1d,
const int index)
594 int i=0, j=0, new_i=0, new_j=0;
598 if (face_id1==3 || face_id1==4)
602 else if (face_id1==0)
619 new_j = (size1d-1-i);
622 new_i = (size1d-1-i);
626 new_i = (size1d-1-i);
627 new_j = (size1d-1-j);
630 new_i = (size1d-1-j);
631 new_j = (size1d-1-i);
634 new_i = (size1d-1-j);
639 new_j = (size1d-1-j);
642 return ToLexOrdering3D(face_id2, size1d, new_i, new_j);
647 const int face_id2,
const int orientation,
648 const int size1d,
const int index)
655 return PermuteFace2D(face_id1, face_id2, orientation, size1d, index);
657 return PermuteFace3D(face_id1, face_id2, orientation, size1d, index);
669 nf(fes.GetNFbyType(type)),
672 ndofs(fes.GetNDofs()),
674 fes.GetTraceElement(0, fes.GetMesh()->GetFaceBaseGeometry(0))->GetDof()
678 scatter_indices1(nf*dof),
686 MFEM_VERIFY(tfe != NULL &&
689 "Only Gauss-Lobatto and Bernstein basis are supported in "
690 "L2FaceRestriction.");
692 "Non-conforming meshes not yet supported with partial assembly.");
693 if (
nf==0) {
return; }
699 mfem_error(
"Non-Tensor L2FaceRestriction not yet implemented.");
701 if (dof_reorder &&
nf > 0)
703 for (
int f = 0; f < fes.
GetNF(); ++f)
709 if (el) {
continue; }
710 mfem_error(
"Finite element not suitable for lexicographic ordering");
714 const int* elementMap = e2dTable.
GetJ();
718 int face_id1, face_id2;
725 for (
int f = 0; f < fes.
GetNF(); ++f)
731 orientation = inf1 % 64;
732 face_id1 = inf1 / 64;
734 orientation = inf2 % 64;
735 face_id2 = inf2 / 64;
740 mfem_error(
"FaceRestriction not yet implemented for this type of "
747 for (
int d = 0; d <
dof; ++d)
749 const int face_dof = faceMap1[d];
750 const int did = face_dof;
751 const int gid = elementMap[e1*elem_dofs + did];
752 const int lid = dof*f_ind + d;
757 for (
int d = 0; d <
dof; ++d)
762 orientation, dof1d, d);
763 const int face_dof = faceMap2[pd];
764 const int did = face_dof;
765 const int gid = elementMap[e2*elem_dofs + did];
766 const int lid = dof*f_ind + d;
771 const int lid = dof*f_ind + d;
779 MFEM_VERIFY(f_ind==
nf,
"Unexpected number of faces.");
781 for (
int i = 0; i <=
ndofs; ++i)
786 for (
int f = 0; f < fes.
GetNF(); ++f)
793 orientation = inf1 % 64;
794 face_id1 = inf1 / 64;
796 orientation = inf2 % 64;
797 face_id2 = inf2 / 64;
799 for (
int d = 0; d <
dof; ++d)
801 const int did = faceMap1[d];
802 const int gid = elementMap[e1*elem_dofs + did];
807 for (
int d = 0; d <
dof; ++d)
812 orientation, dof1d, d);
813 const int did = faceMap2[pd];
814 const int gid = elementMap[e2*elem_dofs + did];
822 MFEM_VERIFY(f_ind==
nf,
"Unexpected number of faces.");
823 for (
int i = 1; i <=
ndofs; ++i)
828 for (
int f = 0; f < fes.
GetNF(); ++f)
835 orientation = inf1 % 64;
836 face_id1 = inf1 / 64;
838 orientation = inf2 % 64;
839 face_id2 = inf2 / 64;
841 for (
int d = 0; d <
dof; ++d)
843 const int did = faceMap1[d];
844 const int gid = elementMap[e1*elem_dofs + did];
845 const int lid = dof*f_ind + d;
851 for (
int d = 0; d <
dof; ++d)
856 orientation, dof1d, d);
857 const int did = faceMap2[pd];
858 const int gid = elementMap[e2*elem_dofs + did];
859 const int lid = dof*f_ind + d;
868 MFEM_VERIFY(f_ind==
nf,
"Unexpected number of faces.");
869 for (
int i =
ndofs; i > 0; --i)
891 const int dof = i % nd;
892 const int face = i / nd;
893 const int idx1 = d_indices1[i];
894 for (
int c = 0; c < vd; ++c)
896 d_y(dof, c, 0, face) = d_x(t?c:idx1, t?idx1:c);
898 const int idx2 = d_indices2[i];
899 for (
int c = 0; c < vd; ++c)
901 d_y(dof, c, 1, face) = idx2==-1 ? 0.0 : d_x(t?c:idx2, t?idx2:c);
912 const int dof = i % nd;
913 const int face = i / nd;
914 const int idx1 = d_indices1[i];
915 for (
int c = 0; c < vd; ++c)
917 d_y(dof, c, face) = d_x(t?c:idx1, t?idx1:c);
934 MFEM_FORALL(i,
ndofs,
936 const int offset = d_offsets[i];
937 const int nextOffset = d_offsets[i + 1];
938 for (
int c = 0; c < vd; ++c)
941 for (
int j = offset; j < nextOffset; ++j)
943 int idx_j = d_indices[j];
944 bool isE1 = idx_j < dofs;
945 idx_j = isE1 ? idx_j : idx_j - dofs;
947 d_x(idx_j % nd, c, 0, idx_j / nd)
948 :d_x(idx_j % nd, c, 1, idx_j / nd);
950 d_y(t?c:i,t?i:c) += dofValue;
963 return ToLexOrdering2D(face_id, size1d, index);
965 return ToLexOrdering3D(face_id, size1d, index%size1d, index/size1d);
Abstract class for Finite Elements.
void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
int Size() const
Logical size of the array.
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
void MultTransposeUnsigned(const Vector &x, Vector &y) const
Compute MultTranspose without applying signs based on DOF orientations.
L2FaceRestriction(const FiniteElementSpace &, const ElementDofOrdering, const FaceType, const L2FaceValues m=L2FaceValues::DoubleValued)
const FiniteElement * GetTraceElement(int i, Geometry::Type geom_type) const
Return the trace element from element 'i' to the given 'geom_type'.
Array< int > gather_indices
T * GetData()
Returns the data.
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
H1FaceRestriction(const FiniteElementSpace &, const ElementDofOrdering, const FaceType)
Geometry::Type GetFaceBaseGeometry(int i) const
void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
const FiniteElement * GetFaceElement(int i) const
double * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
Array< int > gather_indices
L2ElementRestriction(const FiniteElementSpace &)
DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims...dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
Mesh * GetMesh() const
Returns the mesh.
void mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
ElementRestriction(const FiniteElementSpace &, ElementDofOrdering)
int GetNF() const
Returns number of faces (i.e. co-dimension 1 entities) in the mesh.
int SpaceDimension() const
int ToLexOrdering(const int dim, const int face_id, const int size1d, const int index)
const FiniteElementSpace & fes
void GetFaceElements(int Face, int *Elem1, int *Elem2) const
void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
void GetFaceInfos(int Face, int *Inf1, int *Inf2) const
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
int GetDof() const
Returns the number of degrees of freedom in the finite element.
void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
void GetFaceDofs(const int dim, const int face_id, const int dof1d, Array< int > &faceMap)
Return the face degrees of freedom returned in Lexicographic order.
The ordering method used when the number of unknowns per mesh node (vector dimension) is bigger than ...
void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
int height
Dimension of the output / number of rows in the matrix.
const Array< int > & GetDofMap() const
Get an Array<int> that maps lexicographically ordered indices to the indices of the respective nodes/...
Array< int > scatter_indices1
const double * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
ElementDofOrdering
Constants describing the possible orderings of the DOFs in one element.
const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement associated with i'th element.
int index(int i, int j, int nx, int ny)
Lexicographic ordering for tensor-product FiniteElements.
int PermuteFaceL2(const int dim, const int face_id1, const int face_id2, const int orientation, const int size1d, const int index)
Permute dofs or quads on a face for e2 to match with the ordering of e1.
const Table & GetElementToDofTable() const
Array< int > scatter_indices
int width
Dimension of the input / number of columns in the matrix.
Array< int > scatter_indices2
void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...