42 const double ip = diff * normal;
54 const Vector origin, normal;
58 std::vector<int> *r2o;
60 std::vector<std::vector<int>> *perm;
64 Vector const& normal_, std::vector<int> *r2o_,
65 Mesh *mesh, std::vector<std::vector<int>> *refPerm) :
67 meshOrig(mesh), r2o(r2o_), perm(refPerm)
73 using VectorCoefficient::Eval;
82 T.Transform(ip, transip);
84 const int elem = T.ElementNo;
85 const bool reflected = (*r2o)[elem] < 0;
86 const int originalElem = reflected ? -1 - (*r2o)[elem] : (*r2o)[elem];
100 a->Eval(V, *T_orig, ip);
112 const std::vector<int>&
p = (*perm)[elem];
121 b[0] = (*ir)[
p[0]].x;
122 b[1] = (*ir)[
p[0]].y;
123 b[2] = (*ir)[
p[0]].z;
128 A(0,0) = (*ir)[
p[1]].x -
b[0];
129 A(1,0) = (*ir)[
p[1]].y -
b[1];
130 A(2,0) = (*ir)[
p[1]].z -
b[2];
133 A(0,1) = (*ir)[
p[3]].x -
b[0];
134 A(1,1) = (*ir)[
p[3]].y -
b[1];
135 A(2,1) = (*ir)[
p[3]].z -
b[2];
138 A(0,2) = (*ir)[
p[4]].x -
b[0];
139 A(1,2) = (*ir)[
p[4]].y -
b[1];
140 A(2,2) = (*ir)[
p[4]].z -
b[2];
156 a->Eval(V, *T_orig, ipo);
167 std::vector<int> & perm)
169 std::map<int, int> h2inv;
170 const int n = perm.size();
172 for (
int i=0; i<n; ++i)
177 for (
int i=0; i<n; ++i)
179 perm[i] = h2inv[h1[i]];
192 HexMeshBuilder(
int nv,
int ne) : v2f(nv)
194 mesh =
new Mesh(3, nv, ne);
225 int AddVertex(
const double *coords)
const 227 return mesh->AddVertex(coords);
236 int AddElement(
Array<int> const& vertices,
const bool reorder);
239 std::vector<std::vector<int>> refPerm;
242 std::vector<std::vector<int>> faces;
243 std::vector<std::set<int>> v2f;
244 std::vector<std::vector<int>> f2e;
245 std::array<std::array<int, 4>, 6> f2v;
246 std::array<std::array<int, 2>, 12> e2v;
248 int FindFourthVertexOnFace(
Array<int> const& hex,
249 std::vector<int>
const& v3)
const;
255 void ReverseHexFace(
Array<int> & hex,
const int face)
const;
256 int FindHexFace(
Array<int> const& hex, std::vector<int>
const& face)
const;
258 bool ReorderHex_faceOrientations(
Array<int> & hex)
const;
259 void SaveHexFaces(
const int elem,
Array<int> const& hex);
262 int HexMeshBuilder::AddElement(
Array<int> const& vertices,
const bool reorder)
264 MFEM_ASSERT(vertices.
Size() == 8,
"Hexahedron must have 8 vertices");
272 bool reordered =
true;
276 reordered = ReorderHex_faceOrientations(rvert);
278 MFEM_VERIFY(iter < 5,
"");
282 std::vector<int> perm_e(8);
284 refPerm.push_back(perm_e);
288 refPerm.push_back(std::vector<int> {0, 1, 2, 3, 4, 5, 6, 7});
291 SaveHexFaces(mesh->GetNE(), rvert);
293 Element * nel = mesh->NewElement(Geometry::Type::CUBE);
296 return mesh->AddElement(nel);
299 int HexMeshBuilder::FindFourthVertexOnFace(
Array<int> const& hex,
300 std::vector<int>
const& v3)
const 303 for (
int f=0;
f<6; ++
f)
305 bool all3found =
true;
307 for (
int i=0; i<3; ++i)
312 for (
int j=0; j<4; ++j)
314 if (hex[f2v[
f][j]] == v3[i])
329 MFEM_ASSERT(f0 == -1,
"");
334 MFEM_VERIFY(f0 >= 0,
"");
339 for (
int j=0; j<4; ++j)
342 for (
int i=0; i<3; ++i)
345 if (hex[f2v[f0][j]] == v3[i])
353 MFEM_ASSERT(v == -1,
"");
358 MFEM_VERIFY(v >= 0,
"");
363 void HexMeshBuilder::ReorderHex(
Array<int> & hex)
const 365 MFEM_VERIFY(hex.
Size() == 8,
"hex");
369 const int v0 = hex.
Min();
371 std::map<int, int> v2hex0;
373 for (
int i=0; i<hex.
Size(); ++i)
379 std::vector<int> v0e;
380 for (
int e=0; e<12; ++e)
382 if (v0 == hex[e2v[e][0]] || v0 == hex[e2v[e][1]])
388 MFEM_VERIFY(v0e.size() == 3,
"");
390 std::vector<int> v0n;
393 if (v0 == hex[e2v[e][0]])
395 v0n.push_back(hex[e2v[e][1]]);
399 v0n.push_back(hex[e2v[e][0]]);
403 MFEM_VERIFY(v0n.size() == 3,
"");
405 sort(v0n.begin(), v0n.end());
413 std::vector<int> v3(3);
417 h[2] = FindFourthVertexOnFace(hex, v3);
421 h[5] = FindFourthVertexOnFace(hex, v3);
425 h[7] = FindFourthVertexOnFace(hex, v3);
431 h[6] = FindFourthVertexOnFace(hex, v3);
436 void HexMeshBuilder::ReverseHexZ(
Array<int> & hex)
const 450 void HexMeshBuilder::ReverseHexY(
Array<int> & hex)
const 464 void HexMeshBuilder::ReverseHexX(
Array<int> & hex)
const 479 void HexMeshBuilder::ReverseHexFace(
Array<int> & hex,
const int face)
const 481 const int f = 2 * (face / 2);
496 int HexMeshBuilder::FindHexFace(
Array<int> const& hex,
497 std::vector<int>
const& face)
const 500 for (
int f=0;
f<6; ++
f)
502 std::vector<int> fv(4);
503 for (
int i=0; i<4; ++i)
505 fv[i] = hex[f2v[
f][i]];
508 sort(fv.begin(), fv.end());
512 MFEM_VERIFY(localFace == -1,
"");
517 MFEM_VERIFY(localFace >= 0,
"");
522 bool HexMeshBuilder::ReorderHex_faceOrientations(
Array<int> & hex)
const 524 std::vector<int> localFacesFound, globalFacesFound;
525 for (
int f=0;
f<6; ++
f)
527 std::vector<int> fv(4);
528 for (
int i=0; i<4; ++i)
530 fv[i] = hex[f2v[
f][i]];
533 sort(fv.begin(), fv.end());
535 const int vmin = fv[0];
537 for (
auto gf : v2f[vmin])
547 globalFacesFound.push_back(globalFace);
548 localFacesFound.push_back(
f);
552 const int numFoundFaces = globalFacesFound.size();
554 for (
int ff=0; ff<numFoundFaces; ++ff)
556 const int globalFace = globalFacesFound[ff];
557 const int localFace = localFacesFound[ff];
559 MFEM_VERIFY(f2e[globalFace].size() == 1,
"");
560 const int neighborElem = f2e[globalFace][0];
563 mesh->GetElementVertices(neighborElem, neighborElemVert);
564 const int neighborLocalFace = FindHexFace(neighborElemVert, faces[globalFace]);
566 std::vector<int> fv(4);
567 std::vector<int> nv(4);
568 for (
int i=0; i<4; ++i)
570 fv[i] = hex[f2v[localFace][i]];
571 nv[i] = neighborElemVert[f2v[neighborLocalFace][i]];
578 for (id0 = 0; id0 < 4; id0++)
580 if (fv[id0] == nv[0])
586 MFEM_VERIFY(id0 < 4,
"");
588 bool same = (fv[(id0+1) % 4] == nv[1]);
593 ReverseHexFace(hex, localFace);
601 void HexMeshBuilder::SaveHexFaces(
const int elem,
Array<int> const& hex)
603 for (
int f=0;
f<6; ++
f)
605 std::vector<int> fv(4);
606 for (
int i=0; i<4; ++i)
608 fv[i] = hex[f2v[
f][i]];
611 sort(fv.begin(), fv.end());
613 const int vmin = fv[0];
615 for (
auto gf : v2f[vmin])
623 if (globalFace == -1)
627 globalFace = faces.
size() - 1;
629 std::vector<int> firstElem = {elem};
630 f2e.push_back(firstElem);
635 MFEM_VERIFY(f2e[globalFace].size() == 1 &&
636 f2e[globalFace][0] != elem,
"");
637 f2e[globalFace].push_back(elem);
640 MFEM_VERIFY(faces.size() == f2e.size(),
"");
641 v2f[vmin].insert(globalFace);
655 const double *v0 = mesh.
GetVertex(vert[0]);
656 const double *v1 = mesh.
GetVertex(vert[1]);
659 for (
int i=0; i<3; ++i)
661 L += (v0[i] - v1[i]) * (v0[i] - v1[i]);
666 if (diam < 0.0 || L < diam) { diam = L; }
673 Vector const& normal, std::vector<int> & el)
675 const double relTol = 1.0e-6;
678 for (
int e=0; e<mesh.
GetNE(); ++e)
684 bool onplane =
false;
688 for (
int i=0; i<3; ++i)
690 diff[i] = vcrd[i] - origin[i];
693 if (std::abs(diff * normal) < relTol * diam)
699 if (onplane) { el.push_back(e); }
705 Vector const& normal, std::vector<int> & elOrder)
707 const int ne = mesh.
GetNE();
708 elOrder.assign(ne, -1);
710 std::vector<bool> elementMarked;
712 elementMarked.assign(ne,
false);
714 std::vector<int> layer;
717 if (layer.size() == 0)
720 for (
int i=0; i<ne; ++i)
735 elementMarked[e] =
true;
738 if (cnt == ne) {
break; }
740 std::set<int> layerNext;
746 if (!elementMarked[n]) { layerNext.insert(n); }
750 MFEM_VERIFY(layerNext.size() > 0,
"");
753 layer.reserve(layerNext.size());
754 for (
auto e : layerNext)
760 MFEM_VERIFY(cnt == ne,
"");
767 MFEM_VERIFY(mesh.
Dimension() == 3,
"Only 3D meshes can be reflected");
770 double minLength = 0.0;
771 for (
int i=0; i<mesh.
GetNE(); i++)
779 const double length = diff.Norml2();
780 if (i == 0 || length < minLength)
786 const double relTol = 1.0e-6;
789 std::set<int> planeVertices;
790 for (
int i=0; i<mesh.
GetNV(); i++)
795 const double ip = diff * normal;
796 if (fabs(ip) < relTol * minLength)
798 planeVertices.insert(i);
802 const int nv = mesh.
GetNV();
803 const int ne = mesh.
GetNE();
805 std::vector<int> r2o;
807 const int nv_reflected = (2*nv) - planeVertices.size();
809 HexMeshBuilder builder(nv_reflected, 2*ne);
811 r2o.assign(2*ne, -2-ne);
813 std::vector<int> v2r;
814 v2r.assign(mesh.
GetNV(), -1);
817 for (
int v=0; v<mesh.
GetNV(); v++)
822 for (
int v=0; v<mesh.
GetNV(); v++)
825 if (planeVertices.find(v) == planeVertices.end())
829 for (
int i=0; i<3; ++i)
836 v2r[v] = builder.AddVertex(vr.
GetData());
840 std::vector<int> elOrder;
843 for (
int eidx=0; eidx<mesh.
GetNE(); eidx++)
845 const int e = elOrder[eidx];
851 MFEM_VERIFY(elvert.
Size() == 8,
"Only hexahedral elements are supported");
853 const int copiedElem = builder.AddElement(elvert,
false);
858 for (
int i=0; i<elvert.
Size(); ++i)
860 const int v = elvert[i];
861 rvert[i] = (v2r[v] == -1) ? v : v2r[v];
864 const int newElem = builder.AddElement(rvert, onPlane);
865 r2o[newElem] = -1 - e;
868 Mesh *reflected = builder.mesh;
871 MFEM_VERIFY((
int) r2o.size() == reflected->
GetNE(),
"");
872 for (
int i = 0; i < (int) r2o.size(); ++i)
874 const int e = (r2o[i] >= 0) ? r2o[i] : -1 - r2o[i];
889 std::map<std::pair<int, int>,
int> mapBE;
890 for (
int i=0; i<mesh.
GetNBE(); ++i)
895 MFEM_VERIFY(v.
Size() == 4,
"Boundary elements must be quadrilateral");
897 const int v1 = v.
Min();
899 for (
int j=0; j<v.
Size(); ++j)
907 const int v2 = v[(v1i + 2) % 4];
909 mapBE[std::pair<int, int>(v1, v2)] = i;
916 for (
int j=0; j<v.
Size(); ++j)
918 rv[j] = (v2r[v[j]] == -1) ? v[j] : v2r[v[j]];
925 if (rv1 == -1 || rv[j] < rv1)
935 const int rv2 = rv[(rv1i + 2) % 4];
937 mapBE[std::pair<int, int>(rv1, rv2)] = i;
952 for (
int i=0; i<reflected->
GetNBE(); ++i)
957 MFEM_VERIFY(rv.
Size() == 4,
"Boundary elements must be quadrilateral");
961 const int v1 = rv.
Min();
963 for (
int j=0; j<rv.
Size(); ++j)
971 const int v2 = rv[(v1i + 2) % 4];
973 const int originalBE = mapBE[std::pair<int, int>(v1, v2)];
995 reflected->
SetCurvature(order, discont, sdim, ordering);
1002 ReflectedCoefficient rc(nodesCoef, origin, normal, &r2o, &mesh,
1006 *reflected_nodes = newReflectedNodes;
1015 const char *mesh_file =
"../../data/pipe-nurbs.mesh";
1016 bool visualization = 1;
1025 args.
AddOption(&mesh_file,
"-m",
"--mesh",
1026 "Mesh file to use.");
1027 args.
AddOption(&normal,
"-n",
"--normal",
1028 "Normal vector of plane.");
1029 args.
AddOption(&origin,
"-o",
"--origin",
1030 "A point in the plane.");
1031 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
1032 "--no-visualization",
1033 "Enable or disable GLVis visualization.");
1042 MFEM_VERIFY(fabs(normal.
Norml2() - 1.0) < 1.0e-14,
"");
1044 Mesh mesh(mesh_file, 0, 0);
1049 ofstream mesh_ofs(
"reflected.mesh");
1050 mesh_ofs.precision(8);
1051 reflected->
Print(mesh_ofs);
1059 sol_sock.precision(8);
1060 sol_sock <<
"mesh\n" << *reflected << flush;
T Min() const
Find the minimal element in the array, using the comparison operator < for class T.
Class for an integration rule - an Array of IntegrationPoint.
Class for grid function - Vector with associated FE space.
void GetElementEdges(int i, Array< int > &edges, Array< int > &cor) const
Return the indices and the orientations of all edges of element i.
Base class for vector Coefficients that optionally depend on time and space.
virtual void GetVertices(Array< int > &v) const =0
Returns element's vertices.
void PrintOptions(std::ostream &out) const
Print the options.
void PrintUsage(std::ostream &out) const
Print the usage message.
int size
Size of the array.
int GetOrder() const
Return the order (polynomial degree) of the FE collection, corresponding to the order/degree returned...
Data type dense matrix using column-major storage.
virtual void SetVertices(const int *ind)
Set the indices the element according to the input.
bool Good() const
Return true if the command line options were parsed successfully.
const IntegrationRule * GetVertices(int GeomType)
Return an IntegrationRule consisting of all vertices of the given Geometry::Type, GeomType...
int GetNBE() const
Returns number of boundary elements.
void add(const Vector &v1, const Vector &v2, Vector &v)
Element * NewElement(int geom)
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
int GetAttribute(int i) const
Return the attribute of element i.
bool GetMeshElementOrder(Mesh const &mesh, Vector const &origin, Vector const &normal, std::vector< int > &elOrder)
void FindElementsTouchingPlane(Mesh const &mesh, Vector const &origin, Vector const &normal, std::vector< int > &el)
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
const FiniteElementCollection * FEColl() const
virtual void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1)
Set the curvature of the mesh nodes using the given polynomial degree.
void GetEdgeVertices(int i, Array< int > &vert) const
Returns the indices of the vertices of edge i.
virtual void Eval(DenseMatrix &M, ElementTransformation &T, const IntegrationRule &ir)
Evaluate the vector coefficient in the element described by T at all points of ir, storing the result in M.
const double * GetVertex(int i) const
Return pointer to vertex i's coordinates.
void GetElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of element i.
Array< int > FindFaceNeighbors(const int elem) const
Returns the sorted, unique indices of elements sharing a face with element elem, including elem...
FiniteElementSpace * FESpace()
void GetHexPermutation(Array< int > const &h1, Array< int > const &h2, std::vector< int > &perm)
double * GetData() const
Return a pointer to the beginning of the Vector data.
int GetBdrAttribute(int i) const
Return the attribute of boundary element i.
void Swap(Array< T > &, Array< T > &)
void ReflectPoint(Vector &p, Vector const &origin, Vector const &normal)
double p(const Vector &x, double t)
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
void RemoveUnusedVertices()
Remove unused vertices and rebuild mesh connectivity.
void subtract(const Vector &x, const Vector &y, Vector &z)
void AddOption(bool *var, const char *enable_short_name, const char *enable_long_name, const char *disable_short_name, const char *disable_long_name, const char *description, bool required=false)
Add a boolean option and set 'var' to receive the value. Enable/disable tags are used to set the bool...
void FinalizeTopology(bool generate_bdr=true)
Finalize the construction of the secondary topology (connectivity) data of a Mesh.
void SetBdrAttribute(int i, int attr)
Set the attribute of boundary element i.
int SpaceDimension() const
int GetNE() const
Returns number of elements.
Class for integration point with weight.
Ordering::Type GetOrdering() const
Return the ordering method.
virtual void Finalize(bool refine=false, bool fix_orientation=false)
Finalize the construction of a general Mesh.
double GetElementEdgeMin(Mesh const &mesh, const int elem)
virtual void ProjectCoefficient(Coefficient &coeff)
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
double Norml2() const
Returns the l2 norm of the vector.
int AddBdrElement(Element *elem)
int Size() const
Return the logical size of the array.
void SetAttribute(int i, int attr)
Set the attribute of element i.
Mesh * ReflectHighOrderMesh(Mesh &mesh, Vector origin, Vector normal)
virtual void Print(std::ostream &os=mfem::out) const
Vector coefficient defined by a vector GridFunction.
void GetNodes(Vector &node_coord) const
const Element * GetBdrElement(int i) const
Geometry::Type GetBdrElementBaseGeometry(int i) const
Abstract data type element.
Arbitrary order "L2-conforming" discontinuous finite elements.
int main(int argc, char *argv[])
double f(const Vector &p)