gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
BackgroundMeshTools.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 "BackgroundMeshTools.h"
7 #include "GFace.h"
8 #include "GVertex.h"
9 #include "GEdge.h"
10 #include "GEntity.h"
11 #include "Context.h"
12 #include "Field.h"
13 #include "GModel.h"
14 
15 static double max_surf_curvature(const GEdge *ge, double u)
16 {
17  double val = 0;
18  std::vector<GFace *> faces = ge->faces();
19  auto it = faces.begin();
20  while(it != faces.end()) {
21  SPoint2 par = ge->reparamOnFace((*it), u, 1);
22  double cc = (*it)->curvatureMax(par);
23  val = std::max(cc, val);
24  ++it;
25  }
26  return val;
27 }
28 
29 static double max_edge_curvature(const GVertex *gv)
30 {
31  double val = 0;
32  std::vector<GEdge *> const &l_edges = gv->edges();
33  for(auto ite = l_edges.begin(); ite != l_edges.end(); ++ite) {
34  GEdge *_myGEdge = *ite;
35  Range<double> range = _myGEdge->parBounds(0);
36  double t = (gv == _myGEdge->getBeginVertex()) ? range.low() : range.high();
37  double EC = _myGEdge->curvature(t);
38  double FC = max_surf_curvature(_myGEdge, t);
39  val = std::max(std::max(val, EC), FC);
40  }
41  return val;
42 }
43 
44 // the mesh vertex is classified on a model vertex. we compute the maximum of
45 // the curvature of model faces surrounding this point if it is classified on a
46 // model edge, we do the same for all model faces surrounding it if it is on a
47 // model face, we compute the curvature at this location
48 static double LC_MVertex_CURV(GEntity *ge, double U, double V)
49 {
50  double Crv = 0;
51  switch(ge->dim()) {
52  case 0:
53  Crv = max_edge_curvature((const GVertex *)ge);
54  // Crv = std::max(max_surf_curvature_vertex((const GVertex *)ge), Crv);
55  // Crv = max_surf_curvature((const GVertex *)ge);
56  break;
57  case 1: {
58  GEdge *ged = (GEdge *)ge;
59  Crv = ged->curvature(U);
60  Crv = std::max(Crv, max_surf_curvature(ged, U));
61  } break;
62  case 2: {
63  GFace *gf = (GFace *)ge;
64  Crv = gf->curvatureMax(SPoint2(U, V));
65  } break;
66  }
67  double ne = CTX::instance()->mesh.lcFromCurvature;
68  if(ne < 1) {
69  Msg::Warning("Invalid number of elements per 2*pi curvature %g", ne);
70  ne = 1;
71  }
72  double lc = Crv > 0 ? 2 * M_PI / Crv / ne : MAX_LC;
73  return lc;
74 }
75 
77 {
78  SVector3 t = ge->firstDer(u);
79  t.normalize();
80  double ne = CTX::instance()->mesh.lcFromCurvature;
81  if(ne < 1) {
82  Msg::Warning("Invalid number of elements per 2*pi curvature %g", ne);
83  ne = 1;
84  }
85  double l_t = (2 * M_PI) / (fabs(ge->curvature(u)) * ne);
86  double l_n = 1.e12;
87  return buildMetricTangentToCurve(t, l_t, l_n);
88 }
89 
91  bool iso_surf)
92 {
93  SMetric3 mesh_size(1.e-12);
94  std::vector<GFace *> faces = ge->faces();
95  auto it = faces.begin();
96  // we choose the metric eigenvectors to be the ones
97  // related to the edge ...
98  SMetric3 curvMetric = max_edge_curvature_metric(ge, u);
99  while(it != faces.end()) {
100  SPoint2 par = ge->reparamOnFace((*it), u, 1);
101  SMetric3 m =
102  metric_based_on_surface_curvature(*it, par.x(), par.y(), iso_surf);
103  curvMetric = intersection_conserveM1(curvMetric, m);
104  ++it;
105  }
106  return curvMetric;
107 }
108 
110  bool iso_surf)
111 {
112  SMetric3 mesh_size(1.e-15);
113  return mesh_size;
114 }
115 
116 SMetric3 LC_MVertex_CURV_ANISO(GEntity *ge, double U, double V)
117 {
118  bool iso_surf = CTX::instance()->mesh.lcFromCurvatureIso;
119 
120  switch(ge->dim()) {
121  case 0:
122  return metric_based_on_surface_curvature((const GVertex *)ge, iso_surf);
123  case 1:
124  return metric_based_on_surface_curvature((const GEdge *)ge, U, iso_surf);
125  case 2:
126  return metric_based_on_surface_curvature((const GFace *)ge, U, V, iso_surf);
127  }
128  Msg::Error("Curvature control impossible to compute for a volume");
129  return SMetric3();
130 }
131 
132 // compute the mesh size at a given vertex due to prescribed sizes at
133 // mesh vertices
134 static double LC_MVertex_PNTS(GEntity *ge, double U, double V)
135 {
136  switch(ge->dim()) {
137  case 0: {
138  GVertex *gv = (GVertex *)ge;
139  double lc = gv->prescribedMeshSizeAtVertex();
140  // FIXME we might want to remove this to make all lc treatment consistent
141  if(lc >= MAX_LC) return CTX::instance()->lc / 10.;
142  return lc;
143  }
144  case 1: {
145  GEdge *ged = (GEdge *)ge;
146  GVertex *v1 = ged->getBeginVertex();
147  GVertex *v2 = ged->getEndVertex();
148  if(v1 && v2) {
149  double lc1 = v1->prescribedMeshSizeAtVertex();
150  double lc2 = v2->prescribedMeshSizeAtVertex();
151  if(lc1 >= MAX_LC && lc2 >= MAX_LC) {
152  // FIXME we might want to remove this to make all lc treatment
153  // consistent
154  return CTX::instance()->lc / 10.;
155  }
156  else {
157  Range<double> range = ged->parBounds(0);
158  double a = (U - range.low()) / (range.high() - range.low());
159  return (1 - a) * lc1 + (a)*lc2;
160  }
161  }
162  else
163  return MAX_LC;
164  }
165  default: return MAX_LC;
166  }
167 }
168 
169 SMetric3 buildMetricTangentToCurve(SVector3 &t, double l_t, double l_n)
170 {
171  if(l_t == 0.0) return SMetric3(1.e-22);
172  SVector3 a;
173  if(fabs(t(0)) <= fabs(t(1)) && fabs(t(0)) <= fabs(t(2))) {
174  a = SVector3(1, 0, 0);
175  }
176  else if(fabs(t(1)) <= fabs(t(0)) && fabs(t(1)) <= fabs(t(2))) {
177  a = SVector3(0, 1, 0);
178  }
179  else {
180  a = SVector3(0, 0, 1);
181  }
182  SVector3 b = crossprod(t, a);
183  SVector3 c = crossprod(b, t);
184  b.normalize();
185  c.normalize();
186  t.normalize();
187  SMetric3 Metric(1. / (l_t * l_t), 1. / (l_n * l_n), 1. / (l_n * l_n), t, b,
188  c);
189  // printf("bmttc %g %g %g %g
190  // %g\n",l_t,l_n,Metric(0,0),Metric(0,1),Metric(1,1));
191  return Metric;
192 }
193 
195  double l_t2, double l_n)
196 {
197  t1.normalize();
198  t2.normalize();
199  SVector3 n = crossprod(t1, t2);
200  n.normalize();
201 
202  l_t1 = std::max(l_t1, CTX::instance()->mesh.lcMin);
203  l_t2 = std::max(l_t2, CTX::instance()->mesh.lcMin);
204  l_t1 = std::min(l_t1, CTX::instance()->mesh.lcMax);
205  l_t2 = std::min(l_t2, CTX::instance()->mesh.lcMax);
206  SMetric3 Metric(1. / (l_t1 * l_t1), 1. / (l_t2 * l_t2), 1. / (l_n * l_n), t1,
207  t2, n);
208  return Metric;
209 }
210 
211 double BGM_MeshSizeWithoutScaling(GEntity *ge, double U, double V, double X,
212  double Y, double Z)
213 {
214  // lc from points
215  double l1 = MAX_LC;
216  if(ge && CTX::instance()->mesh.lcFromPoints && ge->dim() < 2)
217  l1 = LC_MVertex_PNTS(ge, U, V);
218 
219  // lc from curvature
220  double l2 = MAX_LC;
221  if(ge && CTX::instance()->mesh.lcFromCurvature > 0 && ge->dim() < 3)
222  l2 = LC_MVertex_CURV(ge, U, V);
223 
224  // lc from fields
225  double l3 = MAX_LC;
226  if(ge) {
227  FieldManager *fields = ge->model()->getFields();
228  if(fields->getBackgroundField() > 0) {
229  Field *f = fields->get(fields->getBackgroundField());
230  if(f) l3 = (*f)(X, Y, Z, ge);
231  }
232  }
233 
234  // global lc from entity
235  double l4 = ge ? ge->getMeshSize() : MAX_LC;
236 
237  double l5 = (ge && ge->dim() == 1) ?
238  ((GEdge *)ge)->prescribedMeshSizeAtParam(U) :
239  MAX_LC;
240 
241  // take the minimum
242  double lc = std::min(std::min(std::min(std::min(l1, l2), l3), l4), l5);
243 
244  // lc from callback
245  if(GModel::current()->lcCallback) {
246  int dim = (ge ? ge->dim() : -1);
247  int tag = (ge ? ge->tag() : -1);
248  lc = GModel::current()->lcCallback(dim, tag, X, Y, Z, lc);
249  }
250 
251  return lc;
252 }
253 
254 // This is the only function that is used by the meshers
255 double BGM_MeshSize(GEntity *ge, double U, double V, double X, double Y,
256  double Z)
257 {
258  if(!ge) Msg::Warning("No entity in background mesh size evaluation");
259 
260  // default size to size of model
261  double lc = CTX::instance()->lc;
262 
263  // min of all sizes
264  lc = std::min(lc, BGM_MeshSizeWithoutScaling(ge, U, V, X, Y, Z));
265 
266  // constrain by lcMin and lcMax
267  lc = std::max(lc, CTX::instance()->mesh.lcMin);
268  lc = std::min(lc, CTX::instance()->mesh.lcMax);
269 
270  if(lc <= 0.) {
271  Msg::Error("Wrong mesh element size lc = %g (lcmin = %g, lcmax = %g)", lc,
272  CTX::instance()->mesh.lcMin, CTX::instance()->mesh.lcMax);
273  lc = CTX::instance()->lc;
274  }
275 
276  // size factor from entity
277  if(ge && ge->getMeshSizeFactor() != 1.0) lc *= ge->getMeshSizeFactor();
278 
279  // global size factor
280  return lc * CTX::instance()->mesh.lcFactor;
281 }
282 
283 // anisotropic version of the background field
284 SMetric3 BGM_MeshMetric(GEntity *ge, double U, double V, double X, double Y,
285  double Z)
286 {
287  // default size to size of model
288  double lc = CTX::instance()->lc;
289 
290  // lc from points
291  if(CTX::instance()->mesh.lcFromPoints && ge->dim() < 2)
292  lc = std::min(lc, LC_MVertex_PNTS(ge, U, V));
293 
294  // global lc from entity
295  lc = std::min(lc, ge->getMeshSize());
296 
297  // constrain by global min/max
298  lc = std::max(lc, CTX::instance()->mesh.lcMin);
299  lc = std::min(lc, CTX::instance()->mesh.lcMax);
300 
301  if(lc <= 0.) {
302  Msg::Error("Wrong mesh element size lc = %g (lcmin = %g, lcmax = %g)", lc,
303  CTX::instance()->mesh.lcMin, CTX::instance()->mesh.lcMax);
304  lc = CTX::instance()->lc;
305  }
306 
307  // isotropic base metric
308  SMetric3 m0(1. / (lc * lc));
309 
310  // intersect with metrics from fields if applicable
311  FieldManager *fields = ge->model()->getFields();
312  SMetric3 m1 = m0;
313  if(fields->getBackgroundField() > 0) {
314  Field *f = fields->get(fields->getBackgroundField());
315  if(f) {
316  SMetric3 l4;
317  if(!f->isotropic()) { (*f)(X, Y, Z, l4, ge); }
318  else {
319  const double L = (*f)(X, Y, Z, ge);
320  l4 = SMetric3(1 / (L * L));
321  }
322  m1 = intersection(l4, m0);
323  }
324  }
325 
326  // intersect with metrics from curvature if applicable
327  SMetric3 m = (CTX::instance()->mesh.lcFromCurvature > 0 && ge->dim() < 3) ?
328  intersection(m1, LC_MVertex_CURV_ANISO(ge, U, V)) :
329  m1;
330 
331  // apply global size factor
332  if(CTX::instance()->mesh.lcFactor != 0 &&
333  CTX::instance()->mesh.lcFactor != 1.)
335 
336  return m;
337 }
338 
340 {
341  int val = gf->getMeshSizeFromBoundary();
342  return (val > 0 || val == -2);
343 }
344 
346 {
348  return (val > 0 || val == -3);
349 }
350 
352 {
353  SMetric3 val(1.e-12);
354  std::vector<GEdge *> const &l_edges = gv->edges();
355  for(auto ite = l_edges.begin(); ite != l_edges.end(); ++ite) {
356  GEdge *_myGEdge = *ite;
357  Range<double> range = _myGEdge->parBounds(0);
358  SMetric3 cc;
359  double ne = CTX::instance()->mesh.lcFromCurvature;
360  if(ne < 1) {
361  Msg::Warning("Invalid number of elements per 2*pi curvature %g", ne);
362  ne = 1;
363  }
364  if(gv == _myGEdge->getBeginVertex()) {
365  SVector3 t = _myGEdge->firstDer(range.low());
366  t.normalize();
367  double l_t = 2 * M_PI / (fabs(_myGEdge->curvature(range.low())) * ne);
368  double l_n = 1.e12;
369  cc = buildMetricTangentToCurve(t, l_t, l_n);
370  }
371  else {
372  SVector3 t = _myGEdge->firstDer(range.high());
373  t.normalize();
374  double l_t = 2 * M_PI / (fabs(_myGEdge->curvature(range.high())) * ne);
375  double l_n = 1.e12;
376  cc = buildMetricTangentToCurve(t, l_t, l_n);
377  }
378  val = intersection(val, cc);
379  }
380  return val;
381 }
382 
383 SMetric3 metric_based_on_surface_curvature(const GFace *gf, double u, double v,
384  bool surface_isotropic,
385  double d_normal,
386  double d_tangent_max)
387 {
388  if(gf->geomType() == GEntity::Plane) return SMetric3(1.e-12);
389  double cmax, cmin;
390  SVector3 dirMax, dirMin;
391  cmax = gf->curvatures(SPoint2(u, v), dirMax, dirMin, cmax, cmin);
392  if(cmin == 0) cmin = 1.e-12;
393  if(cmax == 0) cmax = 1.e-12;
394  double ne = CTX::instance()->mesh.lcFromCurvature;
395  if(ne < 1) {
396  Msg::Warning("Invalid number of elements per 2*pi curvature %g", ne);
397  ne = 1;
398  }
399  double lambda1 = 2 * M_PI / (fabs(cmin) * ne);
400  double lambda2 = 2 * M_PI / (fabs(cmax) * ne);
401  SVector3 Z = crossprod(dirMax, dirMin);
402  if(surface_isotropic) lambda2 = lambda1 = std::min(lambda2, lambda1);
403  dirMin.normalize();
404  dirMax.normalize();
405  Z.normalize();
406  lambda1 = std::max(lambda1, CTX::instance()->mesh.lcMin);
407  lambda2 = std::max(lambda2, CTX::instance()->mesh.lcMin);
408  lambda1 = std::min(lambda1, CTX::instance()->mesh.lcMax);
409  lambda2 = std::min(lambda2, CTX::instance()->mesh.lcMax);
410  double lambda3 = std::min(d_normal, CTX::instance()->mesh.lcMax);
411  lambda3 = std::max(lambda3, CTX::instance()->mesh.lcMin);
412  lambda1 = std::min(lambda1, d_tangent_max);
413  lambda2 = std::min(lambda2, d_tangent_max);
414 
415  SMetric3 curvMetric(1. / (lambda1 * lambda1), 1. / (lambda2 * lambda2),
416  1. / (lambda3 * lambda3), dirMin, dirMax, Z);
417  return curvMetric;
418 }
crossprod
SVector3 crossprod(const SVector3 &a, const SVector3 &b)
Definition: SVector3.h:150
metric_based_on_surface_curvature
static SMetric3 metric_based_on_surface_curvature(const GEdge *ge, double u, bool iso_surf)
Definition: BackgroundMeshTools.cpp:90
GFace::getMeshSizeFromBoundary
int getMeshSizeFromBoundary() const
Definition: GFace.cpp:71
Field.h
GEdge::reparamOnFace
virtual SPoint2 reparamOnFace(const GFace *face, double epar, int dir) const
Definition: GEdge.cpp:482
contextMeshOptions::lcFromCurvatureIso
int lcFromCurvatureIso
Definition: Context.h:27
SMetric3
Definition: STensor3.h:17
contextMeshOptions::lcFromCurvature
int lcFromCurvature
Definition: Context.h:27
GFace.h
contextMeshOptions::lcExtendFromBoundary
int lcExtendFromBoundary
Definition: Context.h:28
GFace
Definition: GFace.h:33
GEntity::model
GModel * model() const
Definition: GEntity.h:277
GEntity::getMeshSize
virtual double getMeshSize() const
Definition: GEntity.h:341
SPoint2
Definition: SPoint2.h:12
GEntity.h
c
static double c(int i, int j, fullMatrix< double > &CA, const std::vector< SPoint3 > &P, const std::vector< SPoint3 > &Q)
Definition: discreteFrechetDistance.cpp:15
LC_MVertex_CURV
static double LC_MVertex_CURV(GEntity *ge, double U, double V)
Definition: BackgroundMeshTools.cpp:48
GModel::lcCallback
std::function< double(int, int, double, double, double, double)> lcCallback
Definition: GModel.h:713
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
LegendrePolynomials::f
void f(int n, double u, double *val)
Definition: orthogonalBasis.cpp:77
Range::high
T high() const
Definition: Range.h:20
SVector3
Definition: SVector3.h:16
intersection
SMetric3 intersection(const SMetric3 &m1, const SMetric3 &m2)
Definition: STensor3.cpp:119
GVertex::edges
virtual std::vector< GEdge * > const & edges() const
Definition: GVertex.h:54
max_edge_curvature
static double max_edge_curvature(const GVertex *gv)
Definition: BackgroundMeshTools.cpp:29
MAX_LC
#define MAX_LC
Definition: GEntity.h:19
GEntity
Definition: GEntity.h:31
BGM_MeshSizeWithoutScaling
double BGM_MeshSizeWithoutScaling(GEntity *ge, double U, double V, double X, double Y, double Z)
Definition: BackgroundMeshTools.cpp:211
Extend1dMeshIn2dSurfaces
bool Extend1dMeshIn2dSurfaces(GFace *gf)
Definition: BackgroundMeshTools.cpp:339
contextMeshOptions::lcMax
double lcMax
Definition: Context.h:25
GEntity::Plane
@ Plane
Definition: GEntity.h:105
CTX::instance
static CTX * instance()
Definition: Context.cpp:122
GEdge.h
GEdge::firstDer
virtual SVector3 firstDer(double par) const =0
Range
Definition: Range.h:10
GVertex
Definition: GVertex.h:23
GVertex::prescribedMeshSizeAtVertex
virtual double prescribedMeshSizeAtVertex() const
Definition: GVertex.h:75
CTX::lc
double lc
Definition: Context.h:234
FieldManager::get
Field * get(int id)
Definition: Field.cpp:74
BGM_MeshSize
double BGM_MeshSize(GEntity *ge, double U, double V, double X, double Y, double Z)
Definition: BackgroundMeshTools.cpp:255
Extend2dMeshIn3dVolumes
bool Extend2dMeshIn3dVolumes()
Definition: BackgroundMeshTools.cpp:345
max_edge_curvature_metric
SMetric3 max_edge_curvature_metric(const GEdge *ge, double u)
Definition: BackgroundMeshTools.cpp:76
GEdge::getBeginVertex
virtual GVertex * getBeginVertex() const
Definition: GEdge.h:63
FieldManager
Definition: Field.h:145
GEntity::geomType
virtual GeomType geomType() const
Definition: GEntity.h:238
CTX::mesh
contextMeshOptions mesh
Definition: Context.h:313
max_surf_curvature
static double max_surf_curvature(const GEdge *ge, double u)
Definition: BackgroundMeshTools.cpp:15
GModel::getFields
FieldManager * getFields()
Definition: GModel.h:325
GEntity::tag
int tag() const
Definition: GEntity.h:280
Field
Definition: Field.h:103
GEdge::faces
virtual std::vector< GFace * > faces() const
Definition: GEdge.h:113
GEdge::curvature
virtual double curvature(double par) const
Definition: GEdge.cpp:492
FieldManager::getBackgroundField
int getBackgroundField()
Definition: Field.h:178
SPoint2::x
double x(void) const
Definition: SPoint2.h:86
Context.h
GEdge::parBounds
virtual Range< double > parBounds(int i) const =0
GVertex.h
LC_MVertex_PNTS
static double LC_MVertex_PNTS(GEntity *ge, double U, double V)
Definition: BackgroundMeshTools.cpp:134
GFace::curvatureMax
virtual double curvatureMax(const SPoint2 &param) const
Definition: GFace.cpp:1020
contextMeshOptions::lcFactor
double lcFactor
Definition: Context.h:21
GEntity::getMeshSizeFactor
virtual double getMeshSizeFactor() const
Definition: GEntity.h:342
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
BackgroundMeshTools.h
GModel.h
GEdge::getEndVertex
virtual GVertex * getEndVertex() const
Definition: GEdge.h:64
intersection_conserveM1
SMetric3 intersection_conserveM1(const SMetric3 &m1, const SMetric3 &m2)
Definition: STensor3.cpp:164
Range::low
T low() const
Definition: Range.h:18
LC_MVertex_CURV_ANISO
SMetric3 LC_MVertex_CURV_ANISO(GEntity *ge, double U, double V)
Definition: BackgroundMeshTools.cpp:116
GEntity::dim
virtual int dim() const
Definition: GEntity.h:196
GFace::curvatures
virtual double curvatures(const SPoint2 &param, SVector3 &dirMax, SVector3 &dirMin, double &curvMax, double &curvMin) const
Definition: GFace.cpp:1031
GModel::current
static GModel * current(int index=-1)
Definition: GModel.cpp:136
buildMetricTangentToSurface
SMetric3 buildMetricTangentToSurface(SVector3 &t1, SVector3 &t2, double l_t1, double l_t2, double l_n)
Definition: BackgroundMeshTools.cpp:194
buildMetricTangentToCurve
SMetric3 buildMetricTangentToCurve(SVector3 &t, double l_t, double l_n)
Definition: BackgroundMeshTools.cpp:169
SVector3::normalize
double normalize()
Definition: SVector3.h:38
faces
static int faces[4][3]
Definition: meshGRegionDelaunayInsertion.cpp:165
SPoint2::y
double y(void) const
Definition: SPoint2.h:88