42 const real_t 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)
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 real_t *coords)
const
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);
262int 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);
299int 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,
"");
363void 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);
436void HexMeshBuilder::ReverseHexZ(
Array<int> & hex)
const
450void HexMeshBuilder::ReverseHexY(
Array<int> & hex)
const
464void HexMeshBuilder::ReverseHexX(
Array<int> & hex)
const
479void HexMeshBuilder::ReverseHexFace(
Array<int> & hex,
const int face)
const
481 const int f = 2 * (face / 2);
496int 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,
"");
522bool 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];
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);
601void 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);
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 real_t 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");
771 for (
int i=0; i<mesh.
GetNE(); i++)
780 if (i == 0 || length < minLength)
786 const real_t relTol = 1.0e-6;
789 std::set<int> planeVertices;
790 for (
int i=0; i<mesh.
GetNV(); i++)
795 const real_t ip = diff * normal;
796 if (std::abs(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(std::abs(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.
int Size() const
Return the logical size of the array.
Data type dense matrix using column-major storage.
Abstract data type element.
virtual void GetVertices(Array< int > &v) const =0
Get the indices defining the vertices.
virtual void SetVertices(const Array< int > &v)=0
Set the indices defining the vertices.
int GetOrder() const
Return the order (polynomial degree) of the FE collection, corresponding to the order/degree returned...
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Ordering::Type GetOrdering() const
Return the ordering method.
const FiniteElementCollection * FEColl() const
const IntegrationRule * GetVertices(int GeomType) const
Return an IntegrationRule consisting of all vertices of the given Geometry::Type, GeomType.
Class for grid function - Vector with associated FE space.
FiniteElementSpace * FESpace()
virtual void ProjectCoefficient(Coefficient &coeff)
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
Class for integration point with weight.
Class for an integration rule - an Array of IntegrationPoint.
Arbitrary order "L2-conforming" discontinuous finite elements.
Element * NewElement(int geom)
int AddBdrElement(Element *elem)
Array< int > FindFaceNeighbors(const int elem) const
Returns the sorted, unique indices of elements sharing a face with element elem, including elem.
Geometry::Type GetBdrElementGeometry(int i) const
int GetAttribute(int i) const
Return the attribute of element i.
void GetElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of element i.
int GetBdrAttribute(int i) const
Return the attribute of boundary element i.
void SetAttribute(int i, int attr)
Set the attribute of element i.
void FinalizeTopology(bool generate_bdr=true)
Finalize the construction of the secondary topology (connectivity) data of a Mesh.
virtual void Print(std::ostream &os=mfem::out, const std::string &comments="") const
int AddVertex(real_t x, real_t y=0.0, real_t z=0.0)
int GetNE() const
Returns number of elements.
int Dimension() const
Dimension of the reference space used within the elements.
const Element * GetBdrElement(int i) const
Return pointer to the i'th boundary element object.
int AddElement(Element *elem)
void GetElementTransformation(int i, IsoparametricTransformation *ElTr) const
Builds the transformation defining the i-th element in ElTr. ElTr must be allocated in advance and wi...
int SpaceDimension() const
Dimension of the physical space containing the mesh.
void GetNodes(Vector &node_coord) const
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
void GetEdgeVertices(int i, Array< int > &vert) const
Returns the indices of the vertices of edge i.
int GetNBE() const
Returns number of boundary elements.
virtual void Finalize(bool refine=false, bool fix_orientation=false)
Finalize the construction of a general Mesh.
void GetElementEdges(int i, Array< int > &edges, Array< int > &cor) const
Return the indices and the orientations of all edges of element i.
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 SetBdrAttribute(int i, int attr)
Set the attribute of boundary element i.
const real_t * GetVertex(int i) const
Return pointer to vertex i's coordinates.
void RemoveUnusedVertices()
Remove unused vertices and rebuild mesh connectivity.
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
void PrintUsage(std::ostream &out) const
Print the usage message.
void PrintOptions(std::ostream &out) const
Print the options.
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...
bool Good() const
Return true if the command line options were parsed successfully.
Base class for vector Coefficients that optionally depend on time and space.
virtual void Eval(Vector &V, ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the vector coefficient in the element described by T at the point ip, storing the result in ...
Vector coefficient defined by a vector GridFunction.
real_t Norml2() const
Returns the l2 norm of the vector.
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
real_t proj(GridFunction &psi, real_t target_volume, real_t tol=1e-12, int max_its=10)
Bregman projection of ρ = sigmoid(ψ) onto the subspace ∫_Ω ρ dx = θ vol(Ω) as follows:
void Swap(Array< T > &, Array< T > &)
void add(const Vector &v1, const Vector &v2, Vector &v)
void subtract(const Vector &x, const Vector &y, Vector &z)
std::function< real_t(const Vector &)> f(real_t mass_coeff)
real_t p(const Vector &x, real_t t)
void GetHexPermutation(Array< int > const &h1, Array< int > const &h2, std::vector< int > &perm)
real_t GetElementEdgeMin(Mesh const &mesh, const int elem)
void ReflectPoint(Vector &p, Vector const &origin, Vector const &normal)
bool GetMeshElementOrder(Mesh const &mesh, Vector const &origin, Vector const &normal, std::vector< int > &elOrder)
Mesh * ReflectHighOrderMesh(Mesh &mesh, Vector origin, Vector normal)
void FindElementsTouchingPlane(Mesh const &mesh, Vector const &origin, Vector const &normal, std::vector< int > &el)