gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
meshGFaceExtruded.cpp
Go to the documentation of this file.
1 // Gmsh - Copyright (C) 1997-2022 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5 
6 #include <set>
7 #include "GmshConfig.h"
8 #include "GModel.h"
9 #include "MLine.h"
10 #include "MTriangle.h"
11 #include "MQuadrangle.h"
12 #include "ExtrudeParams.h"
13 #include "MVertexRTree.h"
14 #include "Context.h"
15 #include "GmshMessage.h"
16 
17 #if defined(HAVE_QUADTRI)
18 #include "QuadTriExtruded2D.h"
19 #endif
20 
21 static void addTriangle(MVertex *v1, MVertex *v2, MVertex *v3, GFace *to)
22 {
23  to->triangles.push_back(new MTriangle(v1, v2, v3));
24 }
25 
26 static void addQuadrangle(MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4,
27  GFace *to)
28 {
29  to->quadrangles.push_back(new MQuadrangle(v1, v2, v3, v4));
30 }
31 
32 static void
33 createQuaTri(std::vector<MVertex *> &v, GFace *to,
34  std::set<std::pair<MVertex *, MVertex *> > *constrainedEdges,
35  MLine *source, int tri_quad_flag)
36 {
38  if(v[0] == v[1] || v[1] == v[3])
39  addTriangle(v[0], v[3], v[2], to);
40  else if(v[0] == v[2] || v[2] == v[3])
41  addTriangle(v[0], v[1], v[3], to);
42  else if(v[0] == v[3] || v[1] == v[2])
43  Msg::Error("Incoherent extruded quadrangle in surface %d", to->tag());
44  else {
45  // Trevor Strickler added the tri_quad_flag stuff here.
46  if((ep->mesh.Recombine && tri_quad_flag != 2) || tri_quad_flag == 1) {
47  if(!constrainedEdges)
48  addQuadrangle(v[0], v[1], v[3], v[2], to);
49  else {
50  std::pair<MVertex *, MVertex *> p1(std::min(v[1], v[2]),
51  std::max(v[1], v[2]));
52  std::pair<MVertex *, MVertex *> p2(std::min(v[0], v[3]),
53  std::max(v[0], v[3]));
54  if(constrainedEdges->count(p1)) {
55  addTriangle(v[2], v[1], v[0], to);
56  addTriangle(v[2], v[3], v[1], to);
57  }
58  else if(constrainedEdges->count(p2)) {
59  addTriangle(v[2], v[3], v[0], to);
60  addTriangle(v[0], v[3], v[1], to);
61  }
62  else
63  addQuadrangle(v[0], v[1], v[3], v[2], to);
64  }
65  }
66  else if(!constrainedEdges) {
67  addTriangle(v[0], v[1], v[3], to);
68  addTriangle(v[0], v[3], v[2], to);
69  }
70  else {
71  std::pair<MVertex *, MVertex *> p(std::min(v[1], v[2]),
72  std::max(v[1], v[2]));
73  if(constrainedEdges->count(p)) {
74  addTriangle(v[2], v[1], v[0], to);
75  addTriangle(v[2], v[3], v[1], to);
76  }
77  else {
78  addTriangle(v[2], v[3], v[0], to);
79  addTriangle(v[0], v[3], v[1], to);
80  }
81  }
82  }
83 }
84 
85 static void
87  std::set<std::pair<MVertex *, MVertex *> > *constrainedEdges)
88 {
90 
91  // create vertices (if the edges are constrained, they already exist)
92  if(!constrainedEdges) {
93  for(std::size_t i = 0; i < from->mesh_vertices.size(); i++) {
94  std::vector<MVertex *> extruded_vertices;
95  MVertex *v = from->mesh_vertices[i];
96  MEdgeVertex *mv = dynamic_cast<MEdgeVertex *>(v);
97  if(mv) mv->bl_data = new MVertexBoundaryLayerData();
98  for(int j = 0; j < ep->mesh.NbLayer; j++) {
99  for(int k = 0; k < ep->mesh.NbElmLayer[j]; k++) {
100  double x = v->x(), y = v->y(), z = v->z();
101  ep->Extrude(j, k + 1, x, y, z);
102  if(j != ep->mesh.NbLayer - 1 || k != ep->mesh.NbElmLayer[j] - 1) {
103  MVertex *newv = pos.find(x, y, z);
104  if(!newv) {
105  if(from->geomType() != GEntity::DiscreteCurve &&
108  // This can be inefficient, and sometimes useless. We could add
109  // an option to disable it.
110  SPoint3 xyz(x, y, z);
111  SPoint2 uv = to->parFromPoint(xyz);
112  newv = new MFaceVertex(x, y, z, to, uv[0], uv[1]);
113  }
114  else {
115  newv = new MVertex(x, y, z, to);
116  }
117  to->mesh_vertices.push_back(newv);
118  }
119  pos.insert(newv);
120  extruded_vertices.push_back(newv);
121  }
122  }
123  }
124  if(mv) mv->bl_data->addChildrenFamily(extruded_vertices);
125  }
126  }
127 
128  int tri_quad_flag = 0;
129 
130 #if defined(HAVE_QUADTRI)
131  // figure out whether to recombine this surface or not in the event of
132  // quadToTri region neighbors (if QuadToTri, tri_quad_flag is an int flag that
133  // lets createQuadTri() override the surface's intrinsic ep->mesh.Recombine
134  // flag. tri_quad_flag values: 0 = no override, 1 = mesh with quads, 2 = mesh
135  // with triangles.)
136  bool detectQuadToTriLateral = false;
137  bool quadToTri_valid =
138  IsValidQuadToTriLateral(to, &tri_quad_flag, &detectQuadToTriLateral);
139  if(detectQuadToTriLateral && !quadToTri_valid)
140  Msg::Error("Mesh of QuadToTri lateral surface %d likely has errors",
141  to->tag());
142 #endif
143 
144  // create elements (note that it would be faster to access the *interior*
145  // nodes by direct indexing, but it's just simpler to query everything by
146  // position)
147  for(std::size_t i = 0; i < from->lines.size(); i++) {
148  MVertex *v0 = from->lines[i]->getVertex(0);
149  MVertex *v1 = from->lines[i]->getVertex(1);
150  for(int j = 0; j < ep->mesh.NbLayer; j++) {
151  for(int k = 0; k < ep->mesh.NbElmLayer[j]; k++) {
152  std::vector<MVertex *> verts;
153  double x[4] = {v0->x(), v1->x(), v0->x(), v1->x()};
154  double y[4] = {v0->y(), v1->y(), v0->y(), v1->y()};
155  double z[4] = {v0->z(), v1->z(), v0->z(), v1->z()};
156  for(int p = 0; p < 2; p++) {
157  ep->Extrude(j, k, x[p], y[p], z[p]);
158  ep->Extrude(j, k + 1, x[p + 2], y[p + 2], z[p + 2]);
159  }
160  for(int p = 0; p < 4; p++) {
161  MVertex *tmp = pos.find(x[p], y[p], z[p]);
162  if(!tmp) {
163  Msg::Error("Could not find extruded node (%.16g, %.16g, %.16g) "
164  "in surface %d",
165  x[p], y[p], z[p], to->tag());
166  return;
167  }
168  verts.push_back(tmp);
169  }
170  createQuaTri(verts, to, constrainedEdges, from->lines[i],
171  tri_quad_flag);
172  }
173  }
174  }
175 }
176 
177 static void copyMesh(GFace *from, GFace *to, MVertexRTree &pos)
178 {
180 
181  // interior vertices
182  std::vector<MVertex *> mesh_vertices = from->mesh_vertices;
183 
184  // add all embedded vertices
185  std::vector<MVertex *> embedded = from->getEmbeddedMeshVertices();
186  mesh_vertices.insert(mesh_vertices.end(), embedded.begin(), embedded.end());
187 
188  // create extruded vertices
189  for(std::size_t i = 0; i < mesh_vertices.size(); i++) {
190  MVertex *v = mesh_vertices[i];
191  double x = v->x(), y = v->y(), z = v->z();
192  ep->Extrude(ep->mesh.NbLayer - 1, ep->mesh.NbElmLayer[ep->mesh.NbLayer - 1],
193  x, y, z);
194  MVertex *newv = pos.find(x, y, z);
195  if(!newv) {
196  if(to->geomType() != GEntity::DiscreteSurface &&
198  SPoint3 xyz(x, y, z);
199  SPoint2 uv = to->parFromPoint(xyz);
200  newv = new MFaceVertex(x, y, z, to, uv[0], uv[1]);
201  }
202  else {
203  newv = new MVertex(x, y, z, to);
204  }
205  to->mesh_vertices.push_back(newv);
206  pos.insert(newv);
207  }
208  }
209 
210 #if defined(HAVE_QUADTRI)
211  // if performing QuadToTri mesh, cannot simply copy the mesh from the source.
212  // The vertices and triangles can be copied directly though. First, of
213  // course, do some checks and make sure this is a valid QuadToTri top surface
214  // before engaging in QuadToTri meshing.
215  int quadToTri = NO_QUADTRI;
216  bool detectQuadToTriTop = false;
217  int quadToTri_valid =
218  IsValidQuadToTriTop(to, &quadToTri, &detectQuadToTriTop);
219  bool is_toroidal = quadToTri_valid >= 2 ? true : false;
220  bool is_noaddverts = quadToTri_valid == 3 ? true : false;
221  if(detectQuadToTriTop && !quadToTri_valid && !is_toroidal) {
222  Msg::Error("Mesh of QuadToTri top surface %d likely has errors", to->tag());
223  }
224 
225  // if this is toroidal No New Vertices QuadToTri, then replace the root
226  // dependency face's boundary quads with triangles for better meshing.
227  if(is_toroidal && is_noaddverts) {
228  GFace *root = findRootSourceFaceForFace(from);
229  if(root == from) {
230  ReplaceBndQuadsInFace(root);
231  Msg::Warning(
232  "To facilitate QuadToTri interface on surface %d, source "
233  "surface %d was re-meshed with all triangles on boundary. "
234  "To avoid this, use QuadTriAddVerts instead of QuadTriNoNewVerts",
235  to->tag(), root->tag());
236  }
237  }
238 #endif
239 
240  // create triangle elements
241  for(std::size_t i = 0; i < from->triangles.size(); i++) {
242  std::vector<MVertex *> verts;
243  for(int j = 0; j < 3; j++) {
244  MVertex *v = from->triangles[i]->getVertex(j);
245  double x = v->x(), y = v->y(), z = v->z();
246  ep->Extrude(ep->mesh.NbLayer - 1,
247  ep->mesh.NbElmLayer[ep->mesh.NbLayer - 1], x, y, z);
248  MVertex *tmp = pos.find(x, y, z);
249  if(!tmp) {
250  Msg::Error(
251  "Could not find extruded node (%.16g, %.16g, %.16g) in surface %d", x,
252  y, z, to->tag());
253  return;
254  }
255  verts.push_back(tmp);
256  }
257  addTriangle(verts[0], verts[1], verts[2], to);
258  }
259 
260 #if defined(HAVE_QUADTRI)
261  // Add triangles for divided quads for QuadTri. If quadtotri and not part of a
262  // toroidal extrusion, mesh the top surface accordingly
263  if(detectQuadToTriTop && !is_toroidal) {
264  if(!MeshQuadToTriTopSurface(from, to, pos))
265  Msg::Error("Mesh of QuadToTri top surface %d failed", to->tag());
266  return;
267  }
268 #endif
269 
270  // create quadrangle elements if NOT QuadToTri and NOT toroidal
271  for(std::size_t i = 0; i < from->quadrangles.size(); i++) {
272  std::vector<MVertex *> verts;
273  for(int j = 0; j < 4; j++) {
274  MVertex *v = from->quadrangles[i]->getVertex(j);
275  double x = v->x(), y = v->y(), z = v->z();
276  ep->Extrude(ep->mesh.NbLayer - 1,
277  ep->mesh.NbElmLayer[ep->mesh.NbLayer - 1], x, y, z);
278  MVertex *tmp = pos.find(x, y, z);
279  if(!tmp) {
280  Msg::Error(
281  "Could not find extruded node (%.16g, %.16g, %.16g) in surface %d", x,
282  y, z, to->tag());
283  return;
284  }
285  verts.push_back(tmp);
286  }
287  addQuadrangle(verts[0], verts[1], verts[2], verts[3], to);
288  }
289 }
290 
292  GFace *gf, std::set<std::pair<MVertex *, MVertex *> > *constrainedEdges)
293 {
295 
296  if(!ep || !ep->mesh.ExtrudeMesh) return 0;
297 
298  Msg::Info("Meshing surface %d (Extruded)", gf->tag());
299 
300  // build an rtree with all the vertices on the face and its boundary
301  MVertexRTree pos(CTX::instance()->geom.tolerance * CTX::instance()->lc);
302  pos.insert(gf->mesh_vertices);
303  std::vector<GEdge *> const &edges = gf->edges();
304  for(auto it = edges.begin(); it != edges.end(); it++) {
305  pos.insert((*it)->mesh_vertices);
306  if((*it)->getBeginVertex())
307  pos.insert((*it)->getBeginVertex()->mesh_vertices);
308  if((*it)->getEndVertex()) pos.insert((*it)->getEndVertex()->mesh_vertices);
309  }
310  std::vector<MVertex *> embedded = gf->getEmbeddedMeshVertices();
311  pos.insert(embedded);
312 
313  if(ep->geo.Mode == EXTRUDED_ENTITY) {
314  // surface is extruded from a curve
315  GEdge *from = gf->model()->getEdgeByTag(std::abs(ep->geo.Source));
316  if(!from) {
317  Msg::Error("Unknown source curve %d for extrusion", ep->geo.Source);
318  return 0;
319  }
320  extrudeMesh(from, gf, pos, constrainedEdges);
321  }
322  else {
323  // surface is a copy of another surface (the "top" of the extrusion)
324  GFace *from = gf->model()->getFaceByTag(std::abs(ep->geo.Source));
325  if(!from) {
326  Msg::Error("Unknown source surface %d for extrusion", ep->geo.Source);
327  return 0;
328  }
329  else if(from->geomType() != GEntity::DiscreteSurface &&
330  from->meshStatistics.status != GFace::DONE) {
331  // cannot mesh the face yet (the source face is not meshed):
332  // will do it later
333  return 1;
334  }
335  copyMesh(from, gf, pos);
336  if(gf->getMeshMaster() == from) {
337  // explicit periodic constraint, to store node correspondence
338  gf->setMeshMaster(from, gf->affineTransform);
339  }
340  }
341 
343  return 1;
344 }
MTriangle.h
GEntity::BoundaryLayerSurface
@ BoundaryLayerSurface
Definition: GEntity.h:116
extrudeMesh
static void extrudeMesh(GEdge *from, GFace *to, MVertexRTree &pos, std::set< std::pair< MVertex *, MVertex * > > *constrainedEdges)
Definition: meshGFaceExtruded.cpp:86
GEntity::affineTransform
std::vector< double > affineTransform
Definition: GEntity.h:403
GFace::edges
virtual std::vector< GEdge * > const & edges() const
Definition: GFace.h:121
GFace::status
GEntity::MeshGenerationStatus status
Definition: GFace.h:395
MEdgeVertex::bl_data
MVertexBoundaryLayerData * bl_data
Definition: MVertex.h:142
NO_QUADTRI
#define NO_QUADTRI
Definition: GmshDefines.h:263
GFace
Definition: GFace.h:33
GFace::triangles
std::vector< MTriangle * > triangles
Definition: GFace.h:428
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
GEdge::lines
std::vector< MLine * > lines
Definition: GEdge.h:42
GEntity::model
GModel * model() const
Definition: GEntity.h:277
SPoint2
Definition: SPoint2.h:12
MVertex
Definition: MVertex.h:24
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
MVertex::z
double z() const
Definition: MVertex.h:62
GFace::extrude
ExtrudeParams * extrude
Definition: GFace.h:357
SPoint3
Definition: SPoint3.h:14
GModel::getFaceByTag
GFace * getFaceByTag(int n) const
Definition: GModel.cpp:326
GFace::meshAttributes
struct GFace::@18 meshAttributes
GModel::getEdgeByTag
GEdge * getEdgeByTag(int n) const
Definition: GModel.cpp:336
GmshMessage.h
copyMesh
static void copyMesh(GFace *from, GFace *to, MVertexRTree &pos)
Definition: meshGFaceExtruded.cpp:177
MLine.h
edges
static int edges[6][2]
Definition: meshGRegionLocalMeshMod.cpp:23
MeshExtrudedSurface
int MeshExtrudedSurface(GFace *gf, std::set< std::pair< MVertex *, MVertex * > > *constrainedEdges)
Definition: meshGFaceExtruded.cpp:291
ExtrudeParams::geo
struct ExtrudeParams::@15 geo
createQuaTri
static void createQuaTri(std::vector< MVertex * > &v, GFace *to, std::set< std::pair< MVertex *, MVertex * > > *constrainedEdges, MLine *source, int tri_quad_flag)
Definition: meshGFaceExtruded.cpp:33
GEntity::getMeshMaster
GEntity * getMeshMaster() const
Definition: GEntity.h:291
GFace::quadrangles
std::vector< MQuadrangle * > quadrangles
Definition: GFace.h:429
GEntity::DiscreteCurve
@ DiscreteCurve
Definition: GEntity.h:104
MLine
Definition: MLine.h:21
CTX::instance
static CTX * instance()
Definition: Context.cpp:122
ExtrudeParams::mesh
struct ExtrudeParams::@14 mesh
MVertexBoundaryLayerData::addChildrenFamily
void addChildrenFamily(const std::vector< MVertex * > &family)
Definition: MVertexBoundaryLayerData.cpp:31
GFace::meshStatistics
struct GFace::@19 meshStatistics
GEntity::mesh_vertices
std::vector< MVertex * > mesh_vertices
Definition: GEntity.h:56
MEdgeVertex
Definition: MVertex.h:137
EXTRUDED_ENTITY
#define EXTRUDED_ENTITY
Definition: ExtrudeParams.h:17
MVertexRTree::insert
MVertex * insert(MVertex *v, bool warnIfExists=false, std::set< MVertex *, MVertexPtrLessThan > *duplicates=nullptr)
Definition: MVertexRTree.h:38
CTX::lc
double lc
Definition: Context.h:234
GEntity::DONE
@ DONE
Definition: GEntity.h:130
ExtrudeParams::NbLayer
int NbLayer
Definition: ExtrudeParams.h:39
ExtrudeParams.h
GFace::parFromPoint
virtual SPoint2 parFromPoint(const SPoint3 &, bool onSurface=true, bool convTestXYZ=false) const
Definition: GFace.cpp:1254
quadToTri
void quadToTri(double xi, double eta, double *r, double *s, double *J)
Definition: GaussLegendreSimplex.cpp:22
GEntity::geomType
virtual GeomType geomType() const
Definition: GEntity.h:238
ExtrudeParams::Recombine
bool Recombine
Definition: ExtrudeParams.h:37
addTriangle
static void addTriangle(MVertex *v1, MVertex *v2, MVertex *v3, GFace *to)
Definition: meshGFaceExtruded.cpp:21
ExtrudeParams::Mode
int Mode
Definition: ExtrudeParams.h:49
ExtrudeParams::NbElmLayer
std::vector< int > NbElmLayer
Definition: ExtrudeParams.h:40
GEntity::tag
int tag() const
Definition: GEntity.h:280
MFaceVertex
Definition: MVertex.h:168
MVertexRTree.h
ExtrudeParams::Extrude
void Extrude(int iLayer, int iElemLayer, double &dx, double &dy, double &dz)
Definition: ExtrudeParams.cpp:51
ExtrudeParams::ExtrudeMesh
bool ExtrudeMesh
Definition: ExtrudeParams.h:36
addQuadrangle
static void addQuadrangle(MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, GFace *to)
Definition: meshGFaceExtruded.cpp:26
MTriangle
Definition: MTriangle.h:26
GEntity::DiscreteSurface
@ DiscreteSurface
Definition: GEntity.h:117
ExtrudeParams::Source
int Source
Definition: ExtrudeParams.h:51
Context.h
MVertexRTree::find
MVertex * find(double x, double y, double z)
Definition: MVertexRTree.h:70
z
const double z
Definition: GaussQuadratureQuad.cpp:56
MQuadrangle.h
GEdge
Definition: GEdge.h:26
MVertexBoundaryLayerData
Definition: MVertexBoundaryLayerData.h:18
GFace::setMeshMaster
void setMeshMaster(GFace *master, const std::vector< double > &)
Definition: GFace.cpp:2222
MVertexRTree
Definition: MVertexRTree.h:16
GModel.h
MVertex::y
double y() const
Definition: MVertex.h:61
GFace::getEmbeddedMeshVertices
std::vector< MVertex * > getEmbeddedMeshVertices(bool force=false) const
Definition: GFace.cpp:369
ExtrudeParams
Definition: ExtrudeParams.h:26
MQuadrangle
Definition: MQuadrangle.h:26
MVertex::x
double x() const
Definition: MVertex.h:60