gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
meshGEdge.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 "meshGEdge.h"
7 #include "BackgroundMeshTools.h"
8 #include "Context.h"
9 #include "Field.h"
10 #include "GEdge.h"
11 #include "GModel.h"
12 #include "GmshConfig.h"
13 #include "GmshMessage.h"
14 #include "MLine.h"
15 #include "Numeric.h"
16 #include "OS.h"
17 #include "STensor3.h"
18 #include "boundaryLayersData.h"
19 #include "discreteEdge.h"
20 
21 typedef struct
22 {
23  int Num;
24  // t is the local coordinate of the point
25  // lc is x'(t)/h(x(t))
26  // p is the value of the primitive
27  // xp is the norm of the tangent vector
28  double t, lc, p, xp;
29 } IntPoint;
30 
31 static double smoothPrimitive(GEdge *ge, double alpha, std::vector<IntPoint> &Points)
32 {
33  int ITER = 0;
34  while (1)
35  {
36  int count1 = 0;
37  int count2 = 0;
38 
39  // use a gauss-seidel iteration; iterate forward and then backward;
40  // convergence is usually very fast
41  for (std::size_t i = 1; i < Points.size(); i++)
42  {
43  double dh = (Points[i].xp / Points[i].lc - Points[i - 1].xp / Points[i - 1].lc);
44  double dt = Points[i].t - Points[i - 1].t;
45  double dhdt = dh / dt;
46  if (dhdt / Points[i].xp > (alpha - 1.) * 1.01)
47  {
48  double hnew = Points[i - 1].xp / Points[i - 1].lc + dt * (alpha - 1) * Points[i].xp;
49  Points[i].lc = Points[i].xp / hnew;
50  count1++;
51  }
52  }
53 
54  for (int i = Points.size() - 1; i > 0; i--)
55  {
56  double dh = (Points[i - 1].xp / Points[i - 1].lc - Points[i].xp / Points[i].lc);
57  double dt = std::abs(Points[i - 1].t - Points[i].t);
58  double dhdt = dh / dt;
59  if (dhdt / Points[i - 1].xp > (alpha - 1.) * 1.01)
60  {
61  double hnew = Points[i].xp / Points[i].lc + dt * (alpha - 1) * Points[i].xp;
62  Points[i - 1].lc = Points[i - 1].xp / hnew;
63  count2++;
64  }
65  }
66 
67  ++ITER;
68  if (ITER > 2000)
69  break;
70  if (!(count1 + count2))
71  break;
72  }
73 
74  // recompute the primitive
75  for (std::size_t i = 1; i < Points.size(); i++)
76  {
77  IntPoint &pt2 = Points[i];
78  IntPoint &pt1 = Points[i - 1];
79  pt2.p = pt1.p + (pt2.t - pt1.t) * 0.5 * (pt2.lc + pt1.lc);
80  }
81  return Points[Points.size() - 1].p;
82 }
83 
84 struct F_LcB
85 {
86  double operator()(GEdge *ge, double t)
87  {
88  GPoint p = ge->point(t);
89  return BGM_MeshSize(ge, t, 0, p.x(), p.y(), p.z());
90  }
91 };
92 
93 struct F_Lc
94 {
95  double operator()(GEdge *ge, double t)
96  {
97  GPoint p = ge->point(t);
98  Range<double> bounds = ge->parBounds(0);
99  double t_begin = bounds.low();
100  double t_end = bounds.high();
101  double lc_here = 1.e22;
102  if (t == t_begin && ge->getBeginVertex())
103  lc_here = BGM_MeshSize(ge->getBeginVertex(), t, 0, p.x(), p.y(), p.z());
104  else if (t == t_end && ge->getEndVertex())
105  lc_here = BGM_MeshSize(ge->getEndVertex(), t, 0, p.x(), p.y(), p.z());
106 
107  lc_here = std::min(lc_here, BGM_MeshSize(ge, t, 0, p.x(), p.y(), p.z()));
108  SVector3 der = ge->firstDer(t);
109  return norm(der) / lc_here;
110  }
111 };
112 
114 {
115  double operator()(GEdge *ge, double t)
116  {
117  GPoint p = ge->point(t);
118  SMetric3 lc_here;
119 
120  Range<double> bounds = ge->parBounds(0);
121  double t_begin = bounds.low();
122  double t_end = bounds.high();
123 
124  if (t == t_begin && ge->getBeginVertex())
125  lc_here = BGM_MeshMetric(ge->getBeginVertex(), t, 0, p.x(), p.y(), p.z());
126  else if (t == t_end && ge->getEndVertex())
127  lc_here = BGM_MeshMetric(ge->getEndVertex(), t, 0, p.x(), p.y(), p.z());
128  else
129  lc_here = BGM_MeshMetric(ge, t, 0, p.x(), p.y(), p.z());
130 
131  FieldManager *fields = ge->model()->getFields();
132  for (int i = 0; i < fields->getNumBoundaryLayerFields(); ++i)
133  {
134  Field *bl_field = fields->get(fields->getBoundaryLayerField(i));
135  if (bl_field == nullptr)
136  continue;
137  BoundaryLayerField *blf = dynamic_cast<BoundaryLayerField *>(bl_field);
138  if (blf->isEdgeBL(ge->tag()))
139  break;
140  SMetric3 lc_bgm;
141  blf->computeFor1dMesh(p.x(), p.y(), p.z(), lc_bgm);
142  lc_here = intersection_conserveM1(lc_here, lc_bgm);
143  }
144 
145  SVector3 der = ge->firstDer(t);
146  return std::sqrt(dot(der, lc_here, der));
147  }
148 };
149 
150 // static double dfbeta2 (double t, double beta){
151 // double ratio = (1+beta)/(beta-1);
152 // double zlog = log(ratio);
153 // return 1.-acosh(beta*zlog/t - 1.0)/zlog;
154 // return beta*zlog / (1+cosh(zlog*(1-t)));
155 //}
156 
157 static double dfbeta(double t, double beta)
158 {
159  double ratio = (1 + beta) / (beta - 1);
160  double zlog = log(ratio);
161  return 2 * beta / ((1 + beta - t) * (-1 + beta + t) * zlog);
162 }
163 
165 {
166  double operator()(GEdge *ge, double t_)
167  {
168  double length = ge->length();
169  if (length == 0.0)
170  {
171  Msg::Error("Zero-length curve %d in transfinite mesh", ge->tag());
172  return 1.;
173  }
174 
175  SVector3 der = ge->firstDer(t_);
176  double d = norm(der);
177  double coef = ge->meshAttributes.coeffTransfinite;
178  int type = ge->meshAttributes.typeTransfinite;
179  int atype = std::abs(type);
180  int nbpt = ge->meshAttributes.nbPointsTransfinite;
181 
182  if (CTX::instance()->mesh.flexibleTransfinite && CTX::instance()->mesh.lcFactor)
183  nbpt /= CTX::instance()->mesh.lcFactor;
184 
185  Range<double> bounds = ge->parBounds(0);
186  double t_begin = bounds.low();
187  double t_end = bounds.high();
188  double t = (t_ - t_begin) / (t_end - t_begin);
189 
190  double val;
191 
192  if (coef <= 0.0 || coef == 1.0 || (atype == 3 && coef < 1.))
193  {
194  // coef < 0 should never happen
195  val = d * coef / ge->length();
196  }
197  else
198  {
199  switch (atype)
200  {
201  case 1:
202  {
203  // geometric progression ar^i; Sum of n terms = length = a (r^n-1)/(r-1)
204  double r = (gmsh_sign(type) >= 0) ? coef : 1. / coef;
205  double a = length * (r - 1.) / (std::pow(r, nbpt - 1.) - 1.);
206  int i = (int)(std::log(t * length / a * (r - 1.) + 1.) / std::log(r));
207  val = d / (a * std::pow(r, (double)i));
208  }
209  break;
210 
211  case 2:
212  {
213  // "bump"
214  double a;
215  if (coef > 1.0)
216  {
217  a = -4. * std::sqrt(coef - 1.) * std::atan2(1.0, std::sqrt(coef - 1.)) / ((double)nbpt * length);
218  }
219  else
220  {
221  a = 2. * std::sqrt(1. - coef) *
222  std::log(std::abs((1. + 1. / std::sqrt(1. - coef)) / (1. - 1. / std::sqrt(1. - coef)))) /
223  ((double)nbpt * length);
224  }
225  double b = -a * length * length / (4. * (coef - 1.));
226  val = d / (-a * std::pow(t * length - (length)*0.5, 2) + b);
227  break;
228  }
229  case 3:
230  {
231  // "beta" law
232  if (type < 0)
233  val = dfbeta(1. - t, coef);
234  else
235  val = dfbeta(t, coef);
236  break;
237  }
238  case 4:
239  {
240  // standard boundary layer progression: TODO
241  val = d / (length * t);
242  break;
243  }
244  default:
245  Msg::Warning("Unknown case in Transfinite Line mesh");
246  val = 1.;
247  break;
248  }
249  }
250  return val;
251  }
252 };
253 
254 struct F_One
255 {
256  double operator()(GEdge *ge, double t)
257  {
258  SVector3 der = ge->firstDer(t);
259  return norm(der);
260  }
261 };
262 
263 static double trapezoidal(IntPoint *const P1, IntPoint *const P2)
264 {
265  return 0.5 * (P1->lc + P2->lc) * (P2->t - P1->t);
266 }
267 
268 template <typename function>
269 static void RecursiveIntegration(GEdge *ge, IntPoint *from, IntPoint *to, function f, std::vector<IntPoint> &Points,
270  double Prec, int *depth)
271 {
272  IntPoint P, p1;
273 
274  (*depth)++;
275 
276  P.t = 0.5 * (from->t + to->t);
277  P.lc = f(ge, P.t);
278 
279  double const val1 = trapezoidal(from, to);
280  double const val2 = trapezoidal(from, &P);
281  double const val3 = trapezoidal(&P, to);
282  double const err = std::abs(val1 - val2 - val3);
283 
284  if (((err < Prec) && (*depth > 7)) || (*depth > 25))
285  {
286  p1 = Points.back();
287  P.p = p1.p + val2;
288  Points.push_back(P);
289 
290  p1 = Points.back();
291  to->p = p1.p + val3;
292  Points.push_back(*to);
293  }
294  else
295  {
296  RecursiveIntegration(ge, from, &P, f, Points, Prec, depth);
297  RecursiveIntegration(ge, &P, to, f, Points, Prec, depth);
298  }
299 
300  (*depth)--;
301 }
302 
303 template <typename function>
304 static double Integration(GEdge *ge, double t1, double t2, function f, std::vector<IntPoint> &Points, double Prec)
305 {
306  IntPoint from, to;
307 
308  int depth = 0;
309 
310  from.t = t1;
311  from.lc = f(ge, from.t);
312  from.p = 0.0;
313  Points.push_back(from);
314 
315  to.t = t2;
316  to.lc = f(ge, to.t);
317 
318  RecursiveIntegration(ge, &from, &to, f, Points, Prec, &depth);
319 
320  return Points.back().p;
321 }
322 
323 static SPoint3 transform(MVertex *vsource, const std::vector<double> &tfo)
324 {
325  double ps[4] = {vsource->x(), vsource->y(), vsource->z(), 1.};
326  double res[4] = {0., 0., 0., 0.};
327  int idx = 0;
328  for (int i = 0; i < 4; i++)
329  for (int j = 0; j < 4; j++)
330  res[i] += tfo[idx++] * ps[j];
331 
332  return SPoint3(res[0], res[1], res[2]);
333 }
334 
335 static void copyMesh(GEdge *from, GEdge *to, int direction)
336 {
337  if (!from->getBeginVertex() || !from->getEndVertex() || !to->getBeginVertex() || !to->getEndVertex())
338  {
339  Msg::Error("Cannot copy mesh on curves without begin/end points");
340  return;
341  }
342 
343  Range<double> u_bounds = from->parBounds(0);
344  double u_min = u_bounds.low();
345  double u_max = u_bounds.high();
346 
347  Range<double> to_u_bounds = to->parBounds(0);
348  double to_u_min = to_u_bounds.low();
349 
350  // include begin and end point to avoid conflicts when realigning
351  MVertex *vt0 = to->getBeginVertex()->mesh_vertices[0];
352  MVertex *vt1 = to->getEndVertex()->mesh_vertices[0];
353  MVertex *vs0 = from->getBeginVertex()->mesh_vertices[0];
354  MVertex *vs1 = from->getEndVertex()->mesh_vertices[0];
355 
356  to->correspondingVertices[vt0] = direction > 0 ? vs0 : vs1;
357  to->correspondingVertices[vt1] = direction > 0 ? vs1 : vs0;
358 
359  for (std::size_t i = 0; i < from->mesh_vertices.size(); i++)
360  {
361  int index = (direction < 0) ? (from->mesh_vertices.size() - 1 - i) : i;
362  MVertex *v = from->mesh_vertices[index];
363  GPoint gp;
364  double newu;
365  if (to->affineTransform.size() < 16)
366  {
367  // assume identical parametrisations (dangerous...)
368  double u;
369  v->getParameter(0, u);
370  newu = (direction > 0) ? (u - u_min + to_u_min) : (u_max - u + to_u_min);
371  gp = to->point(newu);
372  }
373  else
374  {
375  SPoint3 p = transform(v, to->affineTransform);
376  // for non-exact periodic curves we could use closestPoint; just use
377  // Mesh.HighOrderPeriodic=2, which will do that
378  newu = to->parFromPoint(p);
379  gp = to->point(newu);
380  // gp = to->closestPoint(p, newu);
381  }
382  MEdgeVertex *vv = new MEdgeVertex(gp.x(), gp.y(), gp.z(), to, newu);
383  to->mesh_vertices.push_back(vv);
384  to->correspondingVertices[vv] = v;
385  }
386  for (std::size_t i = 0; i < to->mesh_vertices.size() + 1; i++)
387  {
388  MVertex *v0 = (i == 0) ? to->getBeginVertex()->mesh_vertices[0] : to->mesh_vertices[i - 1];
389  MVertex *v1 = (i == to->mesh_vertices.size()) ? to->getEndVertex()->mesh_vertices[0] : to->mesh_vertices[i];
390  to->lines.push_back(new MLine(v0, v1));
391  }
392 }
393 
394 static void fillCorrespondingNodes(GEdge *from, GEdge *to, int direction)
395 {
396  if (!from->getBeginVertex() || !from->getEndVertex() || !to->getBeginVertex() || !to->getEndVertex())
397  {
398  Msg::Error("Cannot fill corresponding nodes on curves without begin/end points");
399  return;
400  }
401 
402  // include begin and end point to avoid conflicts when realigning
403  MVertex *vt0 = to->getBeginVertex()->mesh_vertices[0];
404  MVertex *vt1 = to->getEndVertex()->mesh_vertices[0];
405  MVertex *vs0 = from->getBeginVertex()->mesh_vertices[0];
406  MVertex *vs1 = from->getEndVertex()->mesh_vertices[0];
407 
408  to->correspondingVertices[vt0] = direction > 0 ? vs0 : vs1;
409  to->correspondingVertices[vt1] = direction > 0 ? vs1 : vs0;
410 
411  if (to->mesh_vertices.size() != from->mesh_vertices.size())
412  {
413  Msg::Error("Incompatible meshes to fill node correspondance");
414  return;
415  }
416 
417  for (std::size_t i = 0; i < from->mesh_vertices.size(); i++)
418  {
419  int index = (direction < 0) ? (from->mesh_vertices.size() - 1 - i) : i;
420  MVertex *v = from->mesh_vertices[index];
421  // FIXME: verify that the nodes follow the transformation!
422  to->correspondingVertices[to->mesh_vertices[i]] = v;
423  }
424 }
425 
427 {
428  if (ge->isFullyDiscrete())
429  return;
430  ge->deleteMesh();
432 }
433 
434 /*
435 static void printFandPrimitive(int tag, std::vector<IntPoint> &Points)
436 {
437  char name[256];
438  sprintf(name, "line%d.dat", tag);
439  FILE *f = Fopen(name, "w");
440  if(!f) return;
441  double l = 0;
442  for (std::size_t i = 0; i < Points.size(); i++){
443  const IntPoint &P = Points[i];
444  if(i) l += (P.t - Points[i-1].t) * P.xp;
445  fprintf(f, "%g %g %g %g %g\n", P.t, P.xp/P.lc, P.p, P.lc, l);
446  }
447  fclose(f);
448 }
449 */
450 
451 // new algo for recombining + splitting
452 static int increaseN(int N)
453 {
454  if (((N + 1) / 2 - 1) % 2 != 0)
455  return N + 2;
456  return N;
457 }
458 
459 // ensure not to have points that are too close to each other.
460 // can be caused by a coarse 1D mesh or by a noisy curve
461 static void filterPoints(GEdge *ge, int nMinimumPoints)
462 {
463  if (ge->mesh_vertices.empty())
464  return;
466  return;
467 
468  bool forceOdd = false;
471  {
472  if (CTX::instance()->mesh.recombineAll)
473  {
474  forceOdd = true;
475  }
476  }
477 
478  if (!ge->getBeginVertex() || !ge->getEndVertex())
479  return;
480 
481  MVertex *v0 = ge->getBeginVertex()->mesh_vertices[0];
482  std::vector<std::pair<double, MVertex *>> lengths;
483  for (std::size_t i = 0; i < ge->mesh_vertices.size(); i++)
484  {
485  MEdgeVertex *v = dynamic_cast<MEdgeVertex *>(ge->mesh_vertices[i]);
486  if (!v)
487  {
488  Msg::Error("Node not classified on curve in 1D mesh filtering");
489  return;
490  }
491  double d = distance(v, v0);
492  double t;
493  v->getParameter(0, t);
494  if (i != 0)
495  {
496  double t0;
497  if (v0->onWhat()->dim() == 0)
498  {
499  // Vertex is begin point
500  t0 = ge->parFromPoint(SPoint3(v0->x(), v0->y(), v0->z()));
501  }
502  else
503  v0->getParameter(0, t0);
504 
505  t = 0.5 * (t + t0);
506  }
507  double lc = F_LcB()(ge, t);
508  // double lc = v->getLc();
509  if (d < lc * .3)
510  {
511  lengths.push_back(std::make_pair(lc / d, v));
512  }
513  else
514  v0 = v;
515  }
516  std::sort(lengths.begin(), lengths.end());
517  int last = lengths.size();
518  if (forceOdd)
519  {
520  while (last % 2 != 0)
521  last--;
522  }
523  /*
524  if(CTX::instance()->mesh.algoRecombine == 2){
525  if(last < 4) last = 0;
526  while (last %4 != 0)last--;
527  }
528  else{
529  while (last %2 != 0)last--;
530  }
531  }
532  */
533 
534  bool filteringObservesMinimumN = (((int)ge->mesh_vertices.size() - last) >= nMinimumPoints);
535  if (filteringObservesMinimumN)
536  {
537  for (int i = 0; i < last; i++)
538  {
539  auto it = std::find(ge->mesh_vertices.begin(), ge->mesh_vertices.end(), lengths[i].second);
540 
541  if (it != ge->mesh_vertices.end())
542  {
543  ge->mesh_vertices.erase(it);
544  }
545  delete lengths[i].second;
546  }
547  }
548 }
549 
550 static void createPoints(GVertex *gv, GEdge *ge, BoundaryLayerField *blf, std::vector<MVertex *> &v,
551  const SVector3 &dir)
552 {
553  if (!ge->getBeginVertex() || !ge->getEndVertex())
554  return;
555 
556  const double hWall = blf->hWall(gv->tag());
557  double L = hWall;
558  double LEdge = distance(ge->getBeginVertex()->mesh_vertices[0], ge->getEndVertex()->mesh_vertices[0]);
559 
560  if (blf->betaLaw)
561  {
562  std::vector<double> t(blf->nb_divisions);
563  double zlog = log((1 + blf->beta) / (blf->beta - 1));
564  for (int i = 0; i < blf->nb_divisions; i++)
565  {
566  const double eta = (double)(i + 1) / blf->nb_divisions;
567  const double power = exp(zlog * (1. - eta));
568  const double ratio = (1. - power) / (1. + power);
569  t[i] = 1.0 + blf->beta * ratio;
570  }
571  for (int i = 0; i < blf->nb_divisions; i++)
572  {
573  double L = hWall * t[i] / t[0];
574  SPoint3 p(gv->x() + dir.x() * L, gv->y() + dir.y() * L, 0.0);
575  v.push_back(new MEdgeVertex(p.x(), p.y(), p.z(), ge, ge->parFromPoint(p), 0, blf->hFar));
576  }
577  }
578  else
579  {
580  while (1)
581  {
582  if (L > blf->thickness || L > LEdge * .4)
583  {
584  break;
585  }
586 
587  SPoint3 p(gv->x() + dir.x() * L, gv->y() + dir.y() * L, 0.0);
588  v.push_back(new MEdgeVertex(p.x(), p.y(), p.z(), ge, ge->parFromPoint(p), 0, blf->hFar));
589  int ith = v.size();
590  L += hWall * std::pow(blf->ratio, ith);
591  }
592  }
593 }
594 
595 static void addBoundaryLayerPoints(GEdge *ge, double &t_begin, double &t_end, std::vector<MVertex *> &_addBegin,
596  std::vector<MVertex *> &_addEnd)
597 {
598  _addBegin.clear();
599  _addEnd.clear();
600 
601  // t_begin/t_end may change the left/right parameter of the interval
602  // _addBegin/_addEnd : additional points @ left/right
603  FieldManager *fields = ge->model()->getFields();
604  int n = fields->getNumBoundaryLayerFields();
605 
606  if (n == 0)
607  return;
608 
609  if (!ge->getBeginVertex() || !ge->getEndVertex())
610  return;
611 
612  // Check if edge is a BL edge
613  for (int i = 0; i < n; ++i)
614  {
615  Field *bl_field = fields->get(fields->getBoundaryLayerField(i));
616  if (bl_field == nullptr)
617  continue;
618  BoundaryLayerField *blf = dynamic_cast<BoundaryLayerField *>(bl_field);
619  if (blf->isEdgeBL(ge->tag()))
620  return;
621  }
622 
623  SVector3 dir(ge->getEndVertex()->x() - ge->getBeginVertex()->x(),
624  ge->getEndVertex()->y() - ge->getBeginVertex()->y(),
625  ge->getEndVertex()->z() - ge->getBeginVertex()->z());
626  dir.normalize();
627  GVertex *gvb = ge->getBeginVertex();
628  GVertex *gve = ge->getEndVertex();
629 
630  // Check if extremity nodes are BL node
631  for (int i = 0; i < n; ++i)
632  {
633  Field *bl_field = fields->get(fields->getBoundaryLayerField(i));
634  if (bl_field == nullptr)
635  continue;
636  BoundaryLayerField *blf = dynamic_cast<BoundaryLayerField *>(bl_field);
637  blf->setupFor1d(ge->tag());
638 
639  if (blf->isEndNode(gvb->tag()))
640  {
641  if (ge->geomType() != GEntity::Line)
642  {
643  Msg::Error("Boundary layer end point %d should lie on a straight line", gvb->tag());
644  return;
645  }
646  if (_addBegin.size())
647  {
648  Msg::Error("Different boundary layers cannot touch each other");
649  return;
650  }
651  createPoints(gvb, ge, blf, _addBegin, dir);
652  if (!_addBegin.empty())
653  _addBegin[_addBegin.size() - 1]->getParameter(0, t_begin);
654  }
655  if (blf->isEndNode(gve->tag()))
656  {
657  if (ge->geomType() != GEntity::Line)
658  {
659  Msg::Error("Boundary layer end point %d should lie on a straight line", gve->tag());
660  return;
661  }
662  if (_addEnd.size())
663  {
664  Msg::Error("Different boundary layers cannot touch each other");
665  return;
666  }
667  createPoints(gve, ge, blf, _addEnd, dir * -1.0);
668  if (!_addEnd.empty())
669  _addEnd[_addEnd.size() - 1]->getParameter(0, t_end);
670  }
671  }
672 }
673 
674 int meshGEdgeProcessing(GEdge *ge, const double t_begin, double t_end, int &N, std::vector<IntPoint> &Points, double &a,
675  int &filterMinimumN)
676 {
678  return 0;
679  if (ge->meshAttributes.method == MESH_NONE)
680  return 0;
681  if (CTX::instance()->mesh.meshOnlyVisible && !ge->getVisibility())
682  return 0;
683  if (CTX::instance()->mesh.meshOnlyEmpty && ge->getNumMeshElements())
684  return 0;
685 
686  // first compute the length of the curve by integrating one
687  double length;
688  Points.clear();
689  if (ge->geomType() == GEntity::Line && ge->getBeginVertex() && ge->getBeginVertex() == ge->getEndVertex() &&
690  // do not consider closed lines as degenerated
691  (ge->position(0.5) - ge->getBeginVertex()->xyz()).norm() < CTX::instance()->geom.tolerance)
692  length = 0.0; // special case to avoid infinite loop in integration
693  else
694  length = Integration(ge, t_begin, t_end, F_One(), Points,
695  CTX::instance()->mesh.lcIntegrationPrecision * CTX::instance()->lc);
696  ge->setLength(length);
697  Points.clear();
698 
699  if (length < CTX::instance()->mesh.toleranceEdgeLength)
700  {
701  ge->setTooSmall(true);
702  }
703 
704  // Integrate detJ/lc du
705  filterMinimumN = 1;
706  if (length == 0. && CTX::instance()->mesh.toleranceEdgeLength == 0.)
707  {
708  Msg::Debug("Curve %d has a zero length", ge->tag());
709  a = 0.;
710  N = 1;
711  }
712  else if (ge->degenerate(0))
713  {
714  Msg::Debug("Curve %d is degenerated", ge->tag());
715  a = 0.;
716  N = 1;
717  }
719  {
720  // Transfinite (prescribed number of edges) but the points are positioned
721  // according to the standard size constraints (size map, etc)
722  a = Integration(ge, t_begin, t_end, F_Lc(), Points, CTX::instance()->mesh.lcIntegrationPrecision);
724  }
725  else if (ge->meshAttributes.method == MESH_TRANSFINITE)
726  {
727  a = Integration(ge, t_begin, t_end, F_Transfinite(), Points, CTX::instance()->mesh.lcIntegrationPrecision);
729  if (CTX::instance()->mesh.flexibleTransfinite && CTX::instance()->mesh.lcFactor)
730  N /= CTX::instance()->mesh.lcFactor;
731  }
732  else
733  {
734  if (CTX::instance()->mesh.algo2d == ALGO_2D_BAMG /* || blf*/)
735  {
736  a = Integration(ge, t_begin, t_end, F_Lc_aniso(), Points, CTX::instance()->mesh.lcIntegrationPrecision);
737  }
738  else
739  {
740  a = Integration(ge, t_begin, t_end, F_Lc(), Points, CTX::instance()->mesh.lcIntegrationPrecision);
741  }
742 
743  // we should maybe provide an option to disable the smoothing
744  for (std::size_t i = 0; i < Points.size(); i++)
745  {
746  IntPoint &pt = Points[i];
747  SVector3 der = ge->firstDer(pt.t);
748  pt.xp = der.norm();
749  }
750  if (CTX::instance()->mesh.algo2d != ALGO_2D_BAMG)
751  a = smoothPrimitive(ge, std::sqrt(CTX::instance()->mesh.smoothRatio), Points);
752  filterMinimumN = ge->minimumMeshSegments() + 1;
753  N = std::max(filterMinimumN, (int)(a + 1.99));
754  }
755 
756  // force odd number of points if blossom is used for recombination
759  {
760  std::vector<GFace *> const &faces = ge->faces();
761  if (CTX::instance()->mesh.recombineAll && faces.size())
762  {
763  if (N % 2 == 0)
764  N++;
765  if (CTX::instance()->mesh.algoRecombine == 2 || CTX::instance()->mesh.algoRecombine == 4)
766  N = increaseN(N);
767  }
768  else
769  {
770  for (auto it = faces.begin(); it != faces.end(); it++)
771  {
772  if ((*it)->meshAttributes.recombine)
773  {
774  if (N % 2 == 0)
775  N++;
776  if (CTX::instance()->mesh.algoRecombine == 2 || CTX::instance()->mesh.algoRecombine == 4)
777  N = increaseN(N);
778  break;
779  }
780  }
781  }
782  }
783 
784  return N;
785 }
786 
788 {
789  // debug stuff
790  if (CTX::instance()->debugSurface > 0)
791  {
792  std::vector<GFace *> f = ge->faces();
793  bool found = false;
794  for (size_t i = 0; i < f.size(); i++)
795  {
796  if (f[i]->tag() == CTX::instance()->debugSurface)
797  {
798  found = true;
799  }
800  }
801  if (!found)
802  return;
803  }
804 
805  ge->model()->setCurrentMeshEntity(ge);
806 
807  if (ge->degenerate(1))
808  {
810  return;
811  }
812 
814  return;
815  if (ge->meshAttributes.method == MESH_NONE)
816  return;
817  if (CTX::instance()->mesh.meshOnlyVisible && !ge->getVisibility())
818  return;
819  if (CTX::instance()->mesh.meshOnlyEmpty && ge->getNumMeshElements())
820  return;
821 
822  // destroy the mesh if it exists
823  deMeshGEdge dem;
824  dem(ge);
825 
826  if (MeshExtrudedCurve(ge))
827  {
828 
829  // if there is a periodic constraint, fill the corresponding node arrays
830  if (ge->getMeshMaster() != ge)
831  {
832  GEdge *gef = dynamic_cast<GEdge *>(ge->getMeshMaster());
834  }
835  return;
836  }
837 
838  if (ge->getMeshMaster() != ge)
839  {
840  GEdge *gef = dynamic_cast<GEdge *>(ge->getMeshMaster());
842  return;
843  Msg::Info("Meshing curve %d (%s) as a copy of curve %d", ge->tag(), ge->getTypeString().c_str(),
844  ge->getMeshMaster()->tag());
845  copyMesh(gef, ge, ge->masterOrientation);
847  return;
848  }
849 
850  Msg::Info("Meshing curve %d (%s)", ge->tag(), ge->getTypeString().c_str());
851 
852  // compute bounds
853  Range<double> bounds = ge->parBounds(0);
854  double t_begin = bounds.low();
855  double t_end = bounds.high();
856 
857  // if a BL is ending at one of the ends, then create specific points
858  std::vector<MVertex *> _addBegin, _addEnd;
859  addBoundaryLayerPoints(ge, t_begin, t_end, _addBegin, _addEnd);
860 
861  // integration to get length, number of points, etc
862  int N;
863  std::vector<IntPoint> Points;
864  double a;
865  int filterMinimumN;
866  meshGEdgeProcessing(ge, t_begin, t_end, N, Points, a, filterMinimumN);
867 
868  // printFandPrimitive(ge->tag(),Points);
869 
870  // if the curve is periodic and if the begin vertex is identical to
871  // the end vertex and if this vertex has only one model curve
872  // adjacent to it, then the vertex is not connecting any other
873  // curve. So, the mesh vertex and its associated geom vertex are not
874  // necessary at the same location
875 
876  // look if we are doing the STL triangulation
877  std::vector<MVertex *> &mesh_vertices = ge->mesh_vertices;
878 
879  GPoint beg_p, end_p;
880  if (!ge->getBeginVertex() || !ge->getEndVertex())
881  {
882  Msg::Warning("Skipping curve with no begin or end point");
883  return;
884  }
885  else if (ge->getBeginVertex() == ge->getEndVertex() && ge->getBeginVertex()->edges().size() == 1)
886  {
887  end_p = beg_p = ge->point(t_begin);
888  Msg::Debug("Meshing periodic closed curve (tag %i, %i points)", ge->tag(), N);
889  }
890  else
891  {
892  MVertex *v0 = ge->getBeginVertex()->mesh_vertices[0];
893  MVertex *v1 = ge->getEndVertex()->mesh_vertices[0];
894  beg_p = GPoint(v0->x(), v0->y(), v0->z());
895  end_p = GPoint(v1->x(), v1->y(), v1->z());
896  }
897 
898  // do not consider the first and the last vertex (those are not
899  // classified on this mesh edge)
900  if (N > 1)
901  {
902  const double b = a / static_cast<double>(N - 1);
903  int count = 1, NUMP = 1;
904  IntPoint P1, P2;
905  mesh_vertices.resize(N - 2);
906 
907  while (NUMP < N - 1)
908  {
909  P1 = Points[count - 1];
910  P2 = Points[count];
911  const double d = (double)NUMP * b;
912  if ((std::abs(P2.p) >= std::abs(d)) && (std::abs(P1.p) < std::abs(d)))
913  {
914  double const dt = P2.t - P1.t;
915  double const dlc = P2.lc - P1.lc;
916  double const dp = P2.p - P1.p;
917  double const t = P1.t + dt / dp * (d - P1.p);
918  SVector3 der = ge->firstDer(t);
919  const double d = norm(der);
920  double lc = d / (P1.lc + dlc / dp * (d - P1.p));
921  GPoint V = ge->point(t);
922  mesh_vertices[NUMP - 1] = new MEdgeVertex(V.x(), V.y(), V.z(), ge, t, 0, lc);
923  NUMP++;
924  }
925  else
926  {
927  count++;
928  }
929  }
930  mesh_vertices.resize(NUMP - 1);
931  }
932 
933  // Boundary Layer points are added
934  {
935  std::vector<MVertex *> vv;
936  vv.insert(vv.end(), _addBegin.begin(), _addBegin.end());
937  vv.insert(vv.end(), mesh_vertices.begin(), mesh_vertices.end());
938  for (std::size_t i = 0; i < _addEnd.size(); i++)
939  vv.push_back(_addEnd[_addEnd.size() - 1 - i]);
940  mesh_vertices = vv;
941  }
942 
945  if (_addBegin.empty() && _addEnd.empty())
946  filterPoints(ge, filterMinimumN - 2);
947 
948  std::vector<MLine *> &lines = ge->lines;
949 
950  for (std::size_t i = 0; i <= mesh_vertices.size(); i++)
951  {
952  MVertex *v0 = (i == 0) ? ge->getBeginVertex()->mesh_vertices[0] : mesh_vertices[i - 1];
953 
954  MVertex *v1 = (i == mesh_vertices.size()) ? ge->getEndVertex()->mesh_vertices[0] : mesh_vertices[i];
955  lines.push_back(new MLine(v0, v1));
956  }
957 
958  if (ge->getBeginVertex() == ge->getEndVertex() && ge->getBeginVertex()->edges().size() == 1)
959  {
960  MVertex *v0 = ge->getBeginVertex()->mesh_vertices[0];
961  v0->x() = beg_p.x();
962  v0->y() = beg_p.y();
963  v0->z() = beg_p.z();
964  }
965 
966  Msg::Debug("Meshing curve %d (%s): %li interior vertices", ge->tag(), ge->getTypeString().c_str(),
967  ge->mesh_vertices.size());
968 
970 }
971 
973 {
974  // apply user-specified mesh orientation constraints
975  if (ge->meshAttributes.reverseMesh)
976  for (std::size_t k = 0; k < ge->getNumMeshElements(); k++)
977  ge->getMeshElement(k)->reverse();
978 }
979 
981 {
982  Range<double> bounds = ge->parBounds(0);
983  double t_begin = bounds.low();
984  double t_end = bounds.high();
985 
986  int N = 0;
987  std::vector<IntPoint> Points;
988  double a = 0.;
989  int filterMinimumN = 1;
990  meshGEdgeProcessing(ge, t_begin, t_end, N, Points, a, filterMinimumN);
991  return N;
992 }
GEdge::setLength
void setLength(const double l)
Definition: GEdge.h:171
contextGeometryOptions::tolerance
double tolerance
Definition: Context.h:99
GEntity::affineTransform
std::vector< double > affineTransform
Definition: GEntity.h:403
Field.h
meshGEdgeProcessing
int meshGEdgeProcessing(GEdge *ge, const double t_begin, double t_end, int &N, std::vector< IntPoint > &Points, double &a, int &filterMinimumN)
Definition: meshGEdge.cpp:674
gmsh_sign
int gmsh_sign(T const &value)
Definition: Numeric.h:28
GEdge::getMeshElement
MElement * getMeshElement(std::size_t index) const
Definition: GEdge.cpp:173
BoundaryLayerField::hFar
double hFar
Definition: Field.h:204
dot
double dot(const SVector3 &a, const SMetric3 &m, const SVector3 &b)
Definition: STensor3.h:71
SMetric3
Definition: STensor3.h:17
GVertex::z
virtual double z() const =0
filterPoints
static void filterPoints(GEdge *ge, int nMinimumPoints)
Definition: meshGEdge.cpp:461
GPoint::y
double y() const
Definition: GPoint.h:22
distance
double distance(MVertex *v1, MVertex *v2)
Definition: MVertex.h:245
F_Lc::operator()
double operator()(GEdge *ge, double t)
Definition: meshGEdge.cpp:95
fillCorrespondingNodes
static void fillCorrespondingNodes(GEdge *from, GEdge *to, int direction)
Definition: meshGEdge.cpp:394
smoothPrimitive
static double smoothPrimitive(GEdge *ge, double alpha, std::vector< IntPoint > &Points)
Definition: meshGEdge.cpp:31
F_One
Definition: meshGEdge.cpp:255
IntPoint::t
double t
Definition: meshGEdge.cpp:28
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
GEdge::lines
std::vector< MLine * > lines
Definition: GEdge.h:42
GEntity::degenerate
virtual bool degenerate(int dim) const
Definition: GEntity.h:248
GEntity::model
GModel * model() const
Definition: GEntity.h:277
IntPoint::Num
int Num
Definition: meshGEdge.cpp:23
OS.h
Integration
static double Integration(GEdge *ge, double t1, double t2, function f, std::vector< IntPoint > &Points, double Prec)
Definition: meshGEdge.cpp:304
Msg::Debug
static void Debug(const char *fmt,...)
Definition: GmshMessage.cpp:752
MESH_TRANSFINITE
#define MESH_TRANSFINITE
Definition: GmshDefines.h:259
MVertex
Definition: MVertex.h:24
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
meshGEdgeTargetNumberOfPoints
int meshGEdgeTargetNumberOfPoints(GEdge *ge)
Definition: meshGEdge.cpp:980
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
MVertex::z
double z() const
Definition: MVertex.h:62
orientMeshGEdge::operator()
void operator()(GEdge *)
Definition: meshGEdge.cpp:972
GEdge::reverseMesh
bool reverseMesh
Definition: GEdge.h:259
SPoint3
Definition: SPoint3.h:14
LegendrePolynomials::f
void f(int n, double u, double *val)
Definition: orthogonalBasis.cpp:77
F_One::operator()
double operator()(GEdge *ge, double t)
Definition: meshGEdge.cpp:256
ALGO_2D_PACK_PRLGRMS
#define ALGO_2D_PACK_PRLGRMS
Definition: GmshDefines.h:245
Range::high
T high() const
Definition: Range.h:20
SVector3
Definition: SVector3.h:16
GVertex::edges
virtual std::vector< GEdge * > const & edges() const
Definition: GVertex.h:54
meshGEdge.h
MVertex::onWhat
GEntity * onWhat() const
Definition: MVertex.h:82
GEdge::length
double length() const
Definition: GEdge.h:170
BoundaryLayerField::computeFor1dMesh
void computeFor1dMesh(double x, double y, double z, SMetric3 &metr)
Definition: Field.cpp:2997
RecursiveIntegration
static void RecursiveIntegration(GEdge *ge, IntPoint *from, IntPoint *to, function f, std::vector< IntPoint > &Points, double Prec, int *depth)
Definition: meshGEdge.cpp:269
GmshMessage.h
MLine.h
MEdgeVertex::getParameter
virtual bool getParameter(int i, double &par) const
Definition: MVertex.h:153
GPoint
Definition: GPoint.h:13
GEntity::getMeshMaster
GEntity * getMeshMaster() const
Definition: GEntity.h:291
debugSurface
int debugSurface
Definition: meshGFace.cpp:3150
F_LcB::operator()
double operator()(GEdge *ge, double t)
Definition: meshGEdge.cpp:86
deMeshGEdge
Definition: meshGEdge.h:18
F_LcB
Definition: meshGEdge.cpp:85
MLine
Definition: MLine.h:21
IntPoint::p
double p
Definition: meshGEdge.cpp:28
GPoint::z
double z() const
Definition: GPoint.h:23
GEdge::setTooSmall
void setTooSmall(bool const b)
Definition: GEdge.h:183
CTX::instance
static CTX * instance()
Definition: Context.cpp:122
SPoint3::x
double x(void) const
Definition: SPoint3.h:125
GEdge.h
GEdge::firstDer
virtual SVector3 firstDer(double par) const =0
BoundaryLayerField::setupFor1d
void setupFor1d(int iE)
Definition: Field.cpp:2857
Range
Definition: Range.h:10
GEntity::mesh_vertices
std::vector< MVertex * > mesh_vertices
Definition: GEntity.h:56
boundaryLayersData.h
MEdgeVertex
Definition: MVertex.h:137
trapezoidal
static double trapezoidal(IntPoint *const P1, IntPoint *const P2)
Definition: meshGEdge.cpp:263
F_Transfinite
Definition: meshGEdge.cpp:165
GVertex
Definition: GVertex.h:23
GEntity::getTypeString
virtual std::string getTypeString()
Definition: GEntity.h:133
CTX::lc
double lc
Definition: Context.h:234
createPoints
static void createPoints(GVertex *gv, GEdge *ge, BoundaryLayerField *blf, std::vector< MVertex * > &v, const SVector3 &dir)
Definition: meshGEdge.cpp:550
meshGEdge::operator()
void operator()(GEdge *)
Definition: meshGEdge.cpp:787
norm
void norm(const double *vec, double *norm)
Definition: gmshLevelset.cpp:202
Numeric.h
FieldManager::get
Field * get(int id)
Definition: Field.cpp:74
BoundaryLayerField::nb_divisions
int nb_divisions
Definition: Field.h:206
GEntity::DONE
@ DONE
Definition: GEntity.h:130
BoundaryLayerField::thickness
double thickness
Definition: Field.h:204
BGM_MeshSize
double BGM_MeshSize(GEntity *ge, double U, double V, double X, double Y, double Z)
Definition: BackgroundMeshTools.cpp:255
GEdge::getBeginVertex
virtual GVertex * getBeginVertex() const
Definition: GEdge.h:63
GEntity::Line
@ Line
Definition: GEntity.h:92
MESH_NONE
#define MESH_NONE
Definition: GmshDefines.h:258
MElement::reverse
virtual void reverse()
Definition: MElement.h:308
FieldManager
Definition: Field.h:145
GEntity::geomType
virtual GeomType geomType() const
Definition: GEntity.h:238
GEdge::meshAttributes
struct GEdge::@16 meshAttributes
SVector3::norm
double norm() const
Definition: SVector3.h:33
SPoint3::y
double y(void) const
Definition: SPoint3.h:127
addBoundaryLayerPoints
static void addBoundaryLayerPoints(GEdge *ge, double &t_begin, double &t_end, std::vector< MVertex * > &_addBegin, std::vector< MVertex * > &_addEnd)
Definition: meshGEdge.cpp:595
CTX::mesh
contextMeshOptions mesh
Definition: Context.h:313
IntPoint::lc
double lc
Definition: meshGEdge.cpp:28
GModel::getFields
FieldManager * getFields()
Definition: GModel.h:325
GEdge::masterOrientation
int masterOrientation
Definition: GEdge.h:40
GEntity::tag
int tag() const
Definition: GEntity.h:280
BoundaryLayerField
Definition: Field.h:191
GEdge::position
virtual SVector3 position(double p) const
Definition: GEdge.h:128
GEntity::BoundaryLayerCurve
@ BoundaryLayerCurve
Definition: GEntity.h:103
GEdge::coeffTransfinite
double coeffTransfinite
Definition: GEdge.h:251
Field
Definition: Field.h:103
contextMeshOptions::flexibleTransfinite
int flexibleTransfinite
Definition: Context.h:34
SVector3::x
double x(void) const
Definition: SVector3.h:30
CTX::geom
contextGeometryOptions geom
Definition: Context.h:311
GEdge::faces
virtual std::vector< GFace * > faces() const
Definition: GEdge.h:113
GEdge::typeTransfinite
int typeTransfinite
Definition: GEdge.h:254
length
double length(Quaternion &q)
Definition: Camera.cpp:346
GVertex::x
virtual double x() const =0
transform
static SPoint3 transform(MVertex *vsource, const std::vector< double > &tfo)
Definition: meshGEdge.cpp:323
GVertex::y
virtual double y() const =0
GEdge::status
GEntity::MeshGenerationStatus status
Definition: GEdge.h:263
BoundaryLayerField::betaLaw
int betaLaw
Definition: Field.h:206
MVertex::getParameter
virtual bool getParameter(int i, double &par) const
Definition: MVertex.h:97
F_Lc_aniso
Definition: meshGEdge.cpp:114
GEdge::meshStatistics
struct GEdge::@17 meshStatistics
discreteEdge.h
increaseN
static int increaseN(int N)
Definition: meshGEdge.cpp:452
FieldManager::getBoundaryLayerField
int getBoundaryLayerField(int i)
Definition: Field.h:183
Context.h
GEdge::parBounds
virtual Range< double > parBounds(int i) const =0
SVector3::y
double y(void) const
Definition: SVector3.h:31
BoundaryLayerField::hWall
double hWall(int iV)
Definition: Field.h:249
GVertex::xyz
virtual SPoint3 xyz() const
Definition: GVertex.h:43
contextMeshOptions::lcFactor
double lcFactor
Definition: Context.h:21
contextMeshOptions::algo2d
int algo2d
Definition: Context.h:29
BoundaryLayerField::isEndNode
bool isEndNode(int iV) const
Definition: Field.h:244
F_Lc
Definition: meshGEdge.cpp:94
GEdge::point
virtual GPoint point(double p) const =0
GEdge::deleteMesh
virtual void deleteMesh()
Definition: GEdge.cpp:53
copyMesh
static void copyMesh(GEdge *from, GEdge *to, int direction)
Definition: meshGEdge.cpp:335
STensor3.h
BGM_MeshMetric
SMetric3 BGM_MeshMetric(GEntity *ge, double U, double V, double X, double Y, double Z)
Definition: BackgroundMeshTools.cpp:284
GEdge
Definition: GEdge.h:26
direction
static void direction(Vertex *v1, Vertex *v2, double d[3])
Definition: Geo.cpp:218
FieldManager::getNumBoundaryLayerFields
int getNumBoundaryLayerFields()
Definition: Field.h:179
SPoint3::z
double z(void) const
Definition: SPoint3.h:129
dfbeta
static double dfbeta(double t, double beta)
Definition: meshGEdge.cpp:157
BackgroundMeshTools.h
GModel.h
GEdge::getNumMeshElements
std::size_t getNumMeshElements() const
Definition: GEdge.h:201
MVertex::y
double y() const
Definition: MVertex.h:61
F_Lc_aniso::operator()
double operator()(GEdge *ge, double t)
Definition: meshGEdge.cpp:115
contextMeshOptions::algoRecombine
int algoRecombine
Definition: Context.h:30
GEdge::getEndVertex
virtual GVertex * getEndVertex() const
Definition: GEdge.h:64
GEdge::nbPointsTransfinite
int nbPointsTransfinite
Definition: GEdge.h:253
intersection_conserveM1
SMetric3 intersection_conserveM1(const SMetric3 &m1, const SMetric3 &m2)
Definition: STensor3.cpp:164
Range::low
T low() const
Definition: Range.h:18
GEntity::isFullyDiscrete
virtual bool isFullyDiscrete()
Definition: GEntity.h:256
GEntity::dim
virtual int dim() const
Definition: GEntity.h:196
IntPoint::xp
double xp
Definition: meshGEdge.cpp:28
BoundaryLayerField::ratio
double ratio
Definition: Field.h:204
GPoint::x
double x() const
Definition: GPoint.h:21
GEntity::getVisibility
virtual char getVisibility()
Definition: GEntity.cpp:35
GEntity::correspondingVertices
std::map< MVertex *, MVertex * > correspondingVertices
Definition: GEntity.h:406
GEntity::PENDING
@ PENDING
Definition: GEntity.h:130
IntPoint
Definition: meshGEdge.cpp:22
F_Transfinite::operator()
double operator()(GEdge *ge, double t_)
Definition: meshGEdge.cpp:166
GEdge::parFromPoint
virtual double parFromPoint(const SPoint3 &P) const
Definition: GEdge.cpp:595
ALGO_2D_QUAD_QUASI_STRUCT
#define ALGO_2D_QUAD_QUASI_STRUCT
Definition: GmshDefines.h:247
ALGO_2D_BAMG
#define ALGO_2D_BAMG
Definition: GmshDefines.h:243
deMeshGEdge::operator()
void operator()(GEdge *)
Definition: meshGEdge.cpp:426
GEdge::minimumMeshSegments
int minimumMeshSegments
Definition: GEdge.h:255
GModel::setCurrentMeshEntity
void setCurrentMeshEntity(GEntity *e)
Definition: GModel.cpp:2202
MeshExtrudedCurve
int MeshExtrudedCurve(GEdge *ge)
Definition: meshGEdgeExtruded.cpp:92
BoundaryLayerField::beta
double beta
Definition: Field.h:205
GEdge::method
char method
Definition: GEdge.h:250
BoundaryLayerField::isEdgeBL
bool isEdgeBL(int iE) const
Definition: Field.h:217
MVertex::x
double x() const
Definition: MVertex.h:60
SVector3::normalize
double normalize()
Definition: SVector3.h:38
faces
static int faces[4][3]
Definition: meshGRegionDelaunayInsertion.cpp:165