gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
boundaryLayersData.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 "boundaryLayersData.h"
7 #include "GmshConfig.h"
8 #include "GModel.h"
9 #include "MLine.h"
10 #include "MTriangle.h"
11 #include "MEdge.h"
12 #include "OS.h"
13 #include "Context.h"
14 
15 #if !defined(HAVE_MESH)
16 
18 
19 bool buildAdditionalPoints2D(GFace *gf) { return false; }
20 
21 bool buildAdditionalPoints3D(GRegion *gr) { return false; }
22 
24 {
26 }
27 
28 #else
29 
30 #include "Field.h"
31 
32 /*
33  ^ ni
34  |
35  |
36  +-----------------+
37  bi /
38  bj /
39  /\
40  / \ nj
41  / Z
42  +
43 */
44 
45 SVector3 interiorNormal(const SPoint2 &p1, const SPoint2 &p2, const SPoint2 &p3)
46 {
47  SVector3 ez(0, 0, 1);
48  SVector3 d(p1.x() - p2.x(), p1.y() - p2.y(), 0);
49  SVector3 h(p3.x() - 0.5 * (p2.x() + p1.x()), p3.y() - 0.5 * (p2.y() + p1.y()),
50  0);
51  SVector3 n = crossprod(d, ez);
52  n.normalize();
53  if(dot(n, h) > 0) return n;
54  return n * (-1.);
55 }
56 
58 {
59  MEdgeEqual aaa;
60  MEdge e(v1, v2);
61  auto it1 = _fans.find(v1);
62  auto it2 = _fans.find(v2);
63  int N1 = getNbColumns(v1);
64  int N2 = getNbColumns(v2);
65 
66  int nbSides = _normals.count(e);
67 
68  // if(nbSides != 1)printf("I'm here %d sides\n",nbSides);
69  // Standard case, only two extruded columns from the two vertices
70  if(N1 == 1 && N2 == 1) return edgeColumn(getColumn(v1, 0), getColumn(v2, 0));
71  // one fan on
72  if(nbSides == 1) {
73  if(it1 != _fans.end() && it2 == _fans.end()) {
74  if(aaa(it1->second._e1, e))
75  return edgeColumn(getColumn(v1, 0), getColumn(v2, 0));
76  else
77  return edgeColumn(getColumn(v1, N1 - 1), getColumn(v2, 0));
78  }
79  if(it2 != _fans.end() && it1 == _fans.end()) {
80  if(aaa(it2->second._e1, e))
81  return edgeColumn(getColumn(v1, 0), getColumn(v2, 0));
82  else
83  return edgeColumn(getColumn(v1, 0), getColumn(v2, N2 - 1));
84  }
85  if(it2 != _fans.end() && it1 != _fans.end()) {
86  int c1, c2;
87  if(aaa(it1->second._e1, e))
88  c1 = 0;
89  else
90  c1 = N1 - 1;
91  if(aaa(it2->second._e1, e))
92  c2 = 0;
93  else
94  c2 = N2 - 1;
95  return edgeColumn(getColumn(v1, c1), getColumn(v2, c2));
96  }
97  // fan on the right
98  if(N1 == 1 || N2 == 2) {
99  const BoundaryLayerData &c10 = getColumn(v1, 0);
100  const BoundaryLayerData &c20 = getColumn(v2, 0);
101  const BoundaryLayerData &c21 = getColumn(v2, 1);
102  if(dot(c10._n, c20._n) > dot(c10._n, c21._n))
103  return edgeColumn(c10, c20);
104  else
105  return edgeColumn(c10, c21);
106  }
107  // fan on the left
108  if(N1 == 2 || N2 == 1) {
109  const BoundaryLayerData &c10 = getColumn(v1, 0);
110  const BoundaryLayerData &c11 = getColumn(v1, 1);
111  const BoundaryLayerData &c20 = getColumn(v2, 0);
112  if(dot(c10._n, c20._n) > dot(c11._n, c20._n))
113  return edgeColumn(c10, c20);
114  else
115  return edgeColumn(c11, c20);
116  }
117 
118  // Msg::Error("Impossible Boundary Layer Configuration : "
119  // "one side and no fans %d %d", N1, N2);
120  // FIXME WRONG
121  return N1 ? edgeColumn(getColumn(v1, 0), getColumn(v1, 0)) :
122  edgeColumn(getColumn(v2, 0), getColumn(v2, 0));
123  }
124  else if(nbSides == 2) {
125  int i1 = 0, i2 = 1, j1 = 0, j2 = 1;
126  if(it1 != _fans.end()) {
127  i1 = aaa(it1->second._e1, e) ? 0 : N1 - 1;
128  i2 = !aaa(it1->second._e1, e) ? 0 : N1 - 1;
129  }
130  if(it2 != _fans.end()) {
131  j1 = aaa(it2->second._e1, e) ? 0 : N2 - 1;
132  j2 = !aaa(it2->second._e1, e) ? 0 : N2 - 1;
133  }
134  const BoundaryLayerData &c10 = getColumn(v1, i1);
135  const BoundaryLayerData &c11 = getColumn(v1, i2);
136  const BoundaryLayerData &c20 = getColumn(v2, j1);
137  const BoundaryLayerData &c21 = getColumn(v2, j2);
138 
139  if(side == 0) {
140  if(dot(c10._n, c20._n) > dot(c10._n, c21._n))
141  return edgeColumn(c10, c20);
142  else
143  return edgeColumn(c10, c21);
144  }
145  if(side == 1) {
146  if(dot(c11._n, c20._n) > dot(c11._n, c21._n))
147  return edgeColumn(c11, c20);
148  else
149  return edgeColumn(c11, c21);
150  }
151  }
152 
153  Msg::Error("Not yet Done in BoundaryLayerData nbSides = %d, ", nbSides);
154  static BoundaryLayerData error;
155  static edgeColumn error2(error, error);
156  return error2;
157 }
158 
159 static void treat2Connections(GFace *gf, MVertex *_myVert, MEdge &e1, MEdge &e2,
160  BoundaryLayerColumns *_columns,
161  std::vector<SVector3> &_dirs, bool fan,
162  int fanSize)
163 {
164  std::vector<SVector3> N1, N2;
165  for(auto itm = _columns->_normals.lower_bound(e1);
166  itm != _columns->_normals.upper_bound(e1); ++itm)
167  N1.push_back(itm->second);
168  for(auto itm = _columns->_normals.lower_bound(e2);
169  itm != _columns->_normals.upper_bound(e2); ++itm)
170  N2.push_back(itm->second);
171  if(N1.size() == N2.size()) {
172  for(std::size_t SIDE = 0; SIDE < N1.size(); SIDE++) {
173  if(!fan) {
174  SVector3 x = N1[SIDE] * 1.01 + N2[SIDE];
175  x.normalize();
176  // fix for #1054: the size should be divided by cos(theta/2) where
177  // cos(theta) is dot(N1[SIDE], N2[SIDE])
178  double d = fabs(dot(N1[SIDE], N2[SIDE]));
179  if(d > 1.) d = 1.; // fix for #1450
180  double ct2 = cos(acos(d) / 2);
181  if(ct2) { // fix for #1450
182  double fact = 1. / ct2;
183  x *= fabs(fact);
184  }
185  _dirs.push_back(x);
186  }
187  else if(fan) {
188  // if the angle is greater than PI, than reverse the sense
189  double alpha1 = atan2(N1[SIDE].y(), N1[SIDE].x());
190  double alpha2 = atan2(N2[SIDE].y(), N2[SIDE].x());
191  double AMAX = std::max(alpha1, alpha2);
192  double AMIN = std::min(alpha1, alpha2);
193  MEdge ee[2];
194  if(alpha1 > alpha2) {
195  ee[0] = e2;
196  ee[1] = e1;
197  }
198  else {
199  ee[0] = e1;
200  ee[1] = e2;
201  }
202  if(AMAX - AMIN >= M_PI) {
203  double temp = AMAX;
204  AMAX = AMIN + 2 * M_PI;
205  AMIN = temp;
206  MEdge eee0 = ee[0];
207  ee[0] = ee[1];
208  ee[1] = eee0;
209  }
210  double frac = fabs(AMAX - AMIN) / M_PI;
211  int n =
212  (int)(frac * fanSize /*CTX::instance()->mesh.boundaryLayerFanPoints*/
213  + 0.5);
214  int fanSize = fan ? n : 0;
215  _columns->addFan(_myVert, ee[0], ee[1], true);
216  for(int i = -1; i <= fanSize; i++) {
217  double t = (double)(i + 1) / (fanSize + 1);
218  double alpha = t * AMAX + (1. - t) * AMIN;
219  SVector3 x(cos(alpha), sin(alpha), 0);
220  x.normalize();
221  _dirs.push_back(x);
222  }
223  }
224  /*
225  else {
226  _dirs.push_back(N1[SIDE]);
227  _dirs.push_back(N2[SIDE]);
228  }
229  */
230  }
231  }
232 }
233 
234 static void treat3Connections(GFace *gf, MVertex *_myVert, MEdge &e1, MEdge &e2,
235  MEdge &e3, BoundaryLayerColumns *_columns,
236  std::vector<SVector3> &_dirs)
237 {
238  std::vector<SVector3> N1, N2, N3;
239  for(auto itm = _columns->_normals.lower_bound(e1);
240  itm != _columns->_normals.upper_bound(e1); ++itm)
241  N1.push_back(itm->second);
242  for(auto itm = _columns->_normals.lower_bound(e2);
243  itm != _columns->_normals.upper_bound(e2); ++itm)
244  N2.push_back(itm->second);
245  for(auto itm = _columns->_normals.lower_bound(e3);
246  itm != _columns->_normals.upper_bound(e3); ++itm)
247  N3.push_back(itm->second);
248 
249  SVector3 x1, x2;
250  if(N1.size() == 2) {}
251  else if(N2.size() == 2) {
252  std::vector<SVector3> temp = N1;
253  N1.clear();
254  N1 = N2;
255  N2.clear();
256  N2 = temp;
257  }
258  else if(N3.size() == 2) {
259  std::vector<SVector3> temp = N1;
260  N1.clear();
261  N1 = N3;
262  N3.clear();
263  N3 = temp;
264  }
265  else {
266  Msg::Error("Impossible boundary layer configuration");
267  }
268  if(dot(N1[0], N2[0]) > dot(N1[0], N3[0])) {
269  x1 = N1[0] * 1.01 + N2[0];
270  x2 = N1[1] * 1.01 + N3[0];
271  }
272  else {
273  x1 = N1[1] * 1.01 + N2[0];
274  x2 = N1[0] * 1.01 + N3[0];
275  }
276  x1.normalize();
277  _dirs.push_back(x1);
278  x2.normalize();
279  _dirs.push_back(x2);
280 }
281 
282 static bool isEdgeOfFaceBL(GFace *gf, GEdge *ge, BoundaryLayerField *blf)
283 {
284  if(blf->isEdgeBL(ge->tag())) return true;
285  /*
286  std::list<GFace*> faces = ge->faces();
287  for(auto it = faces.begin(); it != faces.end() ; ++it){
288  if((*it) == gf)return false;
289  }
290  for(auto it = faces.begin(); it != faces.end() ; ++it){
291  if(blf->isFaceBL((*it)->tag()))return true;
292  }
293  */
294  return false;
295 }
296 
297 static void getEdgesData(GFace *gf, BoundaryLayerField *blf,
298  BoundaryLayerColumns *_columns,
299  std::set<MVertex *> &_vertices,
300  std::set<MEdge, MEdgeLessThan> &allEdges,
301  std::multimap<MVertex *, MVertex *> &tangents)
302 {
303  // get all model edges
304  std::vector<GEdge *> edges = gf->edges();
305  std::vector<GEdge *> const &embedded_edges = gf->embeddedEdges();
306  edges.insert(edges.begin(), embedded_edges.begin(), embedded_edges.end());
307 
308  // iterate on model edges
309  auto ite = edges.begin();
310  while(ite != edges.end()) {
311  // check if this edge generates a boundary layer
312  if(isEdgeOfFaceBL(gf, *ite, blf)) {
313  for(std::size_t i = 0; i < (*ite)->lines.size(); i++) {
314  MVertex *v1 = (*ite)->lines[i]->getVertex(0);
315  MVertex *v2 = (*ite)->lines[i]->getVertex(1);
316  allEdges.insert(MEdge(v1, v2));
317  _columns->_non_manifold_edges.insert(std::make_pair(v1, v2));
318  _columns->_non_manifold_edges.insert(std::make_pair(v2, v1));
319  _vertices.insert(v1);
320  _vertices.insert(v2);
321  }
322  }
323  else {
324  MVertex *v1 = (*ite)->lines[0]->getVertex(0);
325  MVertex *v2 = (*ite)->lines[0]->getVertex(1);
326  MVertex *v3 = (*ite)->lines[(*ite)->lines.size() - 1]->getVertex(1);
327  MVertex *v4 = (*ite)->lines[(*ite)->lines.size() - 1]->getVertex(0);
328  tangents.insert(std::make_pair(v1, v2));
329  tangents.insert(std::make_pair(v3, v4));
330  }
331  ++ite;
332  }
333 }
334 
335 static void getNormals(GFace *gf, BoundaryLayerField *blf,
336  BoundaryLayerColumns *_columns,
337  std::set<MEdge, MEdgeLessThan> &allEdges)
338 {
339  // assume that the initial mesh has been created i.e. that there exist
340  // triangles inside the domain. Triangles are used to define exterior normals
341  for(std::size_t i = 0; i < gf->triangles.size(); i++) {
342  SPoint2 p0, p1, p2;
343  MVertex *v0 = gf->triangles[i]->getVertex(0);
344  MVertex *v1 = gf->triangles[i]->getVertex(1);
345  MVertex *v2 = gf->triangles[i]->getVertex(2);
346  reparamMeshEdgeOnFace(v0, v1, gf, p0, p1);
347  reparamMeshEdgeOnFace(v0, v2, gf, p0, p2);
348 
349  MEdge me01(v0, v1);
350  if(allEdges.find(me01) != allEdges.end()) {
351  SVector3 v01 = interiorNormal(p0, p1, p2);
352  _columns->_normals.insert(std::make_pair(me01, v01));
353  }
354 
355  MEdge me02(v0, v2);
356  if(allEdges.find(me02) != allEdges.end()) {
357  SVector3 v02 = interiorNormal(p0, p2, p1);
358  _columns->_normals.insert(std::make_pair(me02, v02));
359  }
360 
361  MEdge me21(v2, v1);
362  if(allEdges.find(me21) != allEdges.end()) {
363  SVector3 v21 = interiorNormal(p2, p1, p0);
364  _columns->_normals.insert(std::make_pair(me21, v21));
365  }
366  }
367 }
368 
369 static void addColumnAtTheEndOfTheBL(GEdge *ge, GVertex *gv,
370  BoundaryLayerColumns *_columns,
371  BoundaryLayerField *blf)
372 {
373  if(!blf->isEdgeBL(ge->tag())) {
374  std::vector<MVertex *> invert;
375  for(std::size_t i = 0; i < ge->mesh_vertices.size(); i++)
376  invert.push_back(ge->mesh_vertices[ge->mesh_vertices.size() - i - 1]);
377  GVertex *g0 = ge->getBeginVertex();
378  GVertex *g1 = ge->getEndVertex();
379  if(g0 && g1) {
380  MVertex *v0 = g0->mesh_vertices[0];
381  MVertex *v1 = g1->mesh_vertices[0];
382  SVector3 t(v1->x() - v0->x(), v1->y() - v0->y(), v1->z() - v0->z());
383  t.normalize();
384  if(g0 == gv)
385  _columns->addColumn(t, v0, ge->mesh_vertices);
386  else if(g1 == gv)
387  _columns->addColumn(t * -1.0, v1, invert);
388  }
389  }
390 }
391 
392 void getLocalInfoAtNode(MVertex *v, BoundaryLayerField *blf, double &hWall)
393 {
394  hWall = blf->hWallN;
395  if(v->onWhat()->dim() == 0) { hWall = blf->hWall(v->onWhat()->tag()); }
396  else if(v->onWhat()->dim() == 1) {
397  GEdge *ge = (GEdge *)v->onWhat();
398  Range<double> bounds = ge->parBounds(0);
399  double t_begin = bounds.low();
400  double t_end = bounds.high();
401  double t;
402  v->getParameter(0, t);
403  if(ge->getBeginVertex() && ge->getEndVertex()) {
404  double hWall_beg = blf->hWall(ge->getBeginVertex()->tag());
405  double hWall_end = blf->hWall(ge->getEndVertex()->tag());
406  double x = (t - t_begin) / (t_end - t_begin);
407  double hWallLin = hWall_beg + x * (hWall_end - hWall_beg);
408  double hWall_mid = std::min(hWall_beg, hWall_end);
409  double hWallQuad = hWall_beg * (1 - x) * (1 - x) +
410  hWall_mid * 2 * x * (1 - x) + hWall_end * x * x;
411  // we prefer a quadratic growing:
412  hWall = 0 * hWallLin + 1 * hWallQuad;
413  }
414  }
415 }
416 
418 {
419  BoundaryLayerColumns *_columns = gf->getColumns();
420  _columns->clearData();
421 
422  FieldManager *fields = gf->model()->getFields();
423  int nBL = fields->getNumBoundaryLayerFields();
424  if(nBL == 0) return false;
425 
426  // Note: boundary layers must be separate (must not touch each other)
427  bool addedAdditionalPoints = false;
428  for(int i = 0; i < nBL; ++i) {
429  // GET THE FIELD THAT DEFINES THE DISTANCE FUNCTION
430  Field *bl_field = fields->get(fields->getBoundaryLayerField(i));
431  if(bl_field == nullptr) continue;
432  BoundaryLayerField *blf = dynamic_cast<BoundaryLayerField *>(bl_field);
433 
434  if(!blf->setupFor2d(gf->tag())) continue;
435 
436  std::set<MVertex *> _vertices;
437  std::set<MEdge, MEdgeLessThan> allEdges;
438  std::multimap<MVertex *, MVertex *> tangents;
439 
440  getEdgesData(gf, blf, _columns, _vertices, allEdges, tangents);
441 
442  if(!_vertices.size()) continue;
443 
444  getNormals(gf, blf, _columns, allEdges);
445 
446  // for all boundry points
447  for(auto it = _vertices.begin(); it != _vertices.end(); ++it) {
448  bool endOfTheBL = false;
449  SVector3 dirEndOfBL;
450  std::vector<MVertex *> columnEndOfBL;
451 
452  std::vector<MVertex *> _connections;
453  std::vector<SVector3> _dirs;
454  // get all vertices that are connected to that
455  // vertex among all boundary layer vertices !
456 
457  bool fan =
458  (*it)->onWhat()->dim() == 0 && blf->isFanNode((*it)->onWhat()->tag());
459  int fanSize = fan ? blf->fanSize((*it)->onWhat()->tag()) : 0;
460 
461  for(auto itm = _columns->_non_manifold_edges.lower_bound(*it);
462  itm != _columns->_non_manifold_edges.upper_bound(*it); ++itm)
463  _connections.push_back(itm->second);
464 
465  // A trailing edge topology : 3 edges incident to a vertex
466  if(_connections.size() == 3) {
467  MEdge e1(*it, _connections[0]);
468  MEdge e2(*it, _connections[1]);
469  MEdge e3(*it, _connections[2]);
470  treat3Connections(gf, *it, e1, e2, e3, _columns, _dirs);
471  }
472  // STANDARD CASE, one vertex connected to two neighboring vertices
473  else if(_connections.size() == 2) {
474  MEdge e1(*it, _connections[0]);
475  MEdge e2(*it, _connections[1]);
476  treat2Connections(gf, *it, e1, e2, _columns, _dirs, fan, fanSize);
477  }
478  else if(_connections.size() == 1) {
479  MEdge e1(*it, _connections[0]);
480  std::vector<SVector3> N1;
481  for(auto itm = _columns->_normals.lower_bound(e1);
482  itm != _columns->_normals.upper_bound(e1); ++itm)
483  N1.push_back(itm->second);
484  // one point has only one side and one normal : it has to be at the end
485  // of the BL then, we have the tangent to the connecting edge
486 
487  // *it _connections[0]
488  // --------- + -----------
489  // NO BL BL
490 
491  if(N1.size() == 1) {
492  std::vector<MVertex *> Ts;
493  for(auto itm = tangents.lower_bound(*it);
494  itm != tangents.upper_bound(*it); ++itm)
495  Ts.push_back(itm->second);
496  // end of the BL --> let's add a column that correspond to the
497  // model edge that lies after the end of teh BL
498  if(Ts.size() == 1) {
499  // printf("HERE WE ARE IN FACE %d %d\n",gf->tag(),Ts.size());
500  // printf("Classif dim %d
501  // %d\n",(*it)->onWhat()->dim(),Ts[0]->onWhat()->dim());
502  GEdge *ge = dynamic_cast<GEdge *>(Ts[0]->onWhat());
503  GVertex *gv = dynamic_cast<GVertex *>((*it)->onWhat());
504  if(ge && gv) { addColumnAtTheEndOfTheBL(ge, gv, _columns, blf); }
505  }
506  else {
507  Msg::Error(
508  "Impossible BL Configuration -- One Edge -- Tscp.size() = %d",
509  Ts.size());
510  }
511  }
512  else if(N1.size() == 2) {
513  SPoint2 p0, p1;
514  reparamMeshEdgeOnFace(_connections[0], *it, gf, p0, p1);
515  double alpha1 = atan2(N1[0].y(), N1[0].x());
516  double alpha2 = atan2(N1[1].y(), N1[1].x());
517  double alpha3 = atan2(p1.y() - p0.y(), p1.x() - p0.x());
518  double AMAX = std::max(alpha1, alpha2);
519  double AMIN = std::min(alpha1, alpha2);
520  if(alpha3 > AMAX) {
521  double temp = AMAX;
522  AMAX = AMIN + 2 * M_PI;
523  AMIN = temp;
524  }
525  if(alpha3 < AMIN) {
526  double temp = AMIN;
527  AMIN = AMAX - 2 * M_PI;
528  AMAX = temp;
529  }
530  double frac = fabs(AMAX - AMIN) / M_PI;
531  int n = (int)(frac * fanSize + 0.5);
532  int fanSize2 = fan ? n : 0;
533  if(fan) _columns->addFan(*it, e1, e1, true);
534  for(int i = -1; i <= fanSize2; i++) {
535  double t = (double)(i + 1) / (fanSize2 + 1);
536  double alpha = t * AMAX + (1. - t) * AMIN;
537  SVector3 x(cos(alpha), sin(alpha), 0);
538  x.normalize();
539  _dirs.push_back(x);
540  }
541  }
542  }
543 
544  // if(_dirs.size() > 1)printf("%d directions\n",_dirs.size());
545 
546  // now create the BL points
547  for(std::size_t DIR = 0; DIR < _dirs.size(); DIR++) {
548  SVector3 n = _dirs[DIR];
549 
550  // < ------------------------------- > //
551  // N = X(p0+ e n) - X(p0) //
552  // = e * (dX/du n_u + dX/dv n_v) //
553  // < ------------------------------- > //
554 
555  /* if (endOfTheBL){
556  printf("%g %g %d %d %g\n", (*it)->x(), (*it)->y(), DIR,
557  (int)_dirs.size(), dot(n, dirEndOfBL));
558  }
559  */
560  if(endOfTheBL && dot(n, dirEndOfBL) > .99) {
561  // printf( "coucou c'est moi\n");
562  }
563  // ADD BETA LAW HERE !!!
564  else if(blf->betaLaw) {
565  MVertex *first = *it;
566  double hWall;
567  getLocalInfoAtNode(first, blf, hWall);
568  std::vector<MVertex *> _column;
569  SPoint2 par =
570  gf->parFromPoint(SPoint3(first->x(), first->y(), first->z()));
571  std::vector<double> t(blf->nb_divisions);
572 
573  double zlog = log((1 + blf->beta) / (blf->beta - 1));
574  printf("T = ");
575  for(int i = 0; i < blf->nb_divisions; i++) {
576  const double eta = (double)(i + 1) / blf->nb_divisions;
577  const double power = exp(zlog * (1. - eta));
578  const double ratio = (1. - power) / (1. + power);
579  t[i] = 1.0 + blf->beta * ratio;
580  printf("%12.5E ", t[i]);
581  }
582  printf("\n");
583  for(int i = 0; i < blf->nb_divisions; i++) {
584  double L = hWall * t[i] / t[0];
585  SPoint2 pnew(par.x() + L * n.x(), par.y() + L * n.y());
586  GPoint pp = gf->point(pnew);
587  MFaceVertex *_current =
588  new MFaceVertex(pp.x(), pp.y(), pp.z(), gf, pnew.x(), pnew.y());
589  _current->bl_data = new MVertexBoundaryLayerData;
590  _column.push_back(_current);
591  }
592  _columns->addColumn(n, *it, _column /*,_metrics*/);
593  }
594  else {
595  MVertex *first = *it;
596  double hWall;
597  getLocalInfoAtNode(first, blf, hWall);
598  std::vector<MVertex *> _column;
599  SPoint2 par =
600  gf->parFromPoint(SPoint3(first->x(), first->y(), first->z()));
601  double L = hWall;
602  while(1) {
603  // printf("L = %g\n",L);
604  if(L > blf->thickness) break;
605  SPoint2 pnew(par.x() + L * n.x(), par.y() + L * n.y());
606  GPoint pp = gf->point(pnew);
607  MFaceVertex *_current =
608  new MFaceVertex(pp.x(), pp.y(), pp.z(), gf, pnew.x(), pnew.y());
609  _current->bl_data = new MVertexBoundaryLayerData;
610  _column.push_back(_current);
611  int ith = _column.size();
612  // ADD BETA LAW HERE !!!
613  L += hWall * pow(blf->ratio, ith);
614  }
615  _columns->addColumn(n, *it, _column /*,_metrics*/);
616  }
617  }
618  }
619  addedAdditionalPoints = true;
620  }
621 
622 #if 0 // DEBUG STUFF
623  char name[256];
624  sprintf(name, "points_face_%d.pos", gf->tag());
625  FILE *f = Fopen(name,"w");
626  if(f){
627  fprintf(f,"View \"\" {\n");
628  for(auto it = _vertices.begin(); it != _vertices.end() ; ++it){
629  MVertex *v = *it;
630  for(int i = 0; i < _columns->getNbColumns(v); i++){
631  const BoundaryLayerData &data = _columns->getColumn(v, i);
632  for(std::size_t j = 0; j < data._column.size(); j++){
633  MVertex *blv = data._column[j];
634  fprintf(f, "SP(%g,%g,%g){%d};\n", blv->x(), blv->y(), blv->z(),
635  v->getNum());
636  }
637  }
638  }
639  fprintf(f, "};\n");
640  fclose(f);
641  }
642 #endif
643 
644  return addedAdditionalPoints;
645 }
646 
647 #endif
crossprod
SVector3 crossprod(const SVector3 &a, const SVector3 &b)
Definition: SVector3.h:150
edgeColumn
Definition: boundaryLayersData.h:43
MTriangle.h
BoundaryLayerColumns::getColumns
edgeColumn getColumns(MVertex *v1, MVertex *v2, int side)
Definition: boundaryLayersData.cpp:23
BoundaryLayerColumns::getColumn
const BoundaryLayerData & getColumn(MVertex *v, MEdge e) const
Definition: boundaryLayersData.h:101
GFace::edges
virtual std::vector< GEdge * > const & edges() const
Definition: GFace.h:121
Field.h
MEdge
Definition: MEdge.h:14
dot
double dot(const SVector3 &a, const SMetric3 &m, const SVector3 &b)
Definition: STensor3.h:71
GPoint::y
double y() const
Definition: GPoint.h:22
GFace
Definition: GFace.h:33
GFace::triangles
std::vector< MTriangle * > triangles
Definition: GFace.h:428
GEntity::model
GModel * model() const
Definition: GEntity.h:277
SPoint2
Definition: SPoint2.h:12
OS.h
MVertex
Definition: MVertex.h:24
buildAdditionalPoints2D
bool buildAdditionalPoints2D(GFace *gf)
Definition: boundaryLayersData.cpp:19
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
MVertex::z
double z() const
Definition: MVertex.h:62
SPoint3
Definition: SPoint3.h:14
LegendrePolynomials::f
void f(int n, double u, double *val)
Definition: orthogonalBasis.cpp:77
MVertex::getNum
std::size_t getNum() const
Definition: MVertex.h:86
Range::high
T high() const
Definition: Range.h:20
GFace::point
virtual GPoint point(double par1, double par2) const =0
SVector3
Definition: SVector3.h:16
MVertex::onWhat
GEntity * onWhat() const
Definition: MVertex.h:82
BoundaryLayerColumns
Definition: boundaryLayersData.h:51
MLine.h
edges
static int edges[6][2]
Definition: meshGRegionLocalMeshMod.cpp:23
GPoint
Definition: GPoint.h:13
Fopen
FILE * Fopen(const char *f, const char *mode)
Definition: OS.cpp:273
BoundaryLayerColumns::addFan
void addFan(MVertex *v, MEdge e1, MEdge e2, bool s)
Definition: boundaryLayersData.h:91
BoundaryLayerColumns::_fans
std::map< MVertex *, BoundaryLayerFan > _fans
Definition: boundaryLayersData.h:52
GPoint::z
double z() const
Definition: GPoint.h:23
BoundaryLayerField::fanSize
int fanSize(int iV)
Definition: Field.h:232
Range
Definition: Range.h:10
GEntity::mesh_vertices
std::vector< MVertex * > mesh_vertices
Definition: GEntity.h:56
boundaryLayersData.h
GVertex
Definition: GVertex.h:23
BoundaryLayerData
Definition: boundaryLayersData.h:24
BoundaryLayerColumns::_normals
std::multimap< MEdge, SVector3, MEdgeLessThan > _normals
Definition: boundaryLayersData.h:64
BoundaryLayerField::setupFor2d
bool setupFor2d(int iF)
Definition: Field.cpp:2893
BoundaryLayerData::_n
SVector3 _n
Definition: boundaryLayersData.h:25
FieldManager::get
Field * get(int id)
Definition: Field.cpp:74
BoundaryLayerField::nb_divisions
int nb_divisions
Definition: Field.h:206
GModel
Definition: GModel.h:44
BoundaryLayerField::thickness
double thickness
Definition: Field.h:204
reparamMeshEdgeOnFace
bool reparamMeshEdgeOnFace(MVertex *v1, MVertex *v2, GFace *gf, SPoint2 &param1, SPoint2 &param2)
Definition: MVertex.cpp:474
GEdge::getBeginVertex
virtual GVertex * getBeginVertex() const
Definition: GEdge.h:63
GFace::parFromPoint
virtual SPoint2 parFromPoint(const SPoint3 &, bool onSurface=true, bool convTestXYZ=false) const
Definition: GFace.cpp:1254
FieldManager
Definition: Field.h:145
GModel::getFields
FieldManager * getFields()
Definition: GModel.h:325
GEntity::tag
int tag() const
Definition: GEntity.h:280
MFaceVertex
Definition: MVertex.h:168
BoundaryLayerField
Definition: Field.h:191
Field
Definition: Field.h:103
BoundaryLayerData::_column
std::vector< MVertex * > _column
Definition: boundaryLayersData.h:26
SVector3::x
double x(void) const
Definition: SVector3.h:30
GRegion
Definition: GRegion.h:28
BoundaryLayerColumns::getNbColumns
int getNbColumns(MVertex *v) const
Definition: boundaryLayersData.h:118
GFace::getColumns
BoundaryLayerColumns * getColumns()
Definition: GFace.h:453
BoundaryLayerField::betaLaw
int betaLaw
Definition: Field.h:206
MVertex::getParameter
virtual bool getParameter(int i, double &par) const
Definition: MVertex.h:97
MEdge.h
BoundaryLayerColumns::_non_manifold_edges
std::multimap< MVertex *, MVertex * > _non_manifold_edges
Definition: boundaryLayersData.h:63
SPoint2::x
double x(void) const
Definition: SPoint2.h:86
BoundaryLayerColumns::addColumn
void addColumn(const SVector3 &dir, MVertex *v, const std::vector< MVertex * > &_column)
Definition: boundaryLayersData.h:86
FieldManager::getBoundaryLayerField
int getBoundaryLayerField(int i)
Definition: Field.h:183
Context.h
getBLField
BoundaryLayerField * getBLField(GModel *gm)
Definition: boundaryLayersData.cpp:17
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
GFace::embeddedEdges
std::vector< GEdge * > & embeddedEdges()
Definition: GFace.h:156
BoundaryLayerField::isFanNode
bool isFanNode(int iV) const
Definition: Field.h:227
GEdge
Definition: GEdge.h:26
MVertexBoundaryLayerData
Definition: MVertexBoundaryLayerData.h:18
MFaceVertex::bl_data
MVertexBoundaryLayerData * bl_data
Definition: MVertex.h:173
FieldManager::getNumBoundaryLayerFields
int getNumBoundaryLayerFields()
Definition: Field.h:179
MEdgeEqual
Definition: MEdge.h:118
GModel.h
MVertex::y
double y() const
Definition: MVertex.h:61
GEdge::getEndVertex
virtual GVertex * getEndVertex() const
Definition: GEdge.h:64
Range::low
T low() const
Definition: Range.h:18
buildAdditionalPoints3D
bool buildAdditionalPoints3D(GRegion *gr)
Definition: boundaryLayersData.cpp:21
BoundaryLayerColumns::clearData
void clearData()
Definition: boundaryLayersData.h:65
GEntity::dim
virtual int dim() const
Definition: GEntity.h:196
BoundaryLayerField::ratio
double ratio
Definition: Field.h:204
GPoint::x
double x() const
Definition: GPoint.h:21
c1
const double c1
Definition: GaussQuadratureHex.cpp:16
BoundaryLayerField::hWallN
double hWallN
Definition: Field.h:204
BoundaryLayerField::beta
double beta
Definition: Field.h:205
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
SPoint2::y
double y(void) const
Definition: SPoint2.h:88