gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
Field.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 // Contributor(s):
7 // Jonathan Lambrechts
8 //
9 
10 #include <cstdlib>
11 #include <limits>
12 #include <list>
13 #include <cmath>
14 #include <fstream>
15 #include <string>
16 #include <string.h>
17 #include <sstream>
18 #include <algorithm>
19 #include "GmshConfig.h"
20 #include "Context.h"
21 #include "Field.h"
22 #include "GModel.h"
23 #include "GModelIO_GEO.h"
24 #include "GmshMessage.h"
25 #include "Numeric.h"
26 #include "mathEvaluator.h"
27 #include "BackgroundMeshTools.h"
28 #include "STensor3.h"
29 #include "ExtrudeParams.h"
30 #include "automaticMeshSizeField.h"
31 #include "fullMatrix.h"
32 #include "SPoint3KDTree.h"
33 #include "MVertex.h"
34 
35 #if defined(HAVE_POST)
36 #include "PView.h"
37 #include "PViewData.h"
38 #endif
39 
40 #if defined(WIN32) && !defined(__CYGWIN__)
41 #include <windows.h>
42 #include <io.h>
43 #else
44 #include <unistd.h>
45 #endif
46 
47 #if defined(HAVE_ANN)
48 #include "ANN/ANN.h"
49 #endif
50 
52 {
53  for(auto it = options.begin(); it != options.end(); ++it) delete it->second;
54  for(auto it = callbacks.begin(); it != callbacks.end(); ++it)
55  delete it->second;
56 }
57 
58 FieldOption *Field::getOption(const std::string &optionName)
59 {
60  auto it = options.find(optionName);
61  if(it == options.end()) {
62  Msg::Error("Field option '%s' does not exist", optionName.c_str());
63  return nullptr;
64  }
65  return it->second;
66 }
67 
69 {
70  for(auto it = begin(); it != end(); it++) { delete it->second; }
71  clear();
72 }
73 
75 {
76  auto it = find(id);
77  if(it == end()) return nullptr;
78  return it->second;
79 }
80 
81 Field *FieldManager::newField(int id, const std::string &type_name)
82 {
83  if(find(id) != end()) {
84  Msg::Error("Field id %i is already defined", id);
85  return nullptr;
86  }
87  if(mapTypeName.find(type_name) == mapTypeName.end()) {
88  Msg::Error("Unknown field type \"%s\"", type_name.c_str());
89  return nullptr;
90  }
91  Field *f = (*mapTypeName[type_name])();
92  if(!f) return nullptr;
93  f->id = id;
94  (*this)[id] = f;
95  return f;
96 }
97 
99 {
100  int i = 0;
101  auto it = begin();
102  while(1) {
103  i++;
104  while(it != end() && it->first < i) it++;
105  if(it == end() || it->first != i) break;
106  }
107  return std::max(i, 1);
108 }
109 
111 {
112  if(!empty())
113  return rbegin()->first;
114  else
115  return 0;
116 }
117 
119 {
120  auto it = find(id);
121  if(it == end()) {
122  Msg::Error("Cannot delete field id %i, it does not exist", id);
123  return;
124  }
125  delete it->second;
126  erase(it);
127 }
128 
129 // StructuredField
130 class StructuredField : public Field {
131 private:
132  double _o[3], _d[3];
133  int _n[3];
134  double *_data;
138  std::string _fileName;
139 
140 public:
142  {
143  _data = nullptr;
144  _errorStatus = false;
145  _textFormat = false;
146  _outsideValueSet = false;
148 
149  options["FileName"] =
150  new FieldOptionPath(_fileName, "Name of the input file", &updateNeeded);
151  options["TextFormat"] = new FieldOptionBool(
152  _textFormat,
153  "True for ASCII input files, false for binary files (4 bite "
154  "signed integers for n, double precision floating points for v, D and O)",
155  &updateNeeded);
156  options["SetOutsideValue"] = new FieldOptionBool(
157  _outsideValueSet, "True to use the \"OutsideValue\" option. If False, "
158  "the last values of the grid are used.");
159  options["OutsideValue"] = new FieldOptionDouble(
160  _outsideValue, "Value of the field outside the grid (only used if the "
161  "\"SetOutsideValue\" option is true).");
162  }
163  std::string getDescription()
164  {
165  return "Linearly interpolate between data provided on a 3D rectangular "
166  "structured grid.\n\n"
167  "The format of the input file is:\n\n"
168  " Ox Oy Oz \n"
169  " Dx Dy Dz \n"
170  " nx ny nz \n"
171  " v(0,0,0) v(0,0,1) v(0,0,2) ... \n"
172  " v(0,1,0) v(0,1,1) v(0,1,2) ... \n"
173  " v(0,2,0) v(0,2,1) v(0,2,2) ... \n"
174  " ... ... ... \n"
175  " v(1,0,0) ... ... \n\n"
176  "where O are the coordinates of the first node, D are the distances "
177  "between nodes in each direction, n are the numbers of nodes in "
178  "each direction, and v are the values on each node.";
179  }
180  const char *getName() { return "Structured"; }
182  {
183  if(_data) delete[] _data;
184  }
185  using Field::operator();
186  double operator()(double x, double y, double z, GEntity *ge = nullptr)
187  {
188  if(updateNeeded) {
189  _errorStatus = false;
190  try {
191  std::ifstream input;
192  if(_textFormat)
193  input.open(_fileName.c_str());
194  else
195  input.open(_fileName.c_str(), std::ios::binary);
196  if(!input.is_open()) {
197  Msg::Error("Could not open file '%s'", _fileName.c_str());
198  return MAX_LC;
199  }
200  input.exceptions(std::ifstream::eofbit | std::ifstream::failbit |
201  std::ifstream::badbit);
202  if(!_textFormat) {
203  input.read((char *)_o, 3 * sizeof(double));
204  input.read((char *)_d, 3 * sizeof(double));
205  input.read((char *)_n, 3 * sizeof(int));
206  int nt = _n[0] * _n[1] * _n[2];
207  if(nt <= 0) {
208  Msg::Error("Field %i: invalid number of data points %d x %d x %d",
209  this->id, _n[0], _n[1], _n[2]);
210  return MAX_LC;
211  }
212  if(_data) delete[] _data;
213  _data = new double[nt];
214  input.read((char *)_data, nt * sizeof(double));
215  }
216  else {
217  input >> _o[0] >> _o[1] >> _o[2] >> _d[0] >> _d[1] >> _d[2] >>
218  _n[0] >> _n[1] >> _n[2];
219  int nt = _n[0] * _n[1] * _n[2];
220  if(nt <= 0) {
221  Msg::Error("Field %i: invalid number of data points %d x %d x %d",
222  this->id, _n[0], _n[1], _n[2]);
223  return MAX_LC;
224  }
225  if(_data) delete[] _data;
226  _data = new double[nt];
227  for(int i = 0; i < nt; i++) input >> _data[i];
228  }
229  input.close();
230  } catch(...) {
231  _errorStatus = true;
232  Msg::Error("Field %i: error reading file '%s'", this->id,
233  _fileName.c_str());
234  }
235  for(int i = 0; i < 3; i++) {
236  // if there is a single point, make sure _d[i] != 0
237  if(_n[i] == 1 && !_d[i]) _d[i] = 1.;
238  }
239  if(!_d[0] || !_d[1] || !_d[2]) {
240  Msg::Error("Field %i: Dx, Dy and Dz should be non zero", this->id);
241  return MAX_LC;
242  }
243  updateNeeded = false;
244  }
245  if(_errorStatus) return MAX_LC;
246  // tri-linear
247  int id[2][3];
248  double xi[3];
249  double xyz[3] = {x, y, z};
250  for(int i = 0; i < 3; i++) {
251  id[0][i] = (int)floor((xyz[i] - _o[i]) / _d[i]);
252  id[1][i] = id[0][i] + 1;
253  if(_outsideValueSet && (id[0][i] < 0 || id[1][i] >= _n[i]) && _n[i] > 1)
254  return _outsideValue;
255  id[0][i] = std::max(std::min(id[0][i], _n[i] - 1), 0);
256  id[1][i] = std::max(std::min(id[1][i], _n[i] - 1), 0);
257  xi[i] = (xyz[i] - (_o[i] + id[0][i] * _d[i])) / _d[i];
258  xi[i] = std::max(std::min(xi[i], 1.), 0.);
259  }
260  double v = 0;
261  for(int i = 0; i < 2; i++)
262  for(int j = 0; j < 2; j++)
263  for(int k = 0; k < 2; k++) {
264  v += _data[id[i][0] * _n[1] * _n[2] + id[j][1] * _n[2] + id[k][2]] *
265  (i * xi[0] + (1 - i) * (1 - xi[0])) *
266  (j * xi[1] + (1 - j) * (1 - xi[1])) *
267  (k * xi[2] + (1 - k) * (1 - xi[2]));
268  }
269  return v;
270  }
271 };
272 
273 class LonLatField : public Field {
274 private:
277 
278 public:
279  std::string getDescription()
280  {
281  return "Evaluate Field[InField] in geographic coordinates (longitude, "
282  "latitude):\n\n"
283  " F = Field[InField](atan(y / x), asin(z / sqrt(x^2 + y^2 + z^2))";
284  }
286  {
287  _inField = 1;
288  _fromStereo = 0;
289  _stereoRadius = 6371e3;
290 
291  options["InField"] =
292  new FieldOptionInt(_inField, "Tag of the field to evaluate");
293  options["FromStereo"] = new FieldOptionInt(
294  _fromStereo, "If = 1, the mesh is in stereographic coordinates: "
295  "xi = 2Rx/(R+z), eta = 2Ry/(R+z)");
296  options["RadiusStereo"] = new FieldOptionDouble(
297  _stereoRadius, "Radius of the sphere of the stereograpic coordinates");
298 
299  // deprecated names
300  options["IField"] =
301  new FieldOptionInt(_inField, "[Deprecated]", nullptr, true);
302  }
303  const char *getName() { return "LonLat"; }
304  using Field::operator();
305  double operator()(double x, double y, double z, GEntity *ge = nullptr)
306  {
307  if(_inField == id) return MAX_LC;
308  Field *field = GModel::current()->getFields()->get(_inField);
309  if(!field) {
310  Msg::Warning("Unknown Field %i", _inField);
311  return MAX_LC;
312  }
313  if(_fromStereo == 1) {
314  double xi = x;
315  double eta = y;
316  double r2 = _stereoRadius * _stereoRadius;
317  x = 4 * r2 * xi / (4 * r2 + xi * xi + eta * eta);
318  y = 4 * r2 * eta / (4 * r2 + xi * xi + eta * eta);
319  z = _stereoRadius * (4 * r2 - eta * eta - xi * xi) /
320  (4 * r2 + xi * xi + eta * eta);
321  }
322  return (*field)(atan2(y, x), asin(z / _stereoRadius), 0);
323  }
324 };
325 
326 class BoxField : public Field {
327 private:
329 
330 public:
331  std::string getDescription()
332  {
333  return "Return VIn inside the box, and VOut outside. The box is defined "
334  "by\n\n"
335  " Xmin <= x <= XMax &&\n"
336  " YMin <= y <= YMax &&\n"
337  " ZMin <= z <= ZMax\n\n"
338  "If Thickness is > 0, the mesh size is interpolated between VIn and "
339  "VOut in a layer around the box of the prescribed thickness.";
340  }
342  {
343  _vIn = _vOut = MAX_LC;
344  _xMin = _xMax = _yMin = _yMax = _zMin = _zMax = _thick = 0.;
345 
346  options["VIn"] = new FieldOptionDouble(_vIn, "Value inside the box");
347  options["VOut"] = new FieldOptionDouble(_vOut, "Value outside the box");
348  options["XMin"] =
349  new FieldOptionDouble(_xMin, "Minimum X coordinate of the box");
350  options["XMax"] =
351  new FieldOptionDouble(_xMax, "Maximum X coordinate of the box");
352  options["YMin"] =
353  new FieldOptionDouble(_yMin, "Minimum Y coordinate of the box");
354  options["YMax"] =
355  new FieldOptionDouble(_yMax, "Maximum Y coordinate of the box");
356  options["ZMin"] =
357  new FieldOptionDouble(_zMin, "Minimum Z coordinate of the box");
358  options["ZMax"] =
359  new FieldOptionDouble(_zMax, "Maximum Z coordinate of the box");
360  options["Thickness"] = new FieldOptionDouble(
361  _thick, "Thickness of a transition layer outside the box");
362  }
363  const char *getName() { return "Box"; }
364  using Field::operator();
365  double computeDistance(double xp, double yp, double zp)
366  {
367  // orthogonal basis with origin (_xMin,_yMin,_zMin)
368  double x0[3] = {_xMin, _yMin, _zMin};
369  double x1[3] = {_xMax, _yMin, _zMin};
370  double y1[3] = {_xMin, _yMax, _zMin};
371  double z1[3] = {_xMin, _yMin, _zMax};
372  double nx[3] = {x1[0] - x0[0], x1[1] - x0[1], x1[2] - x0[2]};
373  double ny[3] = {y1[0] - x0[0], y1[1] - x0[1], y1[2] - x0[2]};
374  double nz[3] = {z1[0] - x0[0], z1[1] - x0[1], z1[2] - x0[2]};
375  double pvect[3] = {xp - x0[0], yp - x0[1], zp - x0[2]};
376  double projX = scalProd(nx, pvect);
377  double tempX = scalProd(nx, nx);
378  if(tempX) projX /= tempX;
379  double projY = scalProd(ny, pvect);
380  double tempY = scalProd(ny, ny);
381  if(tempY) projY /= tempY;
382  double projZ = scalProd(nz, pvect);
383  double tempZ = scalProd(nz, nz);
384  if(tempZ) projZ /= tempZ;
385  if(projX < 0.0) projX = 0.0;
386  if(projX > 1.0) projX = 1.0;
387  if(projY < 0.0) projY = 0.0;
388  if(projY > 1.0) projY = 1.0;
389  if(projZ < 0.0) projZ = 0.0;
390  if(projZ > 1.0) projZ = 1.0;
391  double psbox[3] = {x0[0] + projX * nx[0] + projY * ny[0] + projZ * nz[0],
392  x0[1] + projX * nx[1] + projY * ny[1] + projZ * nz[1],
393  x0[2] + projX * nx[2] + projY * ny[2] + projZ * nz[2]};
394  double dist =
395  sqrt(std::pow((psbox[0] - xp), 2) + std::pow((psbox[1] - yp), 2) +
396  std::pow((psbox[2] - zp), 2));
397  return dist;
398  }
399  double operator()(double x, double y, double z, GEntity *ge = nullptr)
400  {
401  // inside
402  if(x >= _xMin && x <= _xMax && y >= _yMin && y <= _yMax && z >= _zMin &&
403  z <= _zMax) {
404  return _vIn;
405  }
406  // transition layer
407  if(_thick > 0) {
408  double dist = computeDistance(x, y, z);
409  if(dist <= _thick) return _vIn + (dist / _thick) * (_vOut - _vIn);
410  }
411  return _vOut;
412  }
413 };
414 
415 class CylinderField : public Field {
416 private:
417  double _vIn, _vOut;
418  double _xc, _yc, _zc;
419  double _xa, _ya, _za;
420  double _r;
421 
422 public:
423  std::string getDescription()
424  {
425  return "Return VIn inside a frustrated cylinder, and VOut outside. "
426  "The cylinder is defined by\n\n"
427  " ||dX||^2 < R^2 &&\n"
428  " (X-X0).A < ||A||^2\n"
429  " dX = (X - X0) - ((X - X0).A)/(||A||^2) . A";
430  }
432  {
433  _vIn = _vOut = MAX_LC;
434  _xc = _yc = _zc = _xa = _ya = _r = 0.;
435  _za = 1.;
436 
437  options["VIn"] = new FieldOptionDouble(_vIn, "Value inside the cylinder");
438  options["VOut"] =
439  new FieldOptionDouble(_vOut, "Value outside the cylinder");
440  options["XCenter"] =
441  new FieldOptionDouble(_xc, "X coordinate of the cylinder center");
442  options["YCenter"] =
443  new FieldOptionDouble(_yc, "Y coordinate of the cylinder center");
444  options["ZCenter"] =
445  new FieldOptionDouble(_zc, "Z coordinate of the cylinder center");
446  options["XAxis"] =
447  new FieldOptionDouble(_xa, "X component of the cylinder axis");
448  options["YAxis"] =
449  new FieldOptionDouble(_ya, "Y component of the cylinder axis");
450  options["ZAxis"] =
451  new FieldOptionDouble(_za, "Z component of the cylinder axis");
452  options["Radius"] = new FieldOptionDouble(_r, "Radius");
453  }
454  const char *getName() { return "Cylinder"; }
455  using Field::operator();
456  double operator()(double x, double y, double z, GEntity *ge = nullptr)
457  {
458  double dx = x - _xc;
459  double dy = y - _yc;
460  double dz = z - _zc;
461 
462  double adx =
463  (_xa * dx + _ya * dy + _za * dz) / (_xa * _xa + _ya * _ya + _za * _za);
464 
465  dx -= adx * _xa;
466  dy -= adx * _ya;
467  dz -= adx * _za;
468 
469  return ((dx * dx + dy * dy + dz * dz < _r * _r) && fabs(adx) < 1) ? _vIn :
470  _vOut;
471  }
472 };
473 
474 class BallField : public Field {
475 private:
476  double _vIn, _vOut;
477  double _xc, _yc, _zc;
478  double _r, _thick;
479 
480 public:
481  std::string getDescription()
482  {
483  return "Return VIn inside a spherical ball, and VOut outside. "
484  "The ball is defined by\n\n"
485  " ||dX||^2 < R^2 &&\n"
486  " dX = (X - XC)^2 + (Y-YC)^2 + (Z-ZC)^2\n\n"
487  "If Thickness is > 0, the mesh size is interpolated between VIn and "
488  "VOut in a layer around the ball of the prescribed thickness.";
489  }
491  {
492  _vIn = _vOut = MAX_LC;
493  _xc = _yc = _zc = _r = _thick = 0.;
494 
495  options["VIn"] = new FieldOptionDouble(_vIn, "Value inside the ball");
496  options["VOut"] = new FieldOptionDouble(_vOut, "Value outside the ball");
497  options["XCenter"] =
498  new FieldOptionDouble(_xc, "X coordinate of the ball center");
499  options["YCenter"] =
500  new FieldOptionDouble(_yc, "Y coordinate of the ball center");
501  options["ZCenter"] =
502  new FieldOptionDouble(_zc, "Z coordinate of the ball center");
503  options["Radius"] = new FieldOptionDouble(_r, "Radius");
504  options["Thickness"] = new FieldOptionDouble(
505  _thick, "Thickness of a transition layer outside the ball");
506  }
507  const char *getName() { return "Ball"; }
508  using Field::operator();
509  double operator()(double x, double y, double z, GEntity *ge = nullptr)
510  {
511  double dx = x - _xc;
512  double dy = y - _yc;
513  double dz = z - _zc;
514  double d = sqrt(dx * dx + dy * dy + dz * dz);
515  if(d < _r) return _vIn;
516  // transition layer
517  if(_thick > 0) {
518  double dist = d - _r;
519  if(dist <= _thick) return _vIn + (dist / _thick) * (_vOut - _vIn);
520  }
521  return _vOut;
522  }
523 };
524 
525 class FrustumField : public Field {
526 private:
527  double _x1, _y1, _z1;
528  double _x2, _y2, _z2;
529  double _r1i, _r1o, _r2i, _r2o;
530  double _v1i, _v1o, _v2i, _v2o;
531 
532 public:
533  std::string getDescription()
534  {
535  return "Interpolate mesh sizes on a extended cylinder frustrum defined "
536  "by inner (R1i and R2i) and outer (R1o and R2o) radii and two "
537  "endpoints P1 and P2."
538  "The field value F for a point P is given by :\n\n"
539  " u = P1P . P1P2 / ||P1P2|| \n"
540  " r = || P1P - u*P1P2 || \n"
541  " Ri = (1 - u) * R1i + u * R2i \n"
542  " Ro = (1 - u) * R1o + u * R2o \n"
543  " v = (r - Ri) / (Ro - Ri) \n"
544  " F = (1 - v) * ((1 - u) * v1i + u * v2i) + "
545  " v * ((1 - u) * v1o + u * v2o)\n"
546  "with (u, v) in [0, 1] x [0, 1].";
547  }
549  {
550  _x1 = _y1 = _z1 = 0.;
551  _x2 = _y2 = _z2 = 0.;
552  _z1 = 1.;
553  _r1i = _r2i = 0.;
554  _r1o = _r2o = 1.;
555  _v1i = _v2i = 0.1;
556  _v1o = _v2o = 1.;
557 
558  options["X1"] = new FieldOptionDouble(_x1, "X coordinate of endpoint 1");
559  options["Y1"] = new FieldOptionDouble(_y1, "Y coordinate of endpoint 1");
560  options["Z1"] = new FieldOptionDouble(_z1, "Z coordinate of endpoint 1");
561  options["X2"] = new FieldOptionDouble(_x2, "X coordinate of endpoint 2");
562  options["Y2"] = new FieldOptionDouble(_y2, "Y coordinate of endpoint 2");
563  options["Z2"] = new FieldOptionDouble(_z2, "Z coordinate of endpoint 2");
564  options["InnerR1"] =
565  new FieldOptionDouble(_r1i, "Inner radius of Frustum at endpoint 1");
566  options["OuterR1"] =
567  new FieldOptionDouble(_r1o, "Outer radius of Frustum at endpoint 1");
568  options["InnerR2"] =
569  new FieldOptionDouble(_r2i, "Inner radius of Frustum at endpoint 2");
570  options["OuterR2"] =
571  new FieldOptionDouble(_r2o, "Outer radius of Frustum at endpoint 2");
572  options["InnerV1"] =
573  new FieldOptionDouble(_v1i, "Mesh size at point 1, inner radius");
574  options["OuterV1"] =
575  new FieldOptionDouble(_v1o, "Mesh size at point 1, outer radius");
576  options["InnerV2"] =
577  new FieldOptionDouble(_v2i, "Mesh size at point 2, inner radius");
578  options["OuterV2"] =
579  new FieldOptionDouble(_v2o, "Mesh size at point 2, outer radius");
580 
581  // deprecated names
582  options["R1_inner"] =
583  new FieldOptionDouble(_r1i, "[Deprecated]", nullptr, true);
584  options["R1_outer"] =
585  new FieldOptionDouble(_r1o, "[Deprecated]", nullptr, true);
586  options["R2_inner"] =
587  new FieldOptionDouble(_r2i, "[Deprecated]", nullptr, true);
588  options["R2_outer"] =
589  new FieldOptionDouble(_r2o, "[Deprecated]", nullptr, true);
590  options["V1_inner"] =
591  new FieldOptionDouble(_v1i, "[Deprecated]", nullptr, true);
592  options["V1_outer"] =
593  new FieldOptionDouble(_v1o, "[Deprecated]", nullptr, true);
594  options["V2_inner"] =
595  new FieldOptionDouble(_v2i, "[Deprecated]", nullptr, true);
596  options["V2_outer"] =
597  new FieldOptionDouble(_v2o, "[Deprecated]", nullptr, true);
598  }
599  const char *getName() { return "Frustum"; }
600  using Field::operator();
601  double operator()(double x, double y, double z, GEntity *ge = nullptr)
602  {
603  double dx = x - _x1;
604  double dy = y - _y1;
605  double dz = z - _z1;
606  double x12 = _x2 - _x1;
607  double y12 = _y2 - _y1;
608  double z12 = _z2 - _z1;
609  double l12 = sqrt(x12 * x12 + y12 * y12 + z12 * z12);
610 
611  double l = (dx * x12 + dy * y12 + dz * z12) / l12;
612  double r = sqrt(dx * dx + dy * dy + dz * dz - l * l);
613 
614  double u = l / l12; // u varies between 0 (P1) and 1 (P2)
615  double ri = (1 - u) * _r1i + u * _r2i;
616  double ro = (1 - u) * _r1o + u * _r2o;
617  double v = (r - ri) / (ro - ri); // v varies between 0 (inner) and 1 (outer)
618 
619  double lc = MAX_LC;
620  if(u >= 0 && u <= 1 && v >= 0 && v <= 1) {
621  lc =
622  (1 - v) * ((1 - u) * _v1i + u * _v2i) + v * ((1 - u) * _v1o + u * _v2o);
623  }
624  return lc;
625  }
626 };
627 
628 class ThresholdField : public Field {
629 protected:
630  int _inField;
633 
634 public:
635  virtual const char *getName() { return "Threshold"; }
636  virtual std::string getDescription()
637  {
638  return "Return F = SizeMin if Field[InField] <= DistMin, "
639  "F = SizeMax if Field[InField] >= DistMax, and "
640  "the interpolation between SizeMin and SizeMax if DistMin < "
641  "Field[InField] < DistMax.";
642  }
644  {
645  _inField = 0;
646  _dMin = 1;
647  _dMax = 10;
648  _lcMin = 0.1;
649  _lcMax = 1;
650  _sigmoid = false;
651  _stopAtDistMax = false;
652 
653  options["InField"] =
654  new FieldOptionInt(_inField, "Tag of the field computing the input "
655  "value, usually a distance");
656  options["DistMin"] = new FieldOptionDouble(
657  _dMin, "Value up to which the mesh size will be SizeMin");
658  options["DistMax"] = new FieldOptionDouble(
659  _dMax, "Value after which the mesh size will be SizeMax");
660  options["SizeMin"] =
661  new FieldOptionDouble(_lcMin, "Mesh size when value < DistMin");
662  options["SizeMax"] =
663  new FieldOptionDouble(_lcMax, "Mesh size when value > DistMax");
664  options["Sigmoid"] = new FieldOptionBool(
665  _sigmoid,
666  "True to interpolate between SizeMin and LcMax using a sigmoid, "
667  "false to interpolate linearly");
668  options["StopAtDistMax"] = new FieldOptionBool(
669  _stopAtDistMax, "True to not impose mesh size outside DistMax (i.e., "
670  "F = a very big value if Field[InField] > DistMax)");
671 
672  // deprecated names
673  options["IField"] =
674  new FieldOptionInt(_inField, "[Deprecated]", nullptr, true);
675  options["LcMin"] =
676  new FieldOptionDouble(_lcMin, "[Deprecated]", nullptr, true);
677  options["LcMax"] =
678  new FieldOptionDouble(_lcMax, "[Deprecated]", nullptr, true);
679  }
680  using Field::operator();
681  double operator()(double x, double y, double z, GEntity *ge = nullptr)
682  {
683  if(_inField == id) return MAX_LC;
684  Field *field = GModel::current()->getFields()->get(_inField);
685  if(!field) {
686  Msg::Warning("Unknown Field %i", _inField);
687  return MAX_LC;
688  }
689  double d = (*field)(x, y, z);
690  if(_stopAtDistMax && d >= _dMax) return MAX_LC;
691  double r = (d - _dMin) / (_dMax - _dMin);
692  r = std::max(std::min(r, 1.), 0.);
693  double lc;
694  if(_sigmoid) {
695  double s = exp(12. * r - 6.) / (1. + exp(12. * r - 6.));
696  lc = _lcMin * (1. - s) + _lcMax * s;
697  }
698  else { // linear
699  lc = _lcMin * (1 - r) + _lcMax * r;
700  }
701  return lc;
702  }
703 };
704 
705 class GradientField : public Field {
706 private:
708  double _delta;
709 
710 public:
711  const char *getName() { return "Gradient"; }
712  std::string getDescription()
713  {
714  return "Compute the finite difference gradient of Field[InField]:\n\n"
715  " F = (Field[InField](X + Delta/2) - "
716  " Field[InField](X - Delta/2)) / Delta";
717  }
719  {
720  _inField = 1;
721  _kind = 3;
722  _delta = CTX::instance()->lc / 1e4;
723 
724  options["InField"] = new FieldOptionInt(_inField, "Input field tag");
725  options["Kind"] = new FieldOptionInt(
726  _kind,
727  "Component of the gradient to evaluate: 0 for X, 1 for Y, 2 for Z, "
728  "3 for the norm");
729  options["Delta"] = new FieldOptionDouble(_delta, "Finite difference step");
730 
731  // deprecated names
732  options["IField"] =
733  new FieldOptionInt(_inField, "[Deprecated]", nullptr, true);
734  }
735  using Field::operator();
736  double operator()(double x, double y, double z, GEntity *ge = nullptr)
737  {
738  if(_inField == id) return MAX_LC;
739  Field *field = GModel::current()->getFields()->get(_inField);
740  if(!field) {
741  Msg::Warning("Unknown Field %i", _inField);
742  return MAX_LC;
743  }
744  double gx, gy, gz;
745  switch(_kind) {
746  case 0: /* x */
747  return ((*field)(x + _delta / 2, y, z) - (*field)(x - _delta / 2, y, z)) /
748  _delta;
749  case 1: /* y */
750  return ((*field)(x, y + _delta / 2, z) - (*field)(x, y - _delta / 2, z)) /
751  _delta;
752  case 2: /* z */
753  return ((*field)(x, y, z + _delta / 2) - (*field)(x, y, z - _delta / 2)) /
754  _delta;
755  case 3: /* norm */
756  gx = ((*field)(x + _delta / 2, y, z) - (*field)(x - _delta / 2, y, z)) /
757  _delta;
758  gy = ((*field)(x, y + _delta / 2, z) - (*field)(x, y - _delta / 2, z)) /
759  _delta;
760  gz = ((*field)(x, y, z + _delta / 2) - (*field)(x, y, z - _delta / 2)) /
761  _delta;
762  return sqrt(gx * gx + gy * gy + gz * gz);
763  default:
764  Msg::Error("Field %i: unknown kind (%i) of gradient", this->id, _kind);
765  return MAX_LC;
766  }
767  }
768 };
769 
770 class CurvatureField : public Field {
771 private:
772  int _inField;
773  double _delta;
774 
775 public:
776  const char *getName() { return "Curvature"; }
777  std::string getDescription()
778  {
779  return "Compute the curvature of Field[InField]:\n\n"
780  " F = div(norm(grad(Field[InField])))";
781  }
783  {
784  _inField = 1;
785  _delta = CTX::instance()->lc / 1e4;
786 
787  options["InField"] = new FieldOptionInt(_inField, "Input field tag");
788  options["Delta"] =
789  new FieldOptionDouble(_delta, "Step of the finite differences");
790 
791  // deprecated names
792  options["IField"] =
793  new FieldOptionInt(_inField, "[Deprecated]", nullptr, true);
794  }
795  void grad_norm(Field &f, double x, double y, double z, double *g)
796  {
797  g[0] = f(x + _delta / 2, y, z) - f(x - _delta / 2, y, z);
798  g[1] = f(x, y + _delta / 2, z) - f(x, y - _delta / 2, z);
799  g[2] = f(x, y, z + _delta / 2) - f(x, y, z - _delta / 2);
800  double n = sqrt(g[0] * g[0] + g[1] * g[1] + g[2] * g[2]);
801  g[0] /= n;
802  g[1] /= n;
803  g[2] /= n;
804  }
805  using Field::operator();
806  double operator()(double x, double y, double z, GEntity *ge = nullptr)
807  {
808  if(_inField == id) return MAX_LC;
809  Field *field = GModel::current()->getFields()->get(_inField);
810  if(!field) {
811  Msg::Warning("Unknown Field %i", _inField);
812  return MAX_LC;
813  }
814  double grad[6][3];
815  grad_norm(*field, x + _delta / 2, y, z, grad[0]);
816  grad_norm(*field, x - _delta / 2, y, z, grad[1]);
817  grad_norm(*field, x, y + _delta / 2, z, grad[2]);
818  grad_norm(*field, x, y - _delta / 2, z, grad[3]);
819  grad_norm(*field, x, y, z + _delta / 2, grad[4]);
820  grad_norm(*field, x, y, z - _delta / 2, grad[5]);
821  return (grad[0][0] - grad[1][0] + grad[2][1] - grad[3][1] + grad[4][2] -
822  grad[5][2]) /
823  _delta;
824  }
825 };
826 
827 class MaxEigenHessianField : public Field {
828 private:
829  int _inField;
830  double _delta;
831 
832 public:
833  const char *getName() { return "MaxEigenHessian"; }
834  std::string getDescription()
835  {
836  return "Compute the maximum eigenvalue of the Hessian matrix of "
837  "Field[InField], with the gradients evaluated by finite "
838  "differences:\n\n"
839  " F = max(eig(grad(grad(Field[InField]))))";
840  }
842  {
843  _inField = 1;
844  _delta = CTX::instance()->lc / 1e4;
845 
846  options["InField"] = new FieldOptionInt(_inField, "Input field tag");
847  options["Delta"] =
848  new FieldOptionDouble(_delta, "Step used for the finite differences");
849 
850  // deprecated names
851  options["IField"] =
852  new FieldOptionInt(_inField, "[Deprecated]", nullptr, true);
853  }
854  using Field::operator();
855  double operator()(double x, double y, double z, GEntity *ge = nullptr)
856  {
857  if(_inField == id) return MAX_LC;
858  Field *field = GModel::current()->getFields()->get(_inField);
859  if(!field) {
860  Msg::Warning("Unknown Field %i", _inField);
861  return MAX_LC;
862  }
863  double mat[3][3], eig[3];
864  mat[1][0] = mat[0][1] = (*field)(x + _delta / 2, y + _delta / 2, z) +
865  (*field)(x - _delta / 2, y - _delta / 2, z) -
866  (*field)(x - _delta / 2, y + _delta / 2, z) -
867  (*field)(x + _delta / 2, y - _delta / 2, z);
868  mat[2][0] = mat[0][2] = (*field)(x + _delta / 2, y, z + _delta / 2) +
869  (*field)(x - _delta / 2, y, z - _delta / 2) -
870  (*field)(x - _delta / 2, y, z + _delta / 2) -
871  (*field)(x + _delta / 2, y, z - _delta / 2);
872  mat[2][1] = mat[1][2] = (*field)(x, y + _delta / 2, z + _delta / 2) +
873  (*field)(x, y - _delta / 2, z - _delta / 2) -
874  (*field)(x, y - _delta / 2, z + _delta / 2) -
875  (*field)(x, y + _delta / 2, z - _delta / 2);
876  double f = (*field)(x, y, z);
877  mat[0][0] = (*field)(x + _delta, y, z) + (*field)(x - _delta, y, z) - 2 * f;
878  mat[1][1] = (*field)(x, y + _delta, z) + (*field)(x, y - _delta, z) - 2 * f;
879  mat[2][2] = (*field)(x, y, z + _delta) + (*field)(x, y, z - _delta) - 2 * f;
880  eigenvalue(mat, eig);
881  return eig[0] / (_delta * _delta);
882  }
883 };
884 
885 class LaplacianField : public Field {
886 private:
887  int _inField;
888  double _delta;
889 
890 public:
891  const char *getName() { return "Laplacian"; }
892  std::string getDescription()
893  {
894  return "Compute finite difference the Laplacian of Field[InField]:\n\n"
895  " F = G(x+d,y,z) + G(x-d,y,z) +\n"
896  " G(x,y+d,z) + G(x,y-d,z) +\n"
897  " G(x,y,z+d) + G(x,y,z-d) - 6 * G(x,y,z),\n\n"
898  "where G = Field[InField] and d = Delta.";
899  }
901  {
902  _inField = 1;
903  _delta = CTX::instance()->lc / 1e4;
904 
905  options["InField"] = new FieldOptionInt(_inField, "Input field tag");
906  options["Delta"] = new FieldOptionDouble(_delta, "Finite difference step");
907 
908  // deprecated names
909  options["IField"] =
910  new FieldOptionInt(_inField, "[Deprecated]", nullptr, true);
911  }
912  using Field::operator();
913  double operator()(double x, double y, double z, GEntity *ge = nullptr)
914  {
915  if(_inField == id) return MAX_LC;
916  Field *field = GModel::current()->getFields()->get(_inField);
917  if(!field) {
918  Msg::Warning("Unknown Field %i", _inField);
919  return MAX_LC;
920  }
921  return ((*field)(x + _delta, y, z) + (*field)(x - _delta, y, z) +
922  (*field)(x, y + _delta, z) + (*field)(x, y - _delta, z) +
923  (*field)(x, y, z + _delta) + (*field)(x, y, z - _delta) -
924  6 * (*field)(x, y, z)) /
925  (_delta * _delta);
926  }
927 };
928 
929 class MeanField : public Field {
930 private:
931  int _inField;
932  double _delta;
933 
934 public:
935  const char *getName() { return "Mean"; }
936  std::string getDescription()
937  {
938  return "Return the mean value\n\n"
939  " F = (G(x + delta, y, z) + G(x - delta, y, z) +\n"
940  " G(x, y + delta, z) + G(x, y - delta, z) +\n"
941  " G(x, y, z + delta) + G(x, y, z - delta) +\n"
942  " G(x, y, z)) / 7,\n\n"
943  "where G = Field[InField].";
944  }
946  {
947  _inField = 1;
948  _delta = CTX::instance()->lc / 1e4;
949 
950  options["InField"] = new FieldOptionInt(_inField, "Input field tag");
951  options["Delta"] =
952  new FieldOptionDouble(_delta, "Distance used to compute the mean value");
953 
954  // deprecated names
955  options["IField"] =
956  new FieldOptionInt(_inField, "[Deprecated]", nullptr, true);
957  }
958  using Field::operator();
959  double operator()(double x, double y, double z, GEntity *ge = nullptr)
960  {
961  if(_inField == id) return MAX_LC;
962  Field *field = GModel::current()->getFields()->get(_inField);
963  if(!field) {
964  Msg::Warning("Unknown Field %i", _inField);
965  return MAX_LC;
966  }
967  return ((*field)(x + _delta, y, z) + (*field)(x - _delta, y, z) +
968  (*field)(x, y + _delta, z) + (*field)(x, y - _delta, z) +
969  (*field)(x, y, z + _delta) + (*field)(x, y, z - _delta) +
970  (*field)(x, y, z)) /
971  7;
972  }
973 };
974 
976 private:
978  std::set<int> _fields;
979 
980 public:
981  MathEvalExpression() : _f(nullptr) {}
983  {
984  if(_f) delete _f;
985  }
986  bool set_function(const std::string &f)
987  {
988  // get id numbers of fields appearing in the function
989  _fields.clear();
990  std::size_t i = 0;
991  while(i < f.size()) {
992  std::size_t j = 0;
993  if(f[i] == 'F') {
994  std::string id("");
995  while(i + 1 + j < f.size() && f[i + 1 + j] >= '0' &&
996  f[i + 1 + j] <= '9') {
997  id += f[i + 1 + j];
998  j++;
999  }
1000  if(id.size() > 0) {
1001  _fields.insert(atoi(id.c_str()));
1002  }
1003  }
1004  i += j + 1;
1005  }
1006  std::vector<std::string> expressions(1), variables(3 + _fields.size());
1007  expressions[0] = f;
1008  variables[0] = "x";
1009  variables[1] = "y";
1010  variables[2] = "z";
1011  i = 3;
1012  for(auto it = _fields.begin(); it != _fields.end(); it++) {
1013  std::ostringstream sstream;
1014  sstream << "F" << *it;
1015  variables[i++] = sstream.str();
1016  }
1017  if(_f) delete _f;
1018  _f = new mathEvaluator(expressions, variables);
1019  if(expressions.empty()) {
1020  delete _f;
1021  _f = nullptr;
1022  return false;
1023  }
1024  return true;
1025  }
1026  double evaluate(double x, double y, double z)
1027  {
1028  if(!_f) return MAX_LC;
1029  std::vector<double> values(3 + _fields.size()), res(1);
1030  values[0] = x;
1031  values[1] = y;
1032  values[2] = z;
1033  int i = 3;
1034  for(auto it = _fields.begin(); it != _fields.end(); it++) {
1035  Field *field = GModel::current()->getFields()->get(*it);
1036  if(field) {
1037  values[i++] = (*field)(x, y, z);
1038  }
1039  else {
1040  Msg::Warning("Unknown Field %i in MathEval", *it);
1041  values[i++] = MAX_LC;
1042  }
1043  }
1044  if(_f->eval(values, res))
1045  return res[0];
1046  else
1047  return MAX_LC;
1048  }
1049 };
1050 
1052 private:
1054  std::set<int> _fields[6];
1055 
1056 public:
1058  {
1059  for(int i = 0; i < 6; i++) _f[i] = nullptr;
1060  }
1062  {
1063  for(int i = 0; i < 6; i++)
1064  if(_f[i]) delete _f[i];
1065  }
1066  bool set_function(int iFunction, const std::string &f)
1067  {
1068  // get id numbers of fields appearing in the function
1069  _fields[iFunction].clear();
1070  std::size_t i = 0;
1071  while(i < f.size()) {
1072  std::size_t j = 0;
1073  if(f[i] == 'F') {
1074  std::string id("");
1075  while(i + 1 + j < f.size() && f[i + 1 + j] >= '0' &&
1076  f[i + 1 + j] <= '9') {
1077  id += f[i + 1 + j];
1078  j++;
1079  }
1080  _fields[iFunction].insert(atoi(id.c_str()));
1081  }
1082  i += j + 1;
1083  }
1084  std::vector<std::string> expressions(1),
1085  variables(3 + _fields[iFunction].size());
1086  expressions[0] = f;
1087  variables[0] = "x";
1088  variables[1] = "y";
1089  variables[2] = "z";
1090  i = 3;
1091  for(auto it = _fields[iFunction].begin(); it != _fields[iFunction].end();
1092  it++) {
1093  std::ostringstream sstream;
1094  sstream << "F" << *it;
1095  variables[i++] = sstream.str();
1096  }
1097  if(_f[iFunction]) delete _f[iFunction];
1098  _f[iFunction] = new mathEvaluator(expressions, variables);
1099  if(expressions.empty()) {
1100  delete _f[iFunction];
1101  _f[iFunction] = nullptr;
1102  return false;
1103  }
1104  return true;
1105  }
1106  void evaluate(double x, double y, double z, SMetric3 &metr)
1107  {
1108  const int index[6][2] = {{0, 0}, {1, 1}, {2, 2}, {0, 1}, {0, 2}, {1, 2}};
1109  for(int iFunction = 0; iFunction < 6; iFunction++) {
1110  if(!_f[iFunction])
1111  metr(index[iFunction][0], index[iFunction][1]) = MAX_LC;
1112  else {
1113  std::vector<double> values(3 + _fields[iFunction].size()), res(1);
1114  values[0] = x;
1115  values[1] = y;
1116  values[2] = z;
1117  int i = 3;
1118  for(auto it = _fields[iFunction].begin();
1119  it != _fields[iFunction].end(); it++) {
1120  Field *field = GModel::current()->getFields()->get(*it);
1121  if(field) {
1122  values[i++] = (*field)(x, y, z);
1123  }
1124  else {
1125  Msg::Warning("Unknown Field %i", *it);
1126  values[i++] = MAX_LC;
1127  }
1128  }
1129  if(_f[iFunction]->eval(values, res))
1130  metr(index[iFunction][0], index[iFunction][1]) = res[0];
1131  else
1132  metr(index[iFunction][0], index[iFunction][1]) = MAX_LC;
1133  }
1134  }
1135  }
1136 };
1137 
1138 class MathEvalField : public Field {
1139 private:
1141  std::string _f;
1142 
1143 public:
1145  {
1146  _f = "F2 + Sin(z)";
1147  options["F"] = new FieldOptionString(
1148  _f, "Mathematical function to evaluate.", &updateNeeded);
1149  }
1150  using Field::operator();
1151  double operator()(double x, double y, double z, GEntity *ge = nullptr)
1152  {
1153  double ret = 0;
1154 #pragma omp critical
1155  {
1156  if(updateNeeded) {
1157  if(!_expr.set_function(_f))
1158  Msg::Error("Field %i: invalid matheval expression \"%s\"", this->id,
1159  _f.c_str());
1160  updateNeeded = false;
1161  }
1162  ret = _expr.evaluate(x, y, z);
1163  }
1164  return ret;
1165  }
1166  const char *getName() { return "MathEval"; }
1167  std::string getDescription()
1168  {
1169  return "Evaluate a mathematical expression. The expression can contain "
1170  "x, y, z for spatial coordinates, F0, F1, ... for field values, and "
1171  "mathematical functions.";
1172  }
1173 };
1174 
1175 class MathEvalFieldAniso : public Field {
1176 private:
1178  std::string _f[6];
1179 
1180 public:
1181  virtual bool isotropic() const { return false; }
1183  {
1184  _f[0] = "F2 + Sin(z)";
1185  _f[1] = "F2 + Sin(z)";
1186  _f[2] = "F2 + Sin(z)";
1187  _f[3] = "F2 + Sin(z)";
1188  _f[4] = "F2 + Sin(z)";
1189  _f[5] = "F2 + Sin(z)";
1190 
1191  options["M11"] = new FieldOptionString(
1192  _f[0], "Element 11 of the metric tensor", &updateNeeded);
1193  options["M22"] = new FieldOptionString(
1194  _f[1], "Element 22 of the metric tensor", &updateNeeded);
1195  options["M33"] = new FieldOptionString(
1196  _f[2], "Element 33 of the metric tensor", &updateNeeded);
1197  options["M12"] = new FieldOptionString(
1198  _f[3], "Element 12 of the metric tensor", &updateNeeded);
1199  options["M13"] = new FieldOptionString(
1200  _f[4], "Element 13 of the metric tensor", &updateNeeded);
1201  options["M23"] = new FieldOptionString(
1202  _f[5], "Element 23 of the metric tensor", &updateNeeded);
1203 
1204  // deprecated names
1205  options["m11"] =
1206  new FieldOptionString(_f[0], "[Deprecated]", &updateNeeded, true);
1207  options["m22"] =
1208  new FieldOptionString(_f[1], "[Deprecated]", &updateNeeded, true);
1209  options["m33"] =
1210  new FieldOptionString(_f[2], "[Deprecated]", &updateNeeded, true);
1211  options["m12"] =
1212  new FieldOptionString(_f[3], "[Deprecated]", &updateNeeded, true);
1213  options["m13"] =
1214  new FieldOptionString(_f[4], "[Deprecated]", &updateNeeded, true);
1215  options["m23"] =
1216  new FieldOptionString(_f[5], "[Deprecated]", &updateNeeded, true);
1217  }
1218  void operator()(double x, double y, double z, SMetric3 &metr,
1219  GEntity *ge = nullptr)
1220  {
1221 #pragma omp critical
1222  {
1223  if(updateNeeded) {
1224  for(int i = 0; i < 6; i++) {
1225  if(!_expr.set_function(i, _f[i]))
1226  Msg::Error("Field %i: invalid matheval expression \"%s\"", this->id,
1227  _f[i].c_str());
1228  }
1229  updateNeeded = false;
1230  }
1231  _expr.evaluate(x, y, z, metr);
1232  }
1233  }
1234  double operator()(double x, double y, double z, GEntity *ge = nullptr)
1235  {
1236  SMetric3 metr;
1237 #pragma omp critical
1238  {
1239  if(updateNeeded) {
1240  for(int i = 0; i < 6; i++) {
1241  if(!_expr.set_function(i, _f[i]))
1242  Msg::Error("Field %i: invalid matheval expression \"%s\"", this->id,
1243  _f[i].c_str());
1244  }
1245  updateNeeded = false;
1246  }
1247  _expr.evaluate(x, y, z, metr);
1248  }
1249  return metr(0, 0);
1250  }
1251  const char *getName() { return "MathEvalAniso"; }
1252  std::string getDescription()
1253  {
1254  return "Evaluate a metric expression. The expressions can contain "
1255  "x, y, z for spatial coordinates, F0, F1, ... for field values, and "
1256  "mathematical functions.";
1257  }
1258 };
1259 
1260 #if defined(WIN32) && !defined(__CYGWIN__)
1261 // windows implementation from
1262 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx
1263 class Popen2 {
1264 private:
1265  HANDLE _hIn, _hOut;
1266 
1267 public:
1268  Popen2()
1269  {
1270  _hIn = nullptr;
1271  _hOut = nullptr;
1272  }
1273  void stop()
1274  {
1275  if(_hIn) {
1276  CloseHandle(_hIn);
1277  CloseHandle(_hOut);
1278  _hIn = _hOut = nullptr;
1279  }
1280  }
1281  bool started() const { return _hIn; }
1282  bool start(const char *command)
1283  {
1284  stop();
1285  HANDLE hChildStd_OUT_Wr, hChildStd_IN_Rd;
1286  PROCESS_INFORMATION piProcInfo;
1287  SECURITY_ATTRIBUTES saAttr;
1288  saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
1289  saAttr.bInheritHandle = TRUE;
1290  saAttr.lpSecurityDescriptor = nullptr;
1291  if(!CreatePipe(&_hIn, &hChildStd_OUT_Wr, &saAttr, 0))
1292  Msg::Error("StdoutRd CreatePipe");
1293  if(!CreatePipe(&hChildStd_IN_Rd, &_hOut, &saAttr, 0))
1294  Msg::Error("Stdin CreatePipe");
1295  if(!CreatePipe(&_hIn, &hChildStd_OUT_Wr, &saAttr, 0))
1296  Msg::Error("StdoutRd CreatePipe");
1297  if(!SetHandleInformation(_hIn, HANDLE_FLAG_INHERIT, 0))
1298  Msg::Error("Stdout SetHandleInformation");
1299  STARTUPINFO siStartInfo;
1300  BOOL bSuccess = FALSE;
1301  ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
1302  ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
1303  siStartInfo.cb = sizeof(STARTUPINFO);
1304  siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
1305  siStartInfo.hStdOutput = hChildStd_OUT_Wr;
1306  siStartInfo.hStdInput = hChildStd_IN_Rd;
1307  siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
1308  bSuccess = CreateProcess(nullptr, (char *)command, nullptr, nullptr, TRUE,
1309  0, nullptr, nullptr, &siStartInfo, &piProcInfo);
1310  if(!bSuccess) {
1311  Msg::Error("Child process creation failed %i", GetLastError());
1312  _hIn = _hOut = nullptr;
1313  return false;
1314  }
1315  CloseHandle(piProcInfo.hProcess);
1316  CloseHandle(piProcInfo.hThread);
1317  return true;
1318  }
1319  bool read(void *data, size_t size)
1320  {
1321  if(!_hIn) return false;
1322  DWORD nSuccess = 0;
1323  ReadFile(_hIn, data, size, &nSuccess, nullptr);
1324  return nSuccess == size;
1325  }
1326  bool write(void *data, size_t size)
1327  {
1328  if(!_hOut) return false;
1329  DWORD nSuccess = 0;
1330  WriteFile(_hOut, data, size, &nSuccess, nullptr);
1331  return nSuccess == size;
1332  }
1333  ~Popen2() { stop(); }
1334 };
1335 
1336 #else // unix
1337 
1338 class Popen2 {
1339 private:
1341 
1342 public:
1343  Popen2() { _fdIn = _fdOut = -1; }
1344  void stop()
1345  {
1346  if(_fdIn != -1) {
1347  ::close(_fdIn);
1348  ::close(_fdOut);
1349  _fdIn = _fdOut = -1;
1350  }
1351  }
1352  bool started() const { return _fdIn; }
1353  bool start(const char *command)
1354  {
1355  stop();
1356  int p_stdin[2], p_stdout[2];
1357  if(pipe(p_stdin) != 0 || pipe(p_stdout) != 0) return false;
1358  int pid = fork();
1359  if(pid < 0)
1360  return false;
1361  else if(pid == 0) {
1362  close(p_stdin[1]);
1363  dup2(p_stdin[0], 0);
1364  close(p_stdout[0]);
1365  dup2(p_stdout[1], 1);
1366  execl("/bin/sh", "sh", "-c", command, nullptr);
1367  perror("execl");
1368  exit(0);
1369  }
1370  _fdOut = p_stdin[1];
1371  _fdIn = p_stdout[0];
1372  return true;
1373  }
1374  bool read(void *data, size_t size)
1375  {
1376  return ::read(_fdIn, data, size) == (ssize_t)size;
1377  }
1378  bool write(void *data, size_t size)
1379  {
1380  return ::write(_fdOut, data, size) == (ssize_t)size;
1381  }
1382  ~Popen2() { stop(); }
1383 };
1384 #endif
1385 
1386 class ExternalProcessField : public Field {
1387 private:
1388  std::string _cmdLine;
1390  void closePipes()
1391  {
1392  if(_pipes.started()) {
1393  double xyz[3] = {std::numeric_limits<double>::quiet_NaN(),
1394  std::numeric_limits<double>::quiet_NaN(),
1395  std::numeric_limits<double>::quiet_NaN()};
1396  _pipes.write((void *)xyz, 3 * sizeof(double));
1397  _pipes.stop();
1398  }
1399  }
1400 
1401 public:
1403  {
1404  _cmdLine = "";
1405 
1406  options["CommandLine"] =
1407  new FieldOptionString(_cmdLine, "Command line to launch", &updateNeeded);
1408  }
1410  using Field::operator();
1411  double operator()(double x, double y, double z, GEntity *ge = nullptr)
1412  {
1413  double xyz[3] = {x, y, z};
1414  double f;
1415  if(updateNeeded) {
1416  closePipes();
1417  _pipes.start(_cmdLine.c_str());
1418  updateNeeded = false;
1419  }
1420  if(!_pipes.write((void *)xyz, 3 * sizeof(double)) ||
1421  !_pipes.read((void *)&f, sizeof(double))) {
1422  f = 1e22; // std::numeric_limits<double>::max();
1423  }
1424  return f;
1425  }
1426  const char *getName() { return "ExternalProcess"; }
1427  std::string getDescription()
1428  {
1429  return "**This Field is experimental**\n"
1430  "Call an external process that received coordinates triple (x,y,z) "
1431  "as binary double precision numbers on stdin and is supposed to "
1432  "write the "
1433  "field value on stdout as a binary double precision number.\n"
1434  "NaN,NaN,NaN is sent as coordinate to indicate the end of the "
1435  "process.\n"
1436  "\n"
1437  "Example of client (python2):\n"
1438  "import os\n"
1439  "import struct\n"
1440  "import math\n"
1441  "import sys\n"
1442  "if sys.platform == \"win32\" :\n"
1443  " import msvcrt\n"
1444  " msvcrt.setmode(0, os.O_BINARY)\n"
1445  " msvcrt.setmode(1, os.O_BINARY)\n"
1446  "while(True):\n"
1447  " xyz = struct.unpack(\"ddd\", os.read(0,24))\n"
1448  " if math.isnan(xyz[0]):\n"
1449  " break\n"
1450  " f = 0.001 + xyz[1]*0.009\n"
1451  " os.write(1,struct.pack(\"d\",f))\n"
1452  "\n"
1453  "Example of client (python3):\n"
1454  "import struct\n"
1455  "import sys\n"
1456  "import math\n"
1457  "while(True):\n"
1458  " xyz = struct.unpack(\"ddd\", sys.stdin.buffer.read(24))\n"
1459  " if math.isnan(xyz[0]):\n"
1460  " break\n"
1461  " f = 0.001 + xyz[1]*0.009\n"
1462  " sys.stdout.buffer.write(struct.pack(\"d\",f))\n"
1463  " sys.stdout.flush()\n"
1464  "\n"
1465  "Example of client (c, unix):\n"
1466  "#include <unistd.h>\n"
1467  "int main(int argc, char **argv) {\n"
1468  " double xyz[3];\n"
1469  " while(read(STDIN_FILENO, &xyz, 3*sizeof(double)) == "
1470  "3*sizeof(double)) {\n"
1471  " if (xyz[0] != xyz[0]) break; //nan\n"
1472  " double f = 0.001 + 0.009 * xyz[1];\n"
1473  " write(STDOUT_FILENO, &f, sizeof(double));\n"
1474  " }\n"
1475  " return 0;\n"
1476  "}\n"
1477  "\n"
1478  "Example of client (c, windows):\n"
1479  "#include <stdio.h>\n"
1480  "#include <io.h>\n"
1481  "#include <fcntl.h>\n"
1482  "int main(int argc, char **argv) {\n"
1483  " double xyz[3];\n"
1484  " setmode(fileno(stdin),O_BINARY);\n"
1485  " setmode(fileno(stdout),O_BINARY);\n"
1486  " while(read(fileno(stdin), &xyz, 3*sizeof(double)) == "
1487  "3*sizeof(double)) {\n"
1488  " if (xyz[0] != xyz[0])\n"
1489  " break;\n"
1490  " double f = f = 0.01 + 0.09 * xyz[1];\n"
1491  " write(fileno(stdout), &f, sizeof(double));\n"
1492  " }\n"
1493  "}\n";
1494  }
1495 };
1496 
1497 class ParametricField : public Field {
1498 private:
1500  std::string _f[3];
1502 
1503 public:
1505  {
1506  _inField = 1;
1507 
1508  options["InField"] = new FieldOptionInt(_inField, "Input field tag");
1509  options["FX"] = new FieldOptionString(
1510  _f[0], "X component of parametric function", &updateNeeded);
1511  options["FY"] = new FieldOptionString(
1512  _f[1], "Y component of parametric function", &updateNeeded);
1513  options["FZ"] = new FieldOptionString(
1514  _f[2], "Z component of parametric function", &updateNeeded);
1515 
1516  // deprecated names
1517  options["IField"] =
1518  new FieldOptionInt(_inField, "[Deprecated]", nullptr, true);
1519  }
1520  std::string getDescription()
1521  {
1522  return "Evaluate Field[InField] in parametric coordinates:\n\n"
1523  " F = Field[InField](FX,FY,FZ)\n\n"
1524  "See the MathEval Field help to get a description of valid FX, FY "
1525  "and FZ expressions.";
1526  }
1527  using Field::operator();
1528  double operator()(double x, double y, double z, GEntity *ge = nullptr)
1529  {
1530  if(updateNeeded) {
1531  for(int i = 0; i < 3; i++) {
1532  if(!_expr[i].set_function(_f[i]))
1533  Msg::Error("Field %i: invalid matheval expression \"%s\"", this->id,
1534  _f[i].c_str());
1535  }
1536  updateNeeded = false;
1537  }
1538  if(_inField == id) return MAX_LC;
1539  Field *field = GModel::current()->getFields()->get(_inField);
1540  if(!field) {
1541  Msg::Warning("Unknown Field %i", _inField);
1542  return MAX_LC;
1543  }
1544  return (*field)(_expr[0].evaluate(x, y, z), _expr[1].evaluate(x, y, z),
1545  _expr[2].evaluate(x, y, z));
1546  }
1547  const char *getName() { return "Param"; }
1548 };
1549 
1550 #if defined(HAVE_POST)
1551 
1552 class PostViewField : public Field {
1553 private:
1554  int _viewIndex, _viewTag;
1555  bool _cropNegativeValues, _useClosest;
1556 
1557 public:
1558  PostViewField()
1559  {
1560  _viewIndex = 0;
1561  _viewTag = -1;
1562  _cropNegativeValues = true;
1563  _useClosest = true;
1564 
1565  options["ViewIndex"] =
1566  new FieldOptionInt(_viewIndex, "Post-processing view index");
1567  options["ViewTag"] =
1568  new FieldOptionInt(_viewTag, "Post-processing view tag");
1569  options["CropNegativeValues"] = new FieldOptionBool(
1570  _cropNegativeValues, "return MAX_LC instead of a negative value (this "
1571  "option is needed for backward compatibility with "
1572  "the BackgroundMesh option");
1573  options["UseClosest"] =
1574  new FieldOptionBool(_useClosest, "Use value at closest node if "
1575  "no exact match is found");
1576 
1577  // deprecated names
1578  options["IView"] =
1579  new FieldOptionInt(_viewIndex, "[Deprecated]", nullptr, true);
1580  }
1581  ~PostViewField()
1582  {
1583  }
1584  PView *getView() const
1585  {
1586  PView *v = nullptr;
1587  if(_viewTag >= 0) {
1588  v = PView::getViewByTag(_viewTag);
1589  if(!v) {
1590  Msg::Error("View with tag %d does not exist", _viewTag);
1591  }
1592  }
1593  if(!v) {
1594  if(_viewIndex < 0 || _viewIndex >= (int)PView::list.size()) {
1595  Msg::Error("View with index %d does not exist", _viewIndex);
1596  return nullptr;
1597  }
1598  v = PView::list[_viewIndex];
1599  }
1600  if(v->getData()->hasModel(GModel::current())) {
1601  Msg::Error(
1602  "Cannot use view based on current mesh for background mesh: you might"
1603  " want to use a list-based view (.pos file) instead");
1604  return nullptr;
1605  }
1606  return v;
1607  }
1608  virtual bool isotropic() const
1609  {
1610  PView *v = getView();
1611  if(v && v->getData()->getNumTensors()) return false;
1612  return true;
1613  }
1614  virtual int numComponents() const
1615  {
1616  PView *v = getView();
1617  if(v && v->getData()->getNumTensors()) return 9;
1618  if(v && v->getData()->getNumVectors()) return 3;
1619  return 1;
1620  }
1621  double operator()(double x, double y, double z, GEntity *ge = nullptr)
1622  {
1623  double l = MAX_LC;
1624  PView *v = getView();
1625  if(!v) return l;
1626  double dist = _useClosest ? -1. : 0.;
1627  if(numComponents() == 3) {
1628  double values[3];
1629  if(!v->getData()->searchVectorClosest(x, y, z, dist, values, 0)) {
1630  Msg::Warning("No vector element found containing point "
1631  "(%g,%g,%g) in PostView field (for norm)", x, y, z);
1632  }
1633  else {
1634  l = sqrt(values[0] * values[0] + values[1] * values[1] +
1635  values[2] * values[2]);
1636  }
1637  }
1638  else if(numComponents() == 1) {
1639  if(!v->getData()->searchScalarClosest(x, y, z, dist, &l, 0)) {
1640  Msg::Warning("No scalar element found containing point "
1641  "(%g,%g,%g) in PostView field", x, y, z);
1642  }
1643  }
1644  else {
1645  Msg::Warning("No vector or scalar value found in PostView field");
1646  }
1647 
1648  if(l <= 0 && _cropNegativeValues) return MAX_LC;
1649  return l;
1650  }
1651  void operator()(double x, double y, double z, SVector3 &v, GEntity *ge = 0)
1652  {
1653  PView *vie = getView();
1654  if(!vie) {
1655  v.data()[0] = MAX_LC;
1656  v.data()[1] = MAX_LC;
1657  v.data()[2] = MAX_LC;
1658  return;
1659  }
1660  double dist = _useClosest ? -1. : 0.;
1661  if(numComponents() == 3) {
1662  double values[3];
1663  if(!vie->getData()->searchVectorClosest(x, y, z, dist, values, 0)) {
1664  Msg::Warning("No vector element found containing point "
1665  "(%g,%g,%g) in PostView field", x, y, z);
1666  }
1667  else {
1668  v = SVector3(values[0], values[1], values[2]);
1669  }
1670  }
1671  else {
1672  Msg::Warning("No vector value found in PostView field");
1673  }
1674  }
1675  void operator()(double x, double y, double z, SMetric3 &metr,
1676  GEntity *ge = nullptr)
1677  {
1678  PView *v = getView();
1679  if(!v) return;
1680  double dist = _useClosest ? -1. : 0.;
1681  double l[9] = {0., 0., 0., 0., 0., 0., 0., 0., 0.};
1682  if(!v->getData()->searchTensorClosest(x, y, z, dist, l)) {
1683  Msg::Warning("No tensor element found containing point "
1684  "(%g,%g,%g) in PostView field", x, y, z);
1685  }
1686  else {
1687  metr(0, 0) = l[0];
1688  metr(0, 1) = l[1];
1689  metr(0, 2) = l[2];
1690  metr(1, 0) = l[3];
1691  metr(1, 1) = l[4];
1692  metr(1, 2) = l[5];
1693  metr(2, 0) = l[6];
1694  metr(2, 1) = l[7];
1695  metr(2, 2) = l[8];
1696  }
1697  }
1698  const char *getName() { return "PostView"; }
1699  std::string getDescription()
1700  {
1701  return "Evaluate the post processing view with index ViewIndex, or "
1702  "with tag ViewTag if ViewTag is positive.";
1703  }
1704 };
1705 
1706 #endif
1707 
1708 class MinAnisoField : public Field {
1709 private:
1710  std::list<int> _fieldIds;
1711 
1712 public:
1714  {
1715  options["FieldsList"] =
1716  new FieldOptionList(_fieldIds, "Field indices", &updateNeeded);
1717  }
1718  virtual bool isotropic() const { return false; }
1719  std::string getDescription()
1720  {
1721  return "Take the intersection of a list of possibly anisotropic fields.";
1722  }
1723  virtual void operator()(double x, double y, double z, SMetric3 &metr,
1724  GEntity *ge = nullptr)
1725  {
1726  SMetric3 v(1. / MAX_LC);
1727  for(auto it = _fieldIds.begin(); it != _fieldIds.end(); it++) {
1728  Field *f = (GModel::current()->getFields()->get(*it));
1729  if(!f) Msg::Warning("Unknown Field %i", *it);
1730  SMetric3 ff;
1731  if(f && *it != id) {
1732  if(f->isotropic()) {
1733  double l = (*f)(x, y, z, ge);
1734  ff = SMetric3(1. / (l * l));
1735  }
1736  else {
1737  (*f)(x, y, z, ff, ge);
1738  }
1740  }
1741  }
1742  metr = v;
1743  }
1744  double operator()(double x, double y, double z, GEntity *ge = nullptr)
1745  {
1746  SMetric3 metr(1. / MAX_LC);
1747  double v = MAX_LC;
1748  for(auto it = _fieldIds.begin(); it != _fieldIds.end(); it++) {
1749  Field *f = (GModel::current()->getFields()->get(*it));
1750  if(!f) Msg::Warning("Unknown Field %i", *it);
1751  SMetric3 m;
1752  if(f && *it != id) {
1753  if(!f->isotropic()) { (*f)(x, y, z, m, ge); }
1754  else {
1755  double L = (*f)(x, y, z, ge);
1756  for(int i = 0; i < 3; i++) m(i, i) = 1. / (L * L);
1757  }
1758  }
1759  metr = intersection(metr, m);
1760  }
1761  fullMatrix<double> V(3, 3);
1762  fullVector<double> S(3);
1763  metr.eig(V, S, 1);
1764  double val = sqrt(1. / S(2)); // S(2) is largest eigenvalue
1765  return std::min(v, val);
1766  }
1767  const char *getName() { return "MinAniso"; }
1768 };
1769 
1770 class IntersectAnisoField : public Field {
1771 private:
1772  std::list<int> _fieldIds;
1773 
1774 public:
1776  {
1777  options["FieldsList"] =
1778  new FieldOptionList(_fieldIds, "Field indices", &updateNeeded);
1779  }
1780  virtual bool isotropic() const { return false; }
1781  std::string getDescription()
1782  {
1783  return "Take the intersection of 2 anisotropic fields according to "
1784  "Alauzet.";
1785  }
1786  virtual void operator()(double x, double y, double z, SMetric3 &metr,
1787  GEntity *ge = nullptr)
1788  {
1789  // check if _fieldIds contains 2 elements other error message
1790  SMetric3 v;
1791  for(auto it = _fieldIds.begin(); it != _fieldIds.end(); it++) {
1792  Field *f = (GModel::current()->getFields()->get(*it));
1793  if(!f) Msg::Warning("Unknown Field %i", *it);
1794  SMetric3 ff;
1795  if(f && *it != id) {
1796  if(f->isotropic()) {
1797  double l = (*f)(x, y, z, ge);
1798  ff = SMetric3(1. / (l * l));
1799  }
1800  else {
1801  (*f)(x, y, z, ff, ge);
1802  }
1803  if(it == _fieldIds.begin())
1804  v = ff;
1805  else
1806  v = intersection_alauzet(v, ff);
1807  }
1808  }
1809  metr = v;
1810  }
1811  double operator()(double x, double y, double z, GEntity *ge = nullptr)
1812  {
1813  // check if _fieldIds contains 2 elements other error message
1814  SMetric3 metr;
1815  for(auto it = _fieldIds.begin(); it != _fieldIds.end(); it++) {
1816  Field *f = (GModel::current()->getFields()->get(*it));
1817  if(!f) Msg::Warning("Unknown Field %i", *it);
1818  SMetric3 m;
1819  if(f && *it != id) {
1820  if(!f->isotropic()) { (*f)(x, y, z, m, ge); }
1821  else {
1822  double L = (*f)(x, y, z, ge);
1823  for(int i = 0; i < 3; i++) m(i, i) = 1. / (L * L);
1824  }
1825  }
1826  if(it == _fieldIds.begin())
1827  metr = m;
1828  else
1829  metr = intersection_alauzet(metr, m);
1830  }
1831  fullMatrix<double> V(3, 3);
1832  fullVector<double> S(3);
1833  metr.eig(V, S, 1);
1834  return sqrt(1. / S(2)); // S(2) is largest eigenvalue
1835  }
1836  const char *getName() { return "IntersectAniso"; }
1837 };
1838 
1839 class MinField : public Field {
1840 private:
1841  std::list<int> _fieldIds;
1842  std::vector<Field*> _fields;
1843 
1844 public:
1846  {
1847  options["FieldsList"] =
1848  new FieldOptionList(_fieldIds, "Field indices", &updateNeeded);
1849  }
1850  std::string getDescription()
1851  {
1852  return "Take the minimum value of a list of fields.";
1853  }
1854  using Field::operator();
1855  double operator()(double x, double y, double z, GEntity *ge = nullptr)
1856  {
1857 #pragma omp critical
1858  {
1859  if(updateNeeded) {
1860  _fields.clear();
1861  for(auto it = _fieldIds.begin(); it != _fieldIds.end(); it++) {
1862  Field *f = (GModel::current()->getFields()->get(*it));
1863  if(!f) Msg::Warning("Unknown Field %i", *it);
1864  if(f && *it != id) _fields.push_back(f);
1865  }
1866  updateNeeded = false;
1867  }
1868  }
1869 
1870  double v = MAX_LC;
1871  for(auto f : _fields) {
1872  if(f->isotropic())
1873  v = std::min(v, (*f)(x, y, z, ge));
1874  else {
1875  SMetric3 ff;
1876  (*f)(x, y, z, ff, ge);
1877  fullMatrix<double> V(3, 3);
1878  fullVector<double> S(3);
1879  ff.eig(V, S, 1);
1880  v = std::min(v, sqrt(1. / S(2))); // S(2) is largest eigenvalue
1881  }
1882  }
1883  return v;
1884  }
1885  const char *getName() { return "Min"; }
1886 };
1887 
1888 class MaxField : public Field {
1889 private:
1890  std::list<int> _fieldIds;
1891  std::vector<Field*> _fields;
1892 
1893 public:
1895  {
1896  options["FieldsList"] =
1897  new FieldOptionList(_fieldIds, "Field indices", &updateNeeded);
1898  }
1899  std::string getDescription()
1900  {
1901  return "Take the maximum value of a list of fields.";
1902  }
1903  using Field::operator();
1904  double operator()(double x, double y, double z, GEntity *ge = nullptr)
1905  {
1906 #pragma omp critical
1907  {
1908  if(updateNeeded) {
1909  _fields.clear();
1910  for(auto it = _fieldIds.begin(); it != _fieldIds.end(); it++) {
1911  Field *f = (GModel::current()->getFields()->get(*it));
1912  if(!f) Msg::Warning("Unknown Field %i", *it);
1913  if(f && *it != id) _fields.push_back(f);
1914  }
1915  updateNeeded = false;
1916  }
1917  }
1918 
1919  double v = -MAX_LC;
1920  for(auto f : _fields) {
1921  if(f->isotropic())
1922  v = std::max(v, (*f)(x, y, z, ge));
1923  else {
1924  SMetric3 ff;
1925  (*f)(x, y, z, ff, ge);
1926  fullMatrix<double> V(3, 3);
1927  fullVector<double> S(3);
1928  ff.eig(V, S, 1);
1929  v = std::max(v, sqrt(1. / S(0))); // S(0) is smallest eigenvalue
1930  }
1931  }
1932  return v;
1933  }
1934  const char *getName() { return "Max"; }
1935 };
1936 
1937 class RestrictField : public Field {
1938 private:
1942 
1943 public:
1945  {
1946  _inField = 1;
1947  _boundary = true;
1948 
1949  options["InField"] = new FieldOptionInt(_inField, "Input field tag");
1950  options["PointsList"] = new FieldOptionList(_pointTags, "Point tags");
1951  options["CurvesList"] = new FieldOptionList(_curveTags, "Curve tags");
1952  options["SurfacesList"] = new FieldOptionList(_surfaceTags, "Surface tags");
1953  options["VolumesList"] = new FieldOptionList(_volumeTags, "Volume tags");
1954  options["IncludeBoundary"] =
1955  new FieldOptionBool(_boundary, "Include the boundary of the entities");
1956 
1957  // deprecated names
1958  options["IField"] =
1959  new FieldOptionInt(_inField, "[Deprecated]", nullptr, true);
1960  options["VerticesList"] =
1961  new FieldOptionList(_pointTags, "[Deprecated]", nullptr, true);
1962  options["EdgesList"] =
1963  new FieldOptionList(_curveTags, "[Deprecated]", nullptr, true);
1964  options["FacesList"] =
1965  new FieldOptionList(_surfaceTags, "[Deprecated]", nullptr, true);
1966  options["RegionsList"] =
1967  new FieldOptionList(_volumeTags, "[Deprecated]", nullptr, true);
1968  }
1969  std::string getDescription()
1970  {
1971  return "Restrict the application of a field to a given list of geometrical "
1972  "points, curves, surfaces or volumes (as well as their boundaries "
1973  "if IncludeBoundary is set).";
1974  }
1975  using Field::operator();
1976  double operator()(double x, double y, double z, GEntity *ge = nullptr)
1977  {
1978  if(_inField == id) return MAX_LC;
1980  if(!f) {
1981  Msg::Warning("Unknown Field %i", _inField);
1982  return MAX_LC;
1983  }
1984  if(!ge) return (*f)(x, y, z);
1985  if((ge->dim() == 0 && std::find(_pointTags.begin(), _pointTags.end(),
1986  ge->tag()) != _pointTags.end()) ||
1987  (ge->dim() == 1 && std::find(_curveTags.begin(), _curveTags.end(),
1988  ge->tag()) != _curveTags.end()) ||
1989  (ge->dim() == 2 && std::find(_surfaceTags.begin(), _surfaceTags.end(),
1990  ge->tag()) != _surfaceTags.end()) ||
1991  (ge->dim() == 3 && std::find(_volumeTags.begin(), _volumeTags.end(),
1992  ge->tag()) != _volumeTags.end()))
1993  return (*f)(x, y, z);
1994  if(_boundary) {
1995  if(ge->dim() <= 2) {
1996  std::list<GRegion *> volumes = ge->regions();
1997  for(auto v : volumes) {
1998  if(std::find(_volumeTags.begin(), _volumeTags.end(), v->tag()) !=
1999  _volumeTags.end()) return (*f)(x, y, z);
2000  }
2001  }
2002  if(ge->dim() <= 1) {
2003  std::vector<GFace *> surfaces = ge->faces();
2004  for(auto s : surfaces) {
2005  if(std::find(_surfaceTags.begin(), _surfaceTags.end(), s->tag()) !=
2006  _surfaceTags.end()) return (*f)(x, y, z);
2007  }
2008  }
2009  if(ge->dim() == 0) {
2010  std::vector<GEdge *> curves = ge->edges();
2011  for(auto c : curves) {
2012  if(std::find(_curveTags.begin(), _curveTags.end(), c->tag()) !=
2013  _curveTags.end()) return (*f)(x, y, z);
2014  }
2015  }
2016  }
2017  return MAX_LC;
2018  }
2019  const char *getName() { return "Restrict"; }
2020 };
2021 
2022 class ConstantField : public Field {
2023 private:
2024  double _vIn, _vOut;
2027 
2028 public:
2030  {
2031  _vIn = _vOut = MAX_LC;
2032  _boundary = true;
2033 
2034  options["VIn"] = new FieldOptionDouble(_vIn, "Value inside the entities");
2035  options["VOut"] = new FieldOptionDouble(_vOut, "Value outside the entities");
2036  options["PointsList"] = new FieldOptionList(_pointTags, "Point tags");
2037  options["CurvesList"] = new FieldOptionList(_curveTags, "Curve tags");
2038  options["SurfacesList"] = new FieldOptionList(_surfaceTags, "Surface tags");
2039  options["VolumesList"] = new FieldOptionList(_volumeTags, "Volume tags");
2040  options["IncludeBoundary"] =
2041  new FieldOptionBool(_boundary, "Include the boundary of the entities");
2042  }
2043  std::string getDescription()
2044  {
2045  return "Return VIn when inside the entities (and on their boundary if "
2046  "IncludeBoundary is set), and VOut outside.";
2047  }
2048  using Field::operator();
2049  double operator()(double x, double y, double z, GEntity *ge = nullptr)
2050  {
2051  if(!ge) return MAX_LC;
2052  if((ge->dim() == 0 && std::find(_pointTags.begin(), _pointTags.end(),
2053  ge->tag()) != _pointTags.end()) ||
2054  (ge->dim() == 1 && std::find(_curveTags.begin(), _curveTags.end(),
2055  ge->tag()) != _curveTags.end()) ||
2056  (ge->dim() == 2 && std::find(_surfaceTags.begin(), _surfaceTags.end(),
2057  ge->tag()) != _surfaceTags.end()) ||
2058  (ge->dim() == 3 && std::find(_volumeTags.begin(), _volumeTags.end(),
2059  ge->tag()) != _volumeTags.end()))
2060  return _vIn;
2061  if(_boundary) {
2062  if(ge->dim() <= 2) {
2063  std::list<GRegion *> volumes = ge->regions();
2064  for(auto v : volumes) {
2065  if(std::find(_volumeTags.begin(), _volumeTags.end(), v->tag()) !=
2066  _volumeTags.end()) return _vIn;
2067  }
2068  }
2069  if(ge->dim() <= 1) {
2070  std::vector<GFace *> surfaces = ge->faces();
2071  for(auto s : surfaces) {
2072  if(std::find(_surfaceTags.begin(), _surfaceTags.end(), s->tag()) !=
2073  _surfaceTags.end()) return _vIn;
2074  }
2075  }
2076  if(ge->dim() == 0) {
2077  std::vector<GEdge *> curves = ge->edges();
2078  for(auto c : curves) {
2079  if(std::find(_curveTags.begin(), _curveTags.end(), c->tag()) !=
2080  _curveTags.end()) return _vIn;
2081  }
2082  }
2083  }
2084  return _vOut;
2085  }
2086  const char *getName() { return "Constant"; }
2087 };
2088 
2090  AttractorInfo(int a = 0, int b = 0, double c = 0, double d = 0)
2091  : ent(a), dim(b), u(c), v(d)
2092  {
2093  }
2094  int ent, dim;
2095  double u, v;
2096 };
2097 
2098 #if defined(HAVE_ANN)
2099 
2100 class AttractorAnisoCurveField : public Field {
2101 private:
2102  ANNkd_tree *_kdTree;
2103  ANNpointArray _zeroNodes;
2104  ANNidxArray _index;
2105  ANNdistArray _dist;
2106  std::list<int> _curveTags;
2107  double _dMin, _dMax, _lMinTangent, _lMaxTangent, _lMinNormal, _lMaxNormal;
2108  int _sampling;
2109  std::vector<SVector3> _tg;
2110 
2111 public:
2112  AttractorAnisoCurveField() : _kdTree(nullptr), _zeroNodes(nullptr)
2113  {
2114  _index = new ANNidx[1];
2115  _dist = new ANNdist[1];
2116  _sampling = 20;
2117  updateNeeded = true;
2118  _dMin = 0.1;
2119  _dMax = 0.5;
2120  _lMinNormal = 0.05;
2121  _lMinTangent = 0.5;
2122  _lMaxNormal = 0.5;
2123  _lMaxTangent = 0.5;
2124 
2125  options["CurvesList"] = new FieldOptionList(
2126  _curveTags, "Tags of curves in the geometric model", &updateNeeded);
2127  options["Sampling"] = new FieldOptionInt(
2128  _sampling, "Number of sampling points on each curve",
2129  &updateNeeded);
2130  options["DistMin"] = new FieldOptionDouble(
2131  _dMin, "Minimum distance, below this distance from the curves, "
2132  "prescribe the minimum mesh sizes");
2133  options["DistMax"] = new FieldOptionDouble(
2134  _dMax, "Maxmium distance, above this distance from the curves, prescribe "
2135  "the maximum mesh sizes");
2136  options["SizeMinTangent"] = new FieldOptionDouble(
2137  _lMinTangent, "Minimum mesh size in the direction tangeant to the "
2138  "closest curve");
2139  options["SizeMaxTangent"] = new FieldOptionDouble(
2140  _lMaxTangent, "Maximum mesh size in the direction tangeant to the "
2141  "closest curve");
2142  options["SizeMinNormal"] = new FieldOptionDouble(
2143  _lMinNormal, "Minimum mesh size in the direction normal to the "
2144  "closest curve");
2145  options["SizeMaxNormal"] = new FieldOptionDouble(
2146  _lMaxNormal, "Maximum mesh size in the direction normal to the "
2147  "closest curve");
2148 
2149  // deprecated names
2150  options["EdgesList"] =
2151  new FieldOptionList(_curveTags, "[Deprecated]", &updateNeeded, true);
2152  options["NNodesByEdge"] =
2153  new FieldOptionInt(_sampling, "[Deprecated]", &updateNeeded, true);
2154  options["dMin"] =
2155  new FieldOptionDouble(_dMin, "[Deprecated]", nullptr, true);
2156  options["dMax"] =
2157  new FieldOptionDouble(_dMax, "[Deprecated]", nullptr, true);
2158  options["lMinTangent"] =
2159  new FieldOptionDouble(_lMinTangent, "[Deprecated]", nullptr, true);
2160  options["lMaxTangent"] =
2161  new FieldOptionDouble(_lMaxTangent, "[Deprecated]", nullptr, true);
2162  options["lMinNormal"] =
2163  new FieldOptionDouble(_lMinNormal, "[Deprecated]", nullptr, true);
2164  options["lMaxNormal"] =
2165  new FieldOptionDouble(_lMaxNormal, "[Deprecated]", nullptr, true);
2166  options["NumPointsPerCurve"] =
2167  new FieldOptionInt(_sampling, "[Deprecated]", &updateNeeded, true);
2168 
2169  // make sure all internal GEO CAD data has been synced with GModel
2171  }
2172  virtual bool isotropic() const { return false; }
2173  ~AttractorAnisoCurveField()
2174  {
2175  if(_kdTree) delete _kdTree;
2176  if(_zeroNodes) annDeallocPts(_zeroNodes);
2177  delete[] _index;
2178  delete[] _dist;
2179  }
2180  const char *getName() { return "AttractorAnisoCurve"; }
2181  std::string getDescription()
2182  {
2183  return "Compute the distance to the given curves and specify the mesh size "
2184  "independently in the direction normal and parallel to the nearest "
2185  "curve. For efficiency each curve is replaced by a set of Sampling "
2186  "points, to which the distance is actually computed.";
2187  }
2188  void update()
2189  {
2190  if(_zeroNodes) {
2191  annDeallocPts(_zeroNodes);
2192  delete _kdTree;
2193  }
2194  int totpoints = _sampling * _curveTags.size();
2195  if(totpoints) { _zeroNodes = annAllocPts(totpoints, 3); }
2196  _tg.resize(totpoints);
2197  int k = 0;
2198  for(auto it = _curveTags.begin(); it != _curveTags.end(); ++it) {
2199  GEdge *e = GModel::current()->getEdgeByTag(*it);
2200  if(e) {
2201  for(int i = 0; i < _sampling; i++) {
2202  double u = (double)i / (_sampling - 1);
2203  Range<double> b = e->parBounds(0);
2204  double t = b.low() + u * (b.high() - b.low());
2205  GPoint gp = e->point(t);
2206  SVector3 d = e->firstDer(t);
2207  _zeroNodes[k][0] = gp.x();
2208  _zeroNodes[k][1] = gp.y();
2209  _zeroNodes[k][2] = gp.z();
2210  _tg[k] = d;
2211  _tg[k].normalize();
2212  k++;
2213  }
2214  }
2215  else {
2216  Msg::Warning("Unknown curve %d", *it);
2217  }
2218  }
2219  _kdTree = new ANNkd_tree(_zeroNodes, totpoints, 3);
2220  updateNeeded = false;
2221  }
2222  void operator()(double x, double y, double z, SMetric3 &metr,
2223  GEntity *ge = nullptr)
2224  {
2225  if(updateNeeded) update();
2226  double xyz[3] = {x, y, z};
2227 #pragma omp critical // avoid crash (still incorrect) - use Distance instead
2228  _kdTree->annkSearch(xyz, 1, _index, _dist);
2229  double d = sqrt(_dist[0]);
2230  double lTg = d < _dMin ? _lMinTangent :
2231  d > _dMax ? _lMaxTangent :
2232  _lMinTangent + (_lMaxTangent - _lMinTangent) *
2233  (d - _dMin) / (_dMax - _dMin);
2234  double lN = d < _dMin ? _lMinNormal :
2235  d > _dMax ? _lMaxNormal :
2236  _lMinNormal + (_lMaxNormal - _lMinNormal) *
2237  (d - _dMin) / (_dMax - _dMin);
2238  SVector3 t = _tg[_index[0]];
2239  SVector3 n0 = crossprod(t, fabs(t(0)) > fabs(t(1)) ? SVector3(0, 1, 0) :
2240  SVector3(1, 0, 0));
2241  SVector3 n1 = crossprod(t, n0);
2242  metr = SMetric3(1 / lTg / lTg, 1 / lN / lN, 1 / lN / lN, t, n0, n1);
2243  }
2244  virtual double operator()(double X, double Y, double Z, GEntity *ge = nullptr)
2245  {
2246  if(updateNeeded) update();
2247  double xyz[3] = {X, Y, Z};
2248 #pragma omp critical // avoid crash (still incorrect) - use Distance instead
2249  _kdTree->annkSearch(xyz, 1, _index, _dist);
2250  double d = sqrt(_dist[0]);
2251  return std::max(d, 0.05);
2252  }
2253 };
2254 
2255 #endif // ANN
2256 
2257 class OctreeField : public Field {
2258 private:
2259  // octree field
2260  class Cell {
2261  private:
2262  void *_data;
2263  bool _isleaf;
2264 
2265  public:
2266  double evaluate(double x, double y, double z) const
2267  {
2268  if(_isleaf) return *(double *)_data;
2269  Cell *sub = (Cell *)_data;
2270  int i = x > 0.5 ? 1 : 0;
2271  int j = y > 0.5 ? 1 : 0;
2272  int k = z > 0.5 ? 1 : 0;
2273  return sub[i * 4 + j * 2 + k].evaluate(2 * x - i, 2 * y - j, 2 * z - k);
2274  }
2275  Cell(){};
2276  void init(double x0, double y0, double z0, double l, Field &field,
2277  int level)
2278  {
2279 #if 0
2280  double v[8] =
2281  {field(x0, y0, z0), field(x0, y0, z0 + l), field(x0, y0 + l, z0),
2282  field(x0, y0 + l, z0 + l), field(x0 + l, y0, z0), field(x0 + l, y0, z0 + l),
2283  field(x0 + l, y0 + l, z0), field(x0 + l, y0 + l, z0 + l)};
2284  double dmax = 0;
2285  double vmin = v[0];
2286  double vc = field(x0+l/2,y0+l/2,z0+l/2);
2287  for (int i = 0; i < 8; ++i){
2288  dmax = std::max(dmax, std::abs(vc-v[i]));
2289  vmin = std::min(vmin, v[i]);
2290  }
2291 #else
2292  double dmax = 0;
2293  double vc = field(x0 + l / 2, y0 + l / 2, z0 + l / 2);
2294  double vmin = vc;
2295  bool split = level > 0;
2296  if(level > -4) {
2297 #define NSAMPLE 2
2298  double dl = l / NSAMPLE;
2299  for(int i = 0; i <= NSAMPLE; ++i) {
2300  for(int j = 0; j <= NSAMPLE; ++j) {
2301  for(int k = 0; k <= NSAMPLE; ++k) {
2302  double w = field(x0 + i * dl, y0 + j * dl, z0 + k * dl);
2303  dmax = std::max(dmax, std::abs(vc - w));
2304  vmin = std::min(vmin, w);
2305  split |= (dmax / vmin > 0.2 && vmin < l);
2306  if(split) break;
2307  }
2308  }
2309  }
2310 #endif
2311  }
2312  if(split) {
2313  _isleaf = false;
2314  Cell *sub = new Cell[8];
2315  double l2 = l / 2;
2316  sub[0].init(x0, y0, z0, l2, field, level - 1);
2317  sub[1].init(x0, y0, z0 + l2, l2, field, level - 1);
2318  sub[2].init(x0, y0 + l2, z0, l2, field, level - 1);
2319  sub[3].init(x0, y0 + l2, z0 + l2, l2, field, level - 1);
2320  sub[4].init(x0 + l2, y0, z0, l2, field, level - 1);
2321  sub[5].init(x0 + l2, y0, z0 + l2, l2, field, level - 1);
2322  sub[6].init(x0 + l2, y0 + l2, z0, l2, field, level - 1);
2323  sub[7].init(x0 + l2, y0 + l2, z0 + l2, l2, field, level - 1);
2324  _data = (void *)sub;
2325  }
2326  else {
2327  _isleaf = true;
2328  _data = (void *)new double;
2329  *(double *)_data = vc;
2330  }
2331  }
2333  {
2334  if(_isleaf) { delete(double *)_data; }
2335  else {
2336  Cell *sub = (Cell *)_data;
2337  delete[] sub;
2338  }
2339  }
2340  void print(double x0, double y0, double z0, double l, FILE *f)
2341  {
2342  if(_isleaf) {
2343  fprintf(f, "SP(%g, %g, %g) {%g};\n", x0 + l / 2, y0 + l / 2, z0 + l / 2,
2344  *(double *)_data);
2345  }
2346  else {
2347  Cell *sub = (Cell *)_data;
2348  double l2 = l / 2;
2349  sub[0].print(x0, y0, z0, l2, f);
2350  sub[1].print(x0, y0, z0 + l2, l2, f);
2351  sub[2].print(x0, y0 + l2, z0, l2, f);
2352  sub[3].print(x0, y0 + l2, z0 + l2, l2, f);
2353  sub[4].print(x0 + l2, y0, z0, l2, f);
2354  sub[5].print(x0 + l2, y0, z0 + l2, l2, f);
2355  sub[6].print(x0 + l2, y0 + l2, z0, l2, f);
2356  sub[7].print(x0 + l2, y0 + l2, z0 + l2, l2, f);
2357  }
2358  }
2359  };
2364  double _l0;
2365 
2366  public:
2368  {
2369  _root = nullptr;
2370  _inFieldId = 1;
2371 
2372  options["InField"] = new FieldOptionInt
2373  (_inFieldId, "Id of the field to represent on the octree", &updateNeeded);
2374  }
2376  {
2377  if(_root) delete _root;
2378  }
2379  const char *getName() { return "Octree"; }
2380  std::string getDescription()
2381  {
2382  return "Pre compute another field on an octree to speed-up evalution.";
2383  }
2384  void update()
2385  {
2386  if(updateNeeded) {
2387  updateNeeded = false;
2388  if(_root) {
2389  delete _root;
2390  _root = nullptr;
2391  }
2392  }
2393  if(!_root) {
2394  _inField = _inFieldId >= 0 ?
2396  nullptr;
2397  if(!_inField) return;
2399  bounds = GModel::current()->bounds();
2400  _root = new Cell;
2401  SVector3 d = bounds.max() - bounds.min();
2402  _l0 = std::max(std::max(d.x(), d.y()), d.z());
2403  _root->init(bounds.min().x(), bounds.min().y(), bounds.min().z(), _l0,
2404  *_inField, 4);
2405  }
2406  }
2407  virtual double operator()(double X, double Y, double Z, GEntity *ge = nullptr)
2408  {
2409  SPoint3 xmin = bounds.min();
2410  SVector3 d = bounds.max() - xmin;
2411  return _root->evaluate((X - xmin.x()) / _l0, (Y - xmin.y()) / _l0,
2412  (Z - xmin.z()) / _l0);
2413  }
2414 };
2415 
2416 struct PointCloud {
2417  std::vector<SPoint3> pts;
2418 };
2419 
2420 template <typename Derived> struct PointCloudAdaptor {
2421  const Derived &obj;
2422  PointCloudAdaptor(const Derived &obj_) : obj(obj_) {}
2423  inline const Derived &derived() const { return obj; }
2424  inline size_t kdtree_get_point_count() const { return derived().pts.size(); }
2425  inline double kdtree_distance(const double *p1, const size_t idx_p2,
2426  size_t /*size*/) const
2427  {
2428  const double d0 = p1[0] - derived().pts[idx_p2].x();
2429  const double d1 = p1[1] - derived().pts[idx_p2].y();
2430  const double d2 = p1[2] - derived().pts[idx_p2].z();
2431  return d0 * d0 + d1 * d1 + d2 * d2;
2432  }
2433  inline double kdtree_get_pt(const size_t idx, int dim) const
2434  {
2435  if(dim == 0)
2436  return derived().pts[idx].x();
2437  else if(dim == 1)
2438  return derived().pts[idx].y();
2439  else
2440  return derived().pts[idx].z();
2441  }
2442  template <class BBOX> bool kdtree_get_bbox(BBOX & /*bb*/) const
2443  {
2444  return false;
2445  }
2446 };
2447 
2448 class DistanceField : public Field {
2450  std::vector<AttractorInfo> _infos;
2452  int _xFieldId, _yFieldId, _zFieldId; // unused
2456  std::size_t _outIndex;
2457 
2458 public:
2460  {
2461  _sampling = 20;
2462 
2463  options["PointsList"] = new FieldOptionList(
2464  _pointTags, "Tags of points in the geometric model", &updateNeeded);
2465  options["CurvesList"] = new FieldOptionList(
2466  _curveTags, "Tags of curves in the geometric model", &updateNeeded);
2467  options["SurfacesList"] = new FieldOptionList(
2468  _surfaceTags, "Tags of surfaces in the geometric model "
2469  "(only OpenCASCADE and discrete surfaces are currently supported)",
2470  &updateNeeded);
2471  options["Sampling"] = new FieldOptionInt(
2472  _sampling, "Linear (i.e. per dimension) number of sampling points to "
2473  "discretize each curve and surface", &updateNeeded);
2474 
2475  // deprecated names
2476  options["NodesList"] =
2477  new FieldOptionList(_pointTags, "[Deprecated]", &updateNeeded, true);
2478  options["EdgesList"] =
2479  new FieldOptionList(_curveTags, "[Deprecated]", &updateNeeded, true);
2480  options["NNodesByEdge"] =
2481  new FieldOptionInt(_sampling, "[Deprecated]", &updateNeeded, true);
2482  options["FacesList"] =
2483  new FieldOptionList(_surfaceTags, "[Deprecated]", &updateNeeded, true);
2484  options["FieldX"] =
2485  new FieldOptionInt(_xFieldId, "[Deprecated]", &updateNeeded, true);
2486  options["FieldY"] =
2487  new FieldOptionInt(_yFieldId, "[Deprecated]", &updateNeeded, true);
2488  options["FieldZ"] =
2489  new FieldOptionInt(_zFieldId, "[Deprecated]", &updateNeeded, true);
2490  options["NumPointsPerCurve"] =
2491  new FieldOptionInt(_sampling, "[Deprecated]", &updateNeeded, true);
2492  }
2493  DistanceField(int dim, int tag, int nbe)
2494  : _sampling(nbe), _pc2kdtree(_pc), _kdtree(nullptr), _outIndex(0)
2495  {
2496  if(dim == 0)
2497  _pointTags.push_back(tag);
2498  else if(dim == 2)
2499  _curveTags.push_back(tag);
2500  else if(dim == 3)
2501  _surfaceTags.push_back(tag);
2502  _xFieldId = _yFieldId = _zFieldId = -1; // not used
2503  updateNeeded = true;
2504  }
2506  {
2507  if(_kdtree) delete _kdtree;
2508  }
2509  const char *getName() { return "Distance"; }
2510  std::string getDescription()
2511  {
2512  return "Compute the distance to the given points, curves or surfaces. "
2513  "For efficiency, curves and surfaces are replaced by a set "
2514  "of points (sampled according to Sampling), to which the distance "
2515  "is actually computed.";
2516  }
2517  std::pair<AttractorInfo, SPoint3> getAttractorInfo() const
2518  {
2519  if(_outIndex < _infos.size() && _outIndex < _pc.pts.size())
2520  return std::make_pair(_infos[_outIndex], _pc.pts[_outIndex]);
2521  return std::make_pair(AttractorInfo(), SPoint3());
2522  }
2523  void update()
2524  {
2525  if(updateNeeded) {
2526  _infos.clear();
2527  _pc.pts.clear();
2528  if(_kdtree) delete _kdtree;
2529 
2530  for(auto it = _pointTags.begin(); it != _pointTags.end(); ++it) {
2531  GVertex *gv = GModel::current()->getVertexByTag(*it);
2532  if(gv) {
2533  _pc.pts.push_back(SPoint3(gv->x(), gv->y(), gv->z()));
2534  _infos.push_back(AttractorInfo(*it, 0, 0, 0));
2535  }
2536  else {
2537  Msg::Warning("Unknown point %d", *it);
2538  }
2539  }
2540 
2541  for(auto it = _curveTags.begin(); it != _curveTags.end(); ++it) {
2542  GEdge *e = GModel::current()->getEdgeByTag(*it);
2543  if(e) {
2544  if(e->mesh_vertices.size()) {
2545  for(std::size_t i = 0; i < e->mesh_vertices.size(); i++) {
2546  _pc.pts.push_back(SPoint3(e->mesh_vertices[i]->x(),
2547  e->mesh_vertices[i]->y(),
2548  e->mesh_vertices[i]->z()));
2549  double t = 0.;
2550  e->mesh_vertices[i]->getParameter(0, t);
2551  _infos.push_back(AttractorInfo(*it, 1, t, 0));
2552  }
2553  }
2554  int NNN = _sampling - e->mesh_vertices.size();
2555  for(int i = 1; i < NNN - 1; i++) {
2556  double u = (double)i / (NNN - 1);
2557  Range<double> b = e->parBounds(0);
2558  double t = b.low() + u * (b.high() - b.low());
2559  GPoint gp = e->point(t);
2560  _pc.pts.push_back(SPoint3(gp.x(), gp.y(), gp.z()));
2561  _infos.push_back(AttractorInfo(*it, 1, t, 0));
2562  }
2563  }
2564  else {
2565  Msg::Warning("Unknown curve %d", *it);
2566  }
2567  }
2568 
2569  for(auto it = _surfaceTags.begin(); it != _surfaceTags.end(); ++it) {
2570  GFace *f = GModel::current()->getFaceByTag(*it);
2571  if(f) {
2572  double maxDist = f->bounds().diag() / _sampling;
2573  std::vector<SPoint2> uvpoints;
2574  f->fillPointCloud(maxDist, &_pc.pts, &uvpoints);
2575  for(std::size_t i = 0; i < uvpoints.size(); i++)
2576  _infos.push_back
2577  (AttractorInfo(*it, 2, uvpoints[i].x(), uvpoints[i].y()));
2578  }
2579  else {
2580  Msg::Warning("Unknown surface %d", *it);
2581  }
2582  }
2583 
2584  // construct a kd-tree index:
2585  _kdtree = new SPoint3KDTree(3, _pc2kdtree,
2587  _kdtree->buildIndex();
2588  updateNeeded = false;
2589  }
2590  }
2591  using Field::operator();
2592  virtual double operator()(double X, double Y, double Z, GEntity *ge = nullptr)
2593  {
2594  if(!_kdtree) return MAX_LC;
2595  double pt[3] = {X, Y, Z};
2597  double outDistSqr;
2598  res.init(&_outIndex, &outDistSqr);
2599  _kdtree->findNeighbors(res, &pt[0], nanoflann::SearchParams(10));
2600  return sqrt(outDistSqr);
2601  }
2602 };
2603 
2604 class ExtendField : public Field {
2605  std::list<int> _tagCurves, _tagSurfaces;
2606  std::vector<double> _sizeCurves, _sizeSurfaces;
2611 public:
2614  _kdtreeCurves(nullptr), _kdtreeSurfaces(nullptr)
2615  {
2616  _distMax = 1.;
2617  _sizeMax = 1.;
2618  _power = 1.;
2619  options["CurvesList"] = new FieldOptionList(
2620  _tagCurves, "Tags of curves in the geometric model", &updateNeeded);
2621  options["SurfacesList"] = new FieldOptionList(
2622  _tagSurfaces, "Tags of surfaces in the geometric model", &updateNeeded);
2623  options["DistMax"] = new FieldOptionDouble(
2624  _distMax, "Maximum distance of the size extension");
2625  options["SizeMax"] = new FieldOptionDouble(
2626  _sizeMax, "Mesh size outside DistMax");
2627  options["Power"] = new FieldOptionDouble(
2628  _power, "Power exponent used to interpolate the mesh size");
2629  }
2631  {
2632  if(_kdtreeCurves) delete _kdtreeCurves;
2633  if(_kdtreeSurfaces) delete _kdtreeSurfaces;
2634  }
2635  const char *getName() { return "Extend"; }
2636  std::string getDescription()
2637  {
2638  return "Compute an extension of the mesh sizes from the given boundary "
2639  "curves (resp. surfaces) inside the surfaces (resp. volumes) "
2640  "being meshed. If the mesh size on the boundary, computed "
2641  "as the local average length of the edges of the boundary elements, "
2642  "is denoted by SizeBnd, the extension is computed as:\n\n"
2643  " F = f * SizeBnd + (1 - f) * SizeMax, if d < DistMax\n\n"
2644  " F = SizeMax, if d >= DistMax\n\n"
2645  "where d denotes the distance to the boundary and "
2646  "f = ((DistMax - d) / DistMax)^Power.";
2647  }
2649  {
2650  _sizeCurves.clear();
2651  _pcCurves.pts.clear();
2652  if(_kdtreeCurves) delete _kdtreeCurves;
2653  for(auto t : _tagCurves) {
2654  GEdge *ge = GModel::current()->getEdgeByTag(t);
2655  if(ge) {
2656  for(auto e : ge->lines) {
2657  _pcCurves.pts.push_back(e->barycenter());
2658  _sizeCurves.push_back(e->getEdge(0).length());
2659  }
2660  }
2661  else {
2662  Msg::Warning("Unknown curve %d", t);
2663  }
2664  }
2665  if(_sizeCurves.empty()) {
2666  _kdtreeCurves = nullptr;
2667  }
2668  else {
2672  }
2673  }
2675  {
2676  _sizeSurfaces.clear();
2677  _pcSurfaces.pts.clear();
2678  if(_kdtreeSurfaces) delete _kdtreeSurfaces;
2679  for(auto t : _tagSurfaces) {
2680  GFace *gf = GModel::current()->getFaceByTag(t);
2681  if(gf) {
2682  for(auto e : gf->triangles) {
2683  _pcSurfaces.pts.push_back(e->barycenter());
2684  double s = e->getEdge(0).length() + e->getEdge(1).length() +
2685  e->getEdge(2).length();
2686  _sizeSurfaces.push_back(s / 3.);
2687  }
2688  }
2689  else {
2690  Msg::Warning("Unknown surface %d", t);
2691  }
2692  }
2693  if(_sizeSurfaces.empty()) {
2694  _kdtreeSurfaces = nullptr;
2695  }
2696  else {
2700  }
2701  }
2702  using Field::operator();
2703  virtual double operator()(double X, double Y, double Z, GEntity *ge = nullptr)
2704  {
2705  if(!ge) return MAX_LC;
2706  if(ge->dim() != 2 && ge->dim() != 3) return MAX_LC;
2707  if(ge->dim() == 2 && _tagCurves.empty()) return MAX_LC;
2708  if(ge->dim() == 3 && _tagSurfaces.empty()) return MAX_LC;
2709 #pragma omp critical
2710  if(updateNeeded ||
2711  (ge->dim() == 2 && _tagCurves.size() && _sizeCurves.empty())) {
2712  // we are meshing our first surface; recompute distance to the elements on
2713  // curves, and invalidate the distance to surfaces
2714  recomputeCurves();
2715  _sizeSurfaces.clear();
2716  updateNeeded = false;
2717  }
2718 #pragma omp critical
2719  if(updateNeeded ||
2720  (ge->dim() == 3 && _tagSurfaces.size() && _sizeSurfaces.empty())) {
2721  // we are meshing our first volume; recompute distance to the elements on
2722  // surfaces, and invalidate the distance to curves (to be ready for
2723  // subsequent surface meshing pass)
2725  _sizeCurves.clear();
2726  updateNeeded = false;
2727  }
2728  double pt[3] = {X, Y, Z};
2730  std::size_t index = 0;
2731  double dist2 = 0., sbnd = 0.;
2732  res.init(&index, &dist2);
2733  if(ge->dim() == 2 && _kdtreeCurves) {
2735  sbnd = _sizeCurves[index];
2736  }
2737  else if(ge->dim() == 3 && _kdtreeSurfaces) {
2739  sbnd = _sizeSurfaces[index];
2740  }
2741  if(sbnd <= 0 || _distMax <= 0 || _sizeMax <= 0) return MAX_LC;
2742  double d = sqrt(dist2);
2743  if(d >= _distMax) return _sizeMax;
2744  double f = (_distMax - d) / _distMax;
2745  if(_power != 1.) {
2746  f = std::pow(f, _power);
2747  }
2748  // "unscale" the boundary size according to the per-entity and/or the global
2749  // mesh size factor, so that, if a factor is applied, it will be on the
2750  // interpolated "specified" mesh size values
2751  if(ge && ge->getMeshSizeFactor() != 1.0)
2752  sbnd /= ge->getMeshSizeFactor();
2753  sbnd /= CTX::instance()->mesh.lcFactor;
2754  double s = f * sbnd + (1. - f) * _sizeMax;
2755  return s;
2756  }
2757 };
2758 
2759 const char *BoundaryLayerField::getName() { return "BoundaryLayer"; }
2760 
2762 {
2763  return "Insert a 2D boundary layer mesh next to some curves in the model.";
2764 }
2765 
2767 {
2768  betaLaw = 0;
2769  nb_divisions = 10;
2770  beta = 1.01;
2771  hWallN = .1;
2772  hFar = 1;
2773  ratio = 1.1;
2774  thickness = 1.e-2;
2775  tgtAnisoRatio = 1.e10;
2776  iRecombine = 0;
2777  iIntersect = 0;
2778 
2779  options["CurvesList"] = new FieldOptionList(
2780  _curveTags,
2781  "Tags of curves in the geometric model for which a boundary "
2782  "layer is needed",
2783  &updateNeeded);
2784  options["FanPointsList"] =
2786  "Tags of points in the geometric model for which a fan "
2787  "is created",
2788  &updateNeeded);
2789  options["FanPointsSizesList"] = new FieldOptionList(
2790  _fanSizes,
2791  "Number of elements in the fan for each fan node. "
2792  "If not present default value Mesh.BoundaryLayerFanElements",
2793  &updateNeeded);
2794  options["PointsList"] = new FieldOptionList(
2795  _pointTags,
2796  "Tags of points in the geometric model for which a boundary "
2797  "layer ends",
2798  &updateNeeded);
2799  options["Size"] =
2800  new FieldOptionDouble(hWallN, "Mesh size normal to the curve");
2801  options["SizesList"] = new FieldOptionListDouble(
2802  _hWallNNodes, "Mesh size normal to the curve, per point (overwrites "
2803  "Size when defined)");
2804  options["Ratio"] =
2805  new FieldOptionDouble(ratio, "Size ratio between two successive layers");
2806  options["SizeFar"] =
2807  new FieldOptionDouble(hFar, "Mesh size far from the curves");
2808  options["Thickness"] =
2809  new FieldOptionDouble(thickness, "Maximal thickness of the boundary layer");
2810  options["Quads"] = new FieldOptionInt(
2811  iRecombine, "Generate recombined elements in the boundary layer");
2812  options["IntersectMetrics"] =
2813  new FieldOptionInt(iIntersect, "Intersect metrics of all surfaces");
2814  options["AnisoMax"] = new FieldOptionDouble(
2815  tgtAnisoRatio, "Threshold angle for creating a mesh fan in the boundary "
2816  "layer");
2817  options["BetaLaw"] = new FieldOptionInt(
2818  betaLaw, "Use Beta Law instead of geometric progression ");
2819  options["Beta"] =
2820  new FieldOptionDouble(beta, "Beta coefficient of the Beta Law");
2821  options["NbLayers"] =
2822  new FieldOptionInt(nb_divisions, "Number of Layers in theBeta Law");
2823  options["ExcludedSurfacesList"] =
2825  "Tags of surfaces in the geometric model where the "
2826  "boundary layer should not be constructed",
2827  &updateNeeded);
2828 
2829  // deprecated names
2830  options["EdgesList"] =
2831  new FieldOptionList(_curveTags, "[Deprecated]", &updateNeeded, true);
2832  options["FanNodesList"] =
2833  new FieldOptionList(_fanPointTags, "[Deprecated]", &updateNeeded, true);
2834  options["NodesList"] =
2835  new FieldOptionList(_pointTags, "[Deprecated]", &updateNeeded, true);
2836  options["hwall_n"] =
2837  new FieldOptionDouble(hWallN, "[Deprecated]", nullptr, true);
2838  options["hwall_n_nodes"] =
2839  new FieldOptionListDouble(_hWallNNodes, "[Deprecated]", nullptr, true);
2840  options["ratio"] =
2841  new FieldOptionDouble(ratio, "[Deprecated]", nullptr, true);
2842  options["hfar"] =
2843  new FieldOptionDouble(hFar, "[Deprecated]", nullptr, true);
2844  options["thickness"] =
2845  new FieldOptionDouble(thickness, "[Deprecated]", nullptr, true);
2846  options["ExcludedFaceList"] =
2847  new FieldOptionList(_excludedSurfaceTags, "[Deprecated]", &updateNeeded, true);
2848 }
2849 
2851 {
2852  for(auto it = _attFields.begin(); it != _attFields.end(); ++it) delete *it;
2853  _attFields.clear();
2854  updateNeeded = true;
2855 }
2856 
2858 {
2859  if(_curveTagsSaved.empty()) {
2862  }
2863 
2864  _pointTags.clear();
2865  _curveTags.clear();
2866 
2867  bool found = std::find(_curveTagsSaved.begin(), _curveTagsSaved.end(), iE) !=
2868  _curveTagsSaved.end();
2869 
2870  if(!found) {
2871  GEdge *ge = GModel::current()->getEdgeByTag(iE);
2872  if(ge) {
2873  GVertex *gv0 = ge->getBeginVertex();
2874  if(gv0) {
2875  found = std::find(_pointTagsSaved.begin(), _pointTagsSaved.end(),
2876  gv0->tag()) != _pointTagsSaved.end();
2877  if(found) _pointTags.push_back(gv0->tag());
2878  }
2879  GVertex *gv1 = ge->getEndVertex();
2880  if(gv1) {
2881  found = std::find(_pointTagsSaved.begin(), _pointTagsSaved.end(),
2882  gv1->tag()) != _pointTagsSaved.end();
2883  if(found) _pointTags.push_back(gv1->tag());
2884  }
2885  }
2886  else {
2887  Msg::Warning("Unknown curve %d", iE);
2888  }
2889  }
2890  removeAttractors();
2891 }
2892 
2894 {
2895  if(std::find(_excludedSurfaceTags.begin(), _excludedSurfaceTags.end(), iF) !=
2896  _excludedSurfaceTags.end())
2897  return false;
2898 
2899  // remove GFaces from the attractors (only used in 2D) for edges and vertices
2900  if(_curveTagsSaved.empty()) {
2903  }
2904 
2905  _pointTags.clear();
2906  _curveTags.clear();
2907 
2908  // FIXME :
2909  // NOT REALLY A NICE WAY TO DO IT (VERY AD HOC)
2910  // THIS COULD BE PART OF THE INPUT
2911  // OR (better) CHANGE THE PHILOSOPHY
2912 
2913  GFace *gf = GModel::current()->getFaceByTag(iF);
2914  if(!gf) {
2915  Msg::Warning("Unknown surface %d", iF);
2916  return false;
2917  }
2918  std::vector<GEdge *> ed = gf->edges();
2919  std::vector<GEdge *> const &embedded_edges = gf->embeddedEdges();
2920  ed.insert(ed.begin(), embedded_edges.begin(), embedded_edges.end());
2921 
2922  for(auto it = ed.begin(); it != ed.end(); ++it) {
2923  bool isIn = false;
2924  int iE = (*it)->tag();
2925  bool found = std::find(_curveTagsSaved.begin(), _curveTagsSaved.end(),
2926  iE) != _curveTagsSaved.end();
2927  // this edge is a BL Edge
2928  if(found) {
2929  std::vector<GFace *> fc = (*it)->faces();
2930  int numf = 0;
2931  for(auto it = fc.begin(); it != fc.end(); it++) {
2932  if((*it)->meshAttributes.extrude &&
2933  (*it)->meshAttributes.extrude->geo.Mode == EXTRUDED_ENTITY) {
2934  // ok
2935  }
2936  else if(std::find(_excludedSurfaceTags.begin(),
2937  _excludedSurfaceTags.end(),
2938  (*it)->tag()) != _excludedSurfaceTags.end()) {
2939  // ok
2940  }
2941  else {
2942  numf++;
2943  }
2944  }
2945  // one only face, or other faces are extruded --> 2D --> BL
2946  if(numf <= 1)
2947  isIn = true;
2948  else {
2949  Msg::Error("Only 2D Boundary Layers are supported (curve %d is adjacet "
2950  "to %d surfaces)",
2951  iE, fc.size());
2952  }
2953  }
2954  if(isIn) {
2955  _curveTags.push_back(iE);
2956  if((*it)->getBeginVertex())
2957  _pointTags.push_back((*it)->getBeginVertex()->tag());
2958  if((*it)->getEndVertex())
2959  _pointTags.push_back((*it)->getEndVertex()->tag());
2960  }
2961  }
2962 
2963  removeAttractors();
2964  return true;
2965 }
2966 
2967 double BoundaryLayerField::operator()(double x, double y, double z, GEntity *ge)
2968 {
2969  if(updateNeeded) {
2970  for(auto it = _pointTags.begin(); it != _pointTags.end(); ++it) {
2971  _attFields.push_back(new DistanceField(0, *it, 100000));
2972  }
2973  for(auto it = _curveTags.begin(); it != _curveTags.end(); ++it) {
2974  _attFields.push_back(new DistanceField(1, *it, 300000));
2975  }
2976  updateNeeded = false;
2977  }
2978 
2979  double dist = 1.e22;
2980  if(_attFields.empty()) return dist;
2981  for(auto it = _attFields.begin(); it != _attFields.end(); ++it) {
2982  double cdist = (*(*it))(x, y, z);
2983  if(cdist < dist) { dist = cdist; }
2984  }
2985 
2986  if(dist > thickness * ratio) return 1.e22;
2987  currentDistance = dist;
2988  // const double dist = (*field) (x, y, z);
2989  // currentDistance = dist;
2990  double lc = dist * (ratio - 1) + hWallN;
2991 
2992  // double lc = hWallN;
2993  return std::min(hFar, lc);
2994 }
2995 
2996 // assume that the closest point is one of the model vertices
2997 void BoundaryLayerField::computeFor1dMesh(double x, double y, double z,
2998  SMetric3 &metr)
2999 {
3000  double xpk = 0., ypk = 0., zpk = 0.;
3001  double distk = 1.e22;
3002  for(auto it = _pointTags.begin(); it != _pointTags.end(); ++it) {
3003  GVertex *v = GModel::current()->getVertexByTag(*it);
3004  if(v) {
3005  double xp = v->x();
3006  double yp = v->y();
3007  double zp = v->z();
3008  const double dist =
3009  sqrt((x - xp) * (x - xp) + (y - yp) * (y - yp) + (z - zp) * (z - zp));
3010  if(dist < distk) {
3011  distk = dist;
3012  xpk = xp;
3013  ypk = yp;
3014  zpk = zp;
3015  }
3016  }
3017  else {
3018  Msg::Warning("Unknown point %d", *it);
3019  }
3020  }
3021 
3022  const double ll1 = (distk * (ratio - 1) + hWallN) / (1. + 0.5 * (ratio - 1));
3023  double lc_n = std::min(ll1, hFar);
3024 
3025  if(distk > thickness) lc_n = hFar;
3026  lc_n = std::max(lc_n, CTX::instance()->mesh.lcMin);
3027  lc_n = std::min(lc_n, CTX::instance()->mesh.lcMax);
3028  SVector3 t1 = SVector3(x - xpk, y - ypk, z - zpk);
3029  t1.normalize();
3030  metr = buildMetricTangentToCurve(t1, lc_n, lc_n);
3031 }
3032 
3033 void BoundaryLayerField::operator()(DistanceField *cc, double dist, double x,
3034  double y, double z, SMetric3 &metr,
3035  GEntity *ge)
3036 {
3037  // dist = hwall -> lc = hwall * ratio
3038  // dist = hwall (1+ratio) -> lc = hwall ratio ^ 2
3039  // dist = hwall (1+ratio+ratio^2) -> lc = hwall ratio ^ 3
3040  // dist = hwall (1+ratio+ratio^2+...+ratio^{m-1}) = (ratio^{m} - 1)/(ratio-1)
3041  // -> lc = hwall ratio ^ m
3042  // -> find m
3043  // dist/hwall = (ratio^{m} - 1)/(ratio-1)
3044  // (dist/hwall)*(ratio-1) + 1 = ratio^{m}
3045  // lc = dist*(ratio-1) + hwall
3046 
3047  const double ll1 = dist * (ratio - 1) + hWallN;
3048  double lc_n = std::min(ll1, hFar);
3049  double lc_t = std::min(lc_n * CTX::instance()->mesh.anisoMax, hFar);
3050 
3051  lc_n = std::max(lc_n, CTX::instance()->mesh.lcMin);
3052  lc_n = std::min(lc_n, CTX::instance()->mesh.lcMax);
3053  lc_t = std::max(lc_t, CTX::instance()->mesh.lcMin);
3054  lc_t = std::min(lc_t, CTX::instance()->mesh.lcMax);
3055 
3056  std::pair<AttractorInfo, SPoint3> pp = cc->getAttractorInfo();
3057  double beta = CTX::instance()->mesh.smoothRatio;
3058  if(pp.first.dim == 0) {
3059  GVertex *v = GModel::current()->getVertexByTag(pp.first.ent);
3060  if(!v) return;
3061  SVector3 t1;
3062  if(dist < thickness) { t1 = SVector3(1, 0, 0); }
3063  else {
3064  t1 = SVector3(v->x() - x, v->y() - y, v->z() - z);
3065  }
3066  metr = buildMetricTangentToCurve(t1, lc_n, lc_n);
3067  return;
3068  }
3069  else if(pp.first.dim == 1) {
3070  GEdge *e = GModel::current()->getEdgeByTag(pp.first.ent);
3071  if(!e) {
3072  Msg::Warning("Unknown curve %d", pp.first.ent);
3073  return;
3074  }
3075  if(dist < thickness) {
3076  SVector3 t1 = e->firstDer(pp.first.u);
3077  double crv = e->curvature(pp.first.u);
3078  const double b = lc_t;
3079  const double h = lc_n;
3080  double oneOverD2 =
3081  .5 / (b * b) *
3082  (1. +
3083  sqrt(1. + (4. * crv * crv * b * b * b * b / (h * h * beta * beta))));
3084  metr = buildMetricTangentToCurve(t1, sqrt(1. / oneOverD2), lc_n);
3085  return;
3086  }
3087  else {
3088  GPoint p = e->point(pp.first.u);
3089  SVector3 t2 = SVector3(p.x() - x, p.y() - y, p.z() - z);
3090  metr = buildMetricTangentToCurve(t2, lc_t, lc_n);
3091  return;
3092  }
3093  }
3094  else {
3095  GFace *gf = GModel::current()->getFaceByTag(pp.first.ent);
3096  if(!gf) {
3097  Msg::Warning("Unknown surface %d", pp.first.ent);
3098  return;
3099  }
3100  if(dist < thickness) {
3101  double cmin, cmax;
3102  SVector3 dirMax, dirMin;
3103  cmax = gf->curvatures(SPoint2(pp.first.u, pp.first.v), dirMax, dirMin,
3104  cmax, cmin);
3105  const double b = lc_t;
3106  const double h = lc_n;
3107  double oneOverD2_min =
3108  .5 / (b * b) *
3109  (1. +
3110  sqrt(1. + (4. * cmin * cmin * b * b * b * b / (h * h * beta * beta))));
3111  double oneOverD2_max =
3112  .5 / (b * b) *
3113  (1. +
3114  sqrt(1. + (4. * cmax * cmax * b * b * b * b / (h * h * beta * beta))));
3115  double dmin = sqrt(1. / oneOverD2_min);
3116  double dmax = sqrt(1. / oneOverD2_max);
3117  dmin = std::min(dmin, dmax * tgtAnisoRatio);
3118  metr = buildMetricTangentToSurface(dirMin, dirMax, dmin, dmax, lc_n);
3119  return;
3120  }
3121  else {
3122  GPoint p = gf->point(SPoint2(pp.first.u, pp.first.v));
3123  SVector3 t2 = SVector3(p.x() - x, p.y() - y, p.z() - z);
3124  metr = buildMetricTangentToCurve(t2, lc_n, lc_t);
3125  return;
3126  }
3127  }
3128 }
3129 
3130 void BoundaryLayerField::operator()(double x, double y, double z,
3131  SMetric3 &metr, GEntity *ge)
3132 {
3133  if(updateNeeded) {
3134  for(auto it = _pointTags.begin(); it != _pointTags.end(); ++it) {
3135  _attFields.push_back(new DistanceField(0, *it, 100000));
3136  }
3137  for(auto it = _curveTags.begin(); it != _curveTags.end(); ++it) {
3138  _attFields.push_back(new DistanceField(1, *it, 10000));
3139  }
3140  updateNeeded = false;
3141  }
3142 
3143  currentDistance = 1.e22;
3144  currentClosest = nullptr;
3145  std::vector<SMetric3> hop;
3146  SMetric3 v(1. / (CTX::instance()->mesh.lcMax * CTX::instance()->mesh.lcMax));
3147  hop.push_back(v);
3148  for(auto it = _attFields.begin(); it != _attFields.end(); ++it) {
3149  double cdist = (*(*it))(x, y, z);
3150  SPoint3 CLOSEST = (*it)->getAttractorInfo().second;
3151  SMetric3 localMetric;
3152  if(iIntersect) {
3153  (*this)(*it, cdist, x, y, z, localMetric, ge);
3154  hop.push_back(localMetric);
3155  }
3156  if(cdist < currentDistance) {
3157  if(!iIntersect) (*this)(*it, cdist, x, y, z, localMetric, ge);
3158  currentDistance = cdist;
3159  currentClosest = *it;
3160  v = localMetric;
3161  _closestPoint = CLOSEST;
3162  }
3163  }
3164  if(iIntersect)
3165  for(std::size_t i = 0; i < hop.size(); i++)
3166  v = intersection_conserveM1(v, hop[i]);
3167  metr = v;
3168 }
3169 
3171 {
3172  mapTypeName["Structured"] = new FieldFactoryT<StructuredField>();
3173  mapTypeName["Threshold"] = new FieldFactoryT<ThresholdField>();
3174  mapTypeName["BoundaryLayer"] = new FieldFactoryT<BoundaryLayerField>();
3175  mapTypeName["Box"] = new FieldFactoryT<BoxField>();
3176  mapTypeName["Cylinder"] = new FieldFactoryT<CylinderField>();
3177  mapTypeName["Ball"] = new FieldFactoryT<BallField>();
3178  mapTypeName["Frustum"] = new FieldFactoryT<FrustumField>();
3179  mapTypeName["LonLat"] = new FieldFactoryT<LonLatField>();
3180 #if defined(HAVE_POST)
3181  mapTypeName["PostView"] = new FieldFactoryT<PostViewField>();
3182 #endif
3183  mapTypeName["Gradient"] = new FieldFactoryT<GradientField>();
3184  mapTypeName["Octree"] = new FieldFactoryT<OctreeField>();
3185  mapTypeName["Distance"] = new FieldFactoryT<DistanceField>();
3186  mapTypeName["Attractor"] = new FieldFactoryT<DistanceField>();
3187  mapTypeName["Extend"] = new FieldFactoryT<ExtendField>();
3188  mapTypeName["Restrict"] = new FieldFactoryT<RestrictField>();
3189  mapTypeName["Constant"] = new FieldFactoryT<ConstantField>();
3190  mapTypeName["Min"] = new FieldFactoryT<MinField>();
3191  mapTypeName["MinAniso"] = new FieldFactoryT<MinAnisoField>();
3192  mapTypeName["IntersectAniso"] = new FieldFactoryT<IntersectAnisoField>();
3193  mapTypeName["Max"] = new FieldFactoryT<MaxField>();
3194  mapTypeName["Laplacian"] = new FieldFactoryT<LaplacianField>();
3195  mapTypeName["Mean"] = new FieldFactoryT<MeanField>();
3196  mapTypeName["Curvature"] = new FieldFactoryT<CurvatureField>();
3198  mapTypeName["ExternalProcess"] = new FieldFactoryT<ExternalProcessField>();
3199  mapTypeName["MathEval"] = new FieldFactoryT<MathEvalField>();
3200  mapTypeName["MathEvalAniso"] = new FieldFactoryT<MathEvalFieldAniso>();
3201 #if defined(HAVE_ANN)
3202  mapTypeName["AttractorAnisoCurve"] =
3204 #endif
3205  mapTypeName["MaxEigenHessian"] = new FieldFactoryT<MaxEigenHessianField>();
3206  mapTypeName["AutomaticMeshSizeField"] =
3208  _backgroundField = -1;
3209 }
3210 
3212 {
3213  auto it = begin();
3214  for(; it != end(); ++it) it->second->update();
3215 }
3216 
3218 {
3219  for(auto it = mapTypeName.begin(); it != mapTypeName.end(); it++)
3220  delete it->second;
3221  for(auto it = begin(); it != end(); it++) delete it->second;
3222 }
3223 
3225 {
3226  int id = newId();
3227  (*this)[id] = BGF;
3228  _backgroundField = id;
3229 }
3230 
3231 void Field::putOnNewView(int viewTag)
3232 {
3233 #if defined(HAVE_POST)
3234  if(GModel::current()->getMeshStatus() < 1) {
3235  Msg::Error("No mesh available to create the view: please mesh your model!");
3236  return;
3237  }
3238  std::map<int, std::vector<double> > d;
3239  std::vector<GEntity *> entities;
3240  GModel::current()->getEntities(entities);
3241  for(std::size_t i = 0; i < entities.size(); i++) {
3242  for(std::size_t j = 0; j < entities[i]->mesh_vertices.size(); j++) {
3243  MVertex *v = entities[i]->mesh_vertices[j];
3244  d[v->getNum()].push_back((*this)(v->x(), v->y(), v->z(), entities[i]));
3245  }
3246  }
3247  std::ostringstream oss;
3248  oss << "Field " << id;
3249  PView *view =
3250  new PView(oss.str(), "NodeData", GModel::current(), d, 0, -1, viewTag);
3251  view->setChanged(true);
3252 #endif
3253 }
3254 
3255 #if defined(HAVE_POST)
3256 void Field::putOnView(PView *view, int comp)
3257 {
3258  PViewData *data = view->getData();
3259  for(int ent = 0; ent < data->getNumEntities(0); ent++) {
3260  for(int ele = 0; ele < data->getNumElements(0, ent); ele++) {
3261  if(data->skipElement(0, ent, ele)) continue;
3262  for(int nod = 0; nod < data->getNumNodes(0, ent, ele); nod++) {
3263  double x, y, z;
3264  data->getNode(0, ent, ele, nod, x, y, z);
3265  double val = (*this)(x, y, z);
3266  for(int comp = 0; comp < data->getNumComponents(0, ent, ele); comp++)
3267  data->setValue(0, ent, ele, nod, comp, val);
3268  }
3269  }
3270  }
3271  std::ostringstream oss;
3272  oss << "Field " << id;
3273  data->setName(oss.str());
3274  data->finalize();
3275  view->setChanged(true);
3276  data->destroyAdaptiveData();
3277 }
3278 #endif
3279 
3281 {
3282  int id = newId();
3283  Field *f = newField(id, "PostView");
3284  f->options["ViewIndex"]->numericalValue(iView);
3285  (*this)[id] = f;
3286  _backgroundField = id;
3287 }
3288 
3290 
3292 
3293 double GenericField::operator()(double x, double y, double z, GEntity *ge)
3294 {
3295  std::vector<double> sizes(cbs_with_data.size() +
3296  cbs_extended_with_data.size());
3297  auto it = sizes.begin();
3298 
3299  // Go over all callback functions
3300  for(auto itcbs = cbs_with_data.begin(); itcbs != cbs_with_data.end();
3301  itcbs++, it++) {
3302  bool ok = (itcbs->first)(x, y, z, itcbs->second, (*it));
3303  if(!ok) { Msg::Warning("GenericField error from callback"); }
3304  }
3305 
3306  // Go over all extended callback functions
3307  for(auto itcbs = cbs_extended_with_data.begin();
3308  itcbs != cbs_extended_with_data.end(); itcbs++, it++) {
3309  bool ok = (itcbs->first)(x, y, z, ge, itcbs->second, (*it));
3310  if(!ok) { Msg::Warning("GenericField error from callback"); }
3311  }
3312 
3313  // Take minimum value
3314  return (*std::min_element(sizes.begin(), sizes.end()));
3315 }
3316 
3317 void GenericField::setCallbackWithData(ptrfunction fct, void *data)
3318 {
3319  cbs_with_data.push_back(std::make_pair(fct, data));
3320 }
3321 
3322 void GenericField::setCallbackWithData(ptrfunctionextended fct, void *data)
3323 {
3324  cbs_extended_with_data.push_back(std::make_pair(fct, data));
3325 }
PointCloudAdaptor::derived
const Derived & derived() const
Definition: Field.cpp:2423
ThresholdField::ThresholdField
ThresholdField()
Definition: Field.cpp:643
ExtendField::_pcCurves
SPoint3Cloud _pcCurves
Definition: Field.cpp:2607
StructuredField::getDescription
std::string getDescription()
Definition: Field.cpp:163
nanoflann::KDTreeSingleIndexAdaptor::findNeighbors
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParams &searchParams) const
Definition: nanoflann.hpp:906
FieldFactoryT
Definition: Field.h:440
crossprod
SVector3 crossprod(const SVector3 &a, const SVector3 &b)
Definition: SVector3.h:150
MaxField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:1904
BoundaryLayerField::_closestPoint
SPoint3 _closestPoint
Definition: Field.h:199
BallField::getDescription
std::string getDescription()
Definition: Field.cpp:481
Popen2::stop
void stop()
Definition: Field.cpp:1344
BoxField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:399
MathEvalExpressionAniso
Definition: Field.cpp:1051
MaxField::_fields
std::vector< Field * > _fields
Definition: Field.cpp:1891
CurvatureField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:806
Field::~Field
virtual ~Field()
Definition: Field.cpp:51
GFace::edges
virtual std::vector< GEdge * > const & edges() const
Definition: GFace.h:121
PView
Definition: PView.h:27
RestrictField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:1976
RestrictField
Definition: Field.cpp:1937
MinAnisoField::_fieldIds
std::list< int > _fieldIds
Definition: Field.cpp:1710
OctreeField::bounds
SBoundingBox3d bounds
Definition: Field.cpp:2363
Field.h
DistanceField::_kdtree
SPoint3KDTree * _kdtree
Definition: Field.cpp:2455
BoundaryLayerField::currentClosest
DistanceField * currentClosest
Definition: Field.h:207
OctreeField::Cell::print
void print(double x0, double y0, double z0, double l, FILE *f)
Definition: Field.cpp:2340
GradientField::_kind
int _kind
Definition: Field.cpp:707
FieldManager::reset
void reset()
Definition: Field.cpp:68
ExternalProcessField::getDescription
std::string getDescription()
Definition: Field.cpp:1427
CurvatureField::CurvatureField
CurvatureField()
Definition: Field.cpp:782
BoundaryLayerField::hFar
double hFar
Definition: Field.h:204
CylinderField::CylinderField
CylinderField()
Definition: Field.cpp:431
BallField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:509
Field::callbacks
std::map< std::string, FieldCallback * > callbacks
Definition: Field.h:113
MinField::_fields
std::vector< Field * > _fields
Definition: Field.cpp:1842
OctreeField::getName
const char * getName()
Definition: Field.cpp:2379
mathEvaluator
Definition: mathEvaluator.h:37
GenericField::setCallbackWithData
void setCallbackWithData(ptrfunction fct, void *data)
Definition: Field.cpp:3317
SMetric3
Definition: STensor3.h:17
ConstantField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:2049
GVertex::z
virtual double z() const =0
ExtendField::_pc2kdtreeCurves
SPoint3CloudAdaptor< SPoint3Cloud > _pc2kdtreeCurves
Definition: Field.cpp:2608
ExtendField::_kdtreeCurves
SPoint3KDTree * _kdtreeCurves
Definition: Field.cpp:2609
GPoint::y
double y() const
Definition: GPoint.h:22
PViewData::skipElement
virtual bool skipElement(int step, int ent, int ele, bool checkVisibility=false, int samplingRate=1)
Definition: PViewData.cpp:90
BoundaryLayerField::getName
virtual const char * getName()
Definition: Field.cpp:2759
ParametricField::_inField
int _inField
Definition: Field.cpp:1501
ExtendField::_kdtreeSurfaces
SPoint3KDTree * _kdtreeSurfaces
Definition: Field.cpp:2609
ThresholdField::_stopAtDistMax
bool _stopAtDistMax
Definition: Field.cpp:632
MathEvalField::_expr
MathEvalExpression _expr
Definition: Field.cpp:1140
DistanceField::_surfaceTags
std::list< int > _surfaceTags
Definition: Field.cpp:2449
ThresholdField::getDescription
virtual std::string getDescription()
Definition: Field.cpp:636
fullVector< double >
Popen2::~Popen2
~Popen2()
Definition: Field.cpp:1382
CylinderField::_zc
double _zc
Definition: Field.cpp:418
mathEvaluator.h
ExternalProcessField::_pipes
Popen2 _pipes
Definition: Field.cpp:1389
CylinderField::getName
const char * getName()
Definition: Field.cpp:454
IntersectAnisoField::getName
const char * getName()
Definition: Field.cpp:1836
Popen2::start
bool start(const char *command)
Definition: Field.cpp:1353
GFace
Definition: GFace.h:33
StructuredField::_fileName
std::string _fileName
Definition: Field.cpp:138
MinField::MinField
MinField()
Definition: Field.cpp:1845
GFace::triangles
std::vector< MTriangle * > triangles
Definition: GFace.h:428
FrustumField::_v2i
double _v2i
Definition: Field.cpp:530
MinAnisoField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:1744
GEdge::lines
std::vector< MLine * > lines
Definition: GEdge.h:42
MeanField::_inField
int _inField
Definition: Field.cpp:931
SPoint2
Definition: SPoint2.h:12
ExtendField::_distMax
double _distMax
Definition: Field.cpp:2610
ThresholdField::_lcMin
double _lcMin
Definition: Field.cpp:631
PViewData::setValue
virtual void setValue(int step, int ent, int ele, int nod, int comp, double val)
Definition: PViewData.cpp:130
LaplacianField::LaplacianField
LaplacianField()
Definition: Field.cpp:900
FieldOptionString
Definition: Field.h:265
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
CylinderField::_r
double _r
Definition: Field.cpp:420
ConstantField::getDescription
std::string getDescription()
Definition: Field.cpp:2043
ExtendField::_pcSurfaces
SPoint3Cloud _pcSurfaces
Definition: Field.cpp:2607
CylinderField::_ya
double _ya
Definition: Field.cpp:419
OctreeField::Cell
Definition: Field.cpp:2260
MVertex
Definition: MVertex.h:24
OctreeField::_root
Cell * _root
Definition: Field.cpp:2360
SVector3::data
const double * data() const
Definition: SVector3.h:131
FrustumField::_z1
double _z1
Definition: Field.cpp:527
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
PViewData::getNode
virtual int getNode(int step, int ent, int ele, int nod, double &x, double &y, double &z)
Definition: PViewData.h:141
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
CurvatureField
Definition: Field.cpp:770
ConstantField::_pointTags
std::list< int > _pointTags
Definition: Field.cpp:2026
MVertex::z
double z() const
Definition: MVertex.h:62
BoundaryLayerField::_pointTagsSaved
std::list< int > _pointTagsSaved
Definition: Field.h:196
SMetric3::eig
void eig(fullMatrix< double > &V, fullVector< double > &S, bool s=false) const
Definition: STensor3.cpp:104
Popen2
Definition: Field.cpp:1338
Popen2::write
bool write(void *data, size_t size)
Definition: Field.cpp:1378
MathEvalExpression::MathEvalExpression
MathEvalExpression()
Definition: Field.cpp:981
BallField::BallField
BallField()
Definition: Field.cpp:490
Field::isotropic
virtual bool isotropic() const
Definition: Field.h:115
StructuredField::_errorStatus
bool _errorStatus
Definition: Field.cpp:135
MathEvalExpressionAniso::evaluate
void evaluate(double x, double y, double z, SMetric3 &metr)
Definition: Field.cpp:1106
PointCloudAdaptor::obj
const Derived & obj
Definition: Field.cpp:2421
SPoint3KDTree.h
MathEvalFieldAniso::_f
std::string _f[6]
Definition: Field.cpp:1178
DistanceField::operator()
virtual double operator()(double X, double Y, double Z, GEntity *ge=nullptr)
Definition: Field.cpp:2592
MathEvalExpressionAniso::MathEvalExpressionAniso
MathEvalExpressionAniso()
Definition: Field.cpp:1057
MeanField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:959
ParametricField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:1528
SPoint3
Definition: SPoint3.h:14
LegendrePolynomials::f
void f(int n, double u, double *val)
Definition: orthogonalBasis.cpp:77
GradientField::GradientField
GradientField()
Definition: Field.cpp:718
DistanceField::_yFieldId
int _yFieldId
Definition: Field.cpp:2452
Popen2::started
bool started() const
Definition: Field.cpp:1352
CurvatureField::getDescription
std::string getDescription()
Definition: Field.cpp:777
MinAnisoField::MinAnisoField
MinAnisoField()
Definition: Field.cpp:1713
PViewData::searchVectorClosest
bool searchVectorClosest(double x, double y, double z, double &distance, double *values, int step=-1, double *size=nullptr, int qn=0, double *qx=nullptr, double *qy=nullptr, double *qz=nullptr, bool grad=false, int dim=-1)
Definition: PViewData.cpp:378
mathEvaluator::eval
bool eval(const std::vector< double > &values, std::vector< double > &res)
Definition: mathEvaluator.h:47
MVertex::getNum
std::size_t getNum() const
Definition: MVertex.h:86
MaxField::MaxField
MaxField()
Definition: Field.cpp:1894
GModel::getFaceByTag
GFace * getFaceByTag(int n) const
Definition: GModel.cpp:326
Field::getDescription
virtual std::string getDescription()
Definition: Field.h:135
SBoundingBox3d::min
SPoint3 min() const
Definition: SBoundingBox3d.h:90
Range::high
T high() const
Definition: Range.h:20
GenericField::~GenericField
~GenericField()
Definition: Field.cpp:3291
GFace::point
virtual GPoint point(double par1, double par2) const =0
GradientField::getDescription
std::string getDescription()
Definition: Field.cpp:712
SVector3
Definition: SVector3.h:16
MeanField::getDescription
std::string getDescription()
Definition: Field.cpp:936
scalProd
double scalProd(double a[3], double b[3])
Definition: Numeric.h:100
RestrictField::getName
const char * getName()
Definition: Field.cpp:2019
intersection
SMetric3 intersection(const SMetric3 &m1, const SMetric3 &m2)
Definition: STensor3.cpp:119
BoundaryLayerField::getDescription
virtual std::string getDescription()
Definition: Field.cpp:2761
FieldManager::~FieldManager
~FieldManager()
Definition: Field.cpp:3217
GenericField::operator()
virtual double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:3293
BoundaryLayerField::removeAttractors
void removeAttractors()
Definition: Field.cpp:2850
GenericField::cbs_with_data
std::vector< std::pair< ptrfunction, void * > > cbs_with_data
Definition: Field.h:470
OctreeField::_inField
Field * _inField
Definition: Field.cpp:2362
DistanceField::DistanceField
DistanceField()
Definition: Field.cpp:2459
PView.h
BoxField::_yMin
double _yMin
Definition: Field.cpp:328
GradientField
Definition: Field.cpp:705
GModelIO_GEO.h
BallField::getName
const char * getName()
Definition: Field.cpp:507
IntersectAnisoField::IntersectAnisoField
IntersectAnisoField()
Definition: Field.cpp:1775
ExtendField::_pc2kdtreeSurfaces
SPoint3CloudAdaptor< SPoint3Cloud > _pc2kdtreeSurfaces
Definition: Field.cpp:2608
OctreeField::OctreeField
OctreeField()
Definition: Field.cpp:2367
GEdge::length
double length() const
Definition: GEdge.h:170
ParametricField::_expr
MathEvalExpression _expr[3]
Definition: Field.cpp:1499
StructuredField::_data
double * _data
Definition: Field.cpp:134
BallField::_xc
double _xc
Definition: Field.cpp:477
Field::numComponents
virtual int numComponents() const
Definition: Field.h:114
BoundaryLayerField::computeFor1dMesh
void computeFor1dMesh(double x, double y, double z, SMetric3 &metr)
Definition: Field.cpp:2997
LonLatField
Definition: Field.cpp:273
FrustumField::_v1o
double _v1o
Definition: Field.cpp:530
PViewData::hasModel
virtual bool hasModel(GModel *model, int step=-1)
Definition: PViewData.h:217
ConstantField::ConstantField
ConstantField()
Definition: Field.cpp:2029
GModel::getEdgeByTag
GEdge * getEdgeByTag(int n) const
Definition: GModel.cpp:336
MinAnisoField::getName
const char * getName()
Definition: Field.cpp:1767
GmshMessage.h
ThresholdField::_dMax
double _dMax
Definition: Field.cpp:631
BoundaryLayerField::_curveTagsSaved
std::list< int > _curveTagsSaved
Definition: Field.h:196
MAX_LC
#define MAX_LC
Definition: GEntity.h:19
ThresholdField::getName
virtual const char * getName()
Definition: Field.cpp:635
FrustumField::_r1i
double _r1i
Definition: Field.cpp:529
LonLatField::getName
const char * getName()
Definition: Field.cpp:303
MathEvalField::_f
std::string _f
Definition: Field.cpp:1141
PViewData::getNumEntities
virtual int getNumEntities(int step=-1)
Definition: PViewData.h:127
RestrictField::_volumeTags
std::list< int > _volumeTags
Definition: Field.cpp:1941
PViewData.h
ParametricField
Definition: Field.cpp:1497
DistanceField::getName
const char * getName()
Definition: Field.cpp:2509
CylinderField::_xc
double _xc
Definition: Field.cpp:418
ConstantField::_surfaceTags
std::list< int > _surfaceTags
Definition: Field.cpp:2026
GEntity
Definition: GEntity.h:31
MaxEigenHessianField::_inField
int _inField
Definition: Field.cpp:829
GPoint
Definition: GPoint.h:13
BoxField::_yMax
double _yMax
Definition: Field.cpp:328
FrustumField::FrustumField
FrustumField()
Definition: Field.cpp:548
GradientField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:736
CylinderField::_xa
double _xa
Definition: Field.cpp:419
LonLatField::_fromStereo
int _fromStereo
Definition: Field.cpp:275
MathEvalExpressionAniso::_f
mathEvaluator * _f[6]
Definition: Field.cpp:1053
FieldManager::_backgroundField
int _backgroundField
Definition: Field.h:147
OctreeField::~OctreeField
~OctreeField()
Definition: Field.cpp:2375
BoundaryLayerField::_hWallNNodes
std::list< double > _hWallNNodes
Definition: Field.h:194
BoundaryLayerField::_curveTags
std::list< int > _curveTags
Definition: Field.h:195
BoundaryLayerField::_pointTags
std::list< int > _pointTags
Definition: Field.h:195
CylinderField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:456
StructuredField::_outsideValueSet
bool _outsideValueSet
Definition: Field.cpp:136
GradientField::_delta
double _delta
Definition: Field.cpp:708
contextMeshOptions::lcMax
double lcMax
Definition: Context.h:25
FieldOptionBool
Definition: Field.h:402
ThresholdField::_dMin
double _dMin
Definition: Field.cpp:631
MathEvalExpression::_fields
std::set< int > _fields
Definition: Field.cpp:978
PViewData::searchScalarClosest
bool searchScalarClosest(double x, double y, double z, double &distance, double *values, int step=-1, double *size=nullptr, int qn=0, double *qx=nullptr, double *qy=nullptr, double *qz=nullptr, bool grad=false, int dim=-1)
Definition: PViewData.cpp:338
ExternalProcessField::getName
const char * getName()
Definition: Field.cpp:1426
FrustumField::_v2o
double _v2o
Definition: Field.cpp:530
BoundaryLayerField::BoundaryLayerField
BoundaryLayerField()
Definition: Field.cpp:2766
PView::setChanged
void setChanged(bool val)
Definition: PView.cpp:241
OctreeField
Definition: Field.cpp:2257
MeanField::getName
const char * getName()
Definition: Field.cpp:935
BoxField::computeDistance
double computeDistance(double xp, double yp, double zp)
Definition: Field.cpp:365
ThresholdField
Definition: Field.cpp:628
GPoint::z
double z() const
Definition: GPoint.h:23
BallField::_zc
double _zc
Definition: Field.cpp:477
MathEvalField::getName
const char * getName()
Definition: Field.cpp:1166
FieldManager::initialize
void initialize()
Definition: Field.cpp:3211
BoundaryLayerField::_fanPointTags
std::list< int > _fanPointTags
Definition: Field.h:196
MathEvalExpression
Definition: Field.cpp:975
CTX::instance
static CTX * instance()
Definition: Context.cpp:122
SPoint3KDTree
nanoflann::KDTreeSingleIndexAdaptor< nanoflann::L2_Simple_Adaptor< double, SPoint3CloudAdaptor< SPoint3Cloud > >, SPoint3CloudAdaptor< SPoint3Cloud >, 3 > SPoint3KDTree
Definition: SPoint3KDTree.h:46
SPoint3::x
double x(void) const
Definition: SPoint3.h:125
ExtendField::_power
double _power
Definition: Field.cpp:2610
fullMatrix< double >
LegendrePolynomials::fc
void fc(int n, double u, double *val)
Definition: orthogonalBasis.cpp:92
ConstantField::getName
const char * getName()
Definition: Field.cpp:2086
contextMeshOptions::smoothRatio
double smoothRatio
Definition: Context.h:26
MeanField::MeanField
MeanField()
Definition: Field.cpp:945
CurvatureField::_inField
int _inField
Definition: Field.cpp:772
MinField::getName
const char * getName()
Definition: Field.cpp:1885
nanoflann::KDTreeSingleIndexAdaptor::buildIndex
void buildIndex()
Definition: nanoflann.hpp:863
GEdge::firstDer
virtual SVector3 firstDer(double par) const =0
PointCloud
Definition: Field.cpp:2416
GModel::bounds
SBoundingBox3d bounds(bool aroundVisible=false)
Definition: GModel.cpp:1043
BoundaryLayerField::setupFor1d
void setupFor1d(int iE)
Definition: Field.cpp:2857
MathEvalExpression::_f
mathEvaluator * _f
Definition: Field.cpp:977
Field::getOption
FieldOption * getOption(const std::string &optionName)
Definition: Field.cpp:58
FieldManager::deleteField
void deleteField(int id)
Definition: Field.cpp:118
ConstantField::_vOut
double _vOut
Definition: Field.cpp:2024
ConstantField::_curveTags
std::list< int > _curveTags
Definition: Field.cpp:2026
Range
Definition: Range.h:10
MathEvalExpressionAniso::~MathEvalExpressionAniso
~MathEvalExpressionAniso()
Definition: Field.cpp:1061
ExtendField::getDescription
std::string getDescription()
Definition: Field.cpp:2636
MaxEigenHessianField
Definition: Field.cpp:827
AttractorInfo::v
double v
Definition: Field.cpp:2095
CurvatureField::getName
const char * getName()
Definition: Field.cpp:776
PView::getViewByTag
static PView * getViewByTag(int tag, int timeStep=-1, int partition=-1)
Definition: PView.cpp:376
LaplacianField::_inField
int _inField
Definition: Field.cpp:887
MathEvalFieldAniso::getName
const char * getName()
Definition: Field.cpp:1251
IntersectAnisoField
Definition: Field.cpp:1770
AttractorInfo::dim
int dim
Definition: Field.cpp:2094
RestrictField::_surfaceTags
std::list< int > _surfaceTags
Definition: Field.cpp:1941
GEntity::mesh_vertices
std::vector< MVertex * > mesh_vertices
Definition: GEntity.h:56
MathEvalFieldAniso::operator()
void operator()(double x, double y, double z, SMetric3 &metr, GEntity *ge=nullptr)
Definition: Field.cpp:1218
RestrictField::RestrictField
RestrictField()
Definition: Field.cpp:1944
MathEvalExpressionAniso::set_function
bool set_function(int iFunction, const std::string &f)
Definition: Field.cpp:1066
MaxEigenHessianField::_delta
double _delta
Definition: Field.cpp:830
ExtendField::getName
const char * getName()
Definition: Field.cpp:2635
input
static int input(void)
FrustumField::getDescription
std::string getDescription()
Definition: Field.cpp:533
FieldManager::newId
int newId()
Definition: Field.cpp:98
EXTRUDED_ENTITY
#define EXTRUDED_ENTITY
Definition: ExtrudeParams.h:17
GVertex
Definition: GVertex.h:23
BoxField
Definition: Field.cpp:326
nanoflann::SearchParams
Definition: nanoflann.hpp:419
AttractorInfo::u
double u
Definition: Field.cpp:2095
ConstantField
Definition: Field.cpp:2022
BoundaryLayerField::setupFor2d
bool setupFor2d(int iF)
Definition: Field.cpp:2893
CTX::lc
double lc
Definition: Context.h:234
RestrictField::_inField
int _inField
Definition: Field.cpp:1939
MVertex.h
FieldOptionList
Definition: Field.h:335
BoxField::_vIn
double _vIn
Definition: Field.cpp:328
SPoint3Cloud::pts
std::vector< SPoint3 > pts
Definition: SPoint3KDTree.h:13
MathEvalField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:1151
ExtendField::_tagSurfaces
std::list< int > _tagSurfaces
Definition: Field.cpp:2605
FrustumField::_x2
double _x2
Definition: Field.cpp:528
OctreeField::operator()
virtual double operator()(double X, double Y, double Z, GEntity *ge=nullptr)
Definition: Field.cpp:2407
GradientField::getName
const char * getName()
Definition: Field.cpp:711
AttractorInfo::AttractorInfo
AttractorInfo(int a=0, int b=0, double c=0, double d=0)
Definition: Field.cpp:2090
Numeric.h
FieldManager::get
Field * get(int id)
Definition: Field.cpp:74
SPoint3CloudAdaptor< SPoint3Cloud >
BoundaryLayerField::nb_divisions
int nb_divisions
Definition: Field.h:206
MathEvalFieldAniso::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:1234
DistanceField::_xFieldId
int _xFieldId
Definition: Field.cpp:2452
ExternalProcessField::~ExternalProcessField
~ExternalProcessField()
Definition: Field.cpp:1409
FieldManager::mapTypeName
std::map< std::string, FieldFactory * > mapTypeName
Definition: Field.h:151
ConstantField::_vIn
double _vIn
Definition: Field.cpp:2024
LonLatField::LonLatField
LonLatField()
Definition: Field.cpp:285
PView::getData
PViewData * getData(bool useAdaptiveIfAvailable=false)
Definition: PView.cpp:233
BallField
Definition: Field.cpp:474
StructuredField::_n
int _n[3]
Definition: Field.cpp:133
LonLatField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:305
MathEvalFieldAniso::_expr
MathEvalExpressionAniso _expr
Definition: Field.cpp:1177
MaxField
Definition: Field.cpp:1888
BoundaryLayerField::thickness
double thickness
Definition: Field.h:204
automaticMeshSizeField.h
DistanceField::_pointTags
std::list< int > _pointTags
Definition: Field.cpp:2449
StructuredField::_o
double _o[3]
Definition: Field.cpp:132
BoxField::BoxField
BoxField()
Definition: Field.cpp:341
BoundaryLayerField::_excludedSurfaceTags
std::list< int > _excludedSurfaceTags
Definition: Field.h:197
GEdge::getBeginVertex
virtual GVertex * getBeginVertex() const
Definition: GEdge.h:63
nanoflann::KNNResultSet::init
void init(IndexType *indices_, DistanceType *dists_)
Definition: nanoflann.hpp:90
PViewData::destroyAdaptiveData
void destroyAdaptiveData()
Definition: PViewData.cpp:79
BallField::_r
double _r
Definition: Field.cpp:478
ExtrudeParams.h
FrustumField::_v1i
double _v1i
Definition: Field.cpp:530
CylinderField::_yc
double _yc
Definition: Field.cpp:418
StructuredField::_textFormat
bool _textFormat
Definition: Field.cpp:136
RestrictField::getDescription
std::string getDescription()
Definition: Field.cpp:1969
LonLatField::_stereoRadius
double _stereoRadius
Definition: Field.cpp:276
CylinderField::_za
double _za
Definition: Field.cpp:419
FieldOptionInt
Definition: Field.h:312
FALSE
#define FALSE
Definition: gl2gif.cpp:555
AttractorInfo
Definition: Field.cpp:2089
MaxEigenHessianField::getDescription
std::string getDescription()
Definition: Field.cpp:834
PViewData::getNumNodes
virtual int getNumNodes(int step, int ent, int ele)
Definition: PViewData.h:137
SPoint3::y
double y(void) const
Definition: SPoint3.h:127
IntersectAnisoField::operator()
virtual void operator()(double x, double y, double z, SMetric3 &metr, GEntity *ge=nullptr)
Definition: Field.cpp:1786
TRUE
#define TRUE
Definition: gl2gif.cpp:554
intersection_conserve_mostaniso
SMetric3 intersection_conserve_mostaniso(const SMetric3 &m1, const SMetric3 &m2)
Definition: STensor3.cpp:216
MathEvalExpression::~MathEvalExpression
~MathEvalExpression()
Definition: Field.cpp:982
PointCloudAdaptor::kdtree_get_bbox
bool kdtree_get_bbox(BBOX &) const
Definition: Field.cpp:2442
ParametricField::getDescription
std::string getDescription()
Definition: Field.cpp:1520
FieldOptionDouble
Definition: Field.h:288
PointCloudAdaptor::kdtree_get_point_count
size_t kdtree_get_point_count() const
Definition: Field.cpp:2424
PViewData::setName
virtual void setName(const std::string &val)
Definition: PViewData.h:71
CTX::mesh
contextMeshOptions mesh
Definition: Context.h:313
PointCloudAdaptor::kdtree_distance
double kdtree_distance(const double *p1, const size_t idx_p2, size_t) const
Definition: Field.cpp:2425
ConstantField::_boundary
bool _boundary
Definition: Field.cpp:2025
RestrictField::_pointTags
std::list< int > _pointTags
Definition: Field.cpp:1941
BallField::_yc
double _yc
Definition: Field.cpp:477
GModel::getFields
FieldManager * getFields()
Definition: GModel.h:325
PointCloud::pts
std::vector< SPoint3 > pts
Definition: Field.cpp:2417
ExternalProcessField::_cmdLine
std::string _cmdLine
Definition: Field.cpp:1388
FieldManager::maxId
int maxId()
Definition: Field.cpp:110
ExtendField::_tagCurves
std::list< int > _tagCurves
Definition: Field.cpp:2605
SPoint3Cloud
Definition: SPoint3KDTree.h:12
ExtendField::_sizeCurves
std::vector< double > _sizeCurves
Definition: Field.cpp:2606
MathEvalFieldAniso::MathEvalFieldAniso
MathEvalFieldAniso()
Definition: Field.cpp:1182
GEntity::tag
int tag() const
Definition: GEntity.h:280
DistanceField::_infos
std::vector< AttractorInfo > _infos
Definition: Field.cpp:2450
PointCloudAdaptor
Definition: Field.cpp:2420
FrustumField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:601
ParametricField::getName
const char * getName()
Definition: Field.cpp:1547
FrustumField::_r2o
double _r2o
Definition: Field.cpp:529
Field
Definition: Field.h:103
LaplacianField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:913
MinAnisoField::getDescription
std::string getDescription()
Definition: Field.cpp:1719
FieldManager::FieldManager
FieldManager()
Definition: Field.cpp:3170
BoundaryLayerField::iIntersect
int iIntersect
Definition: Field.h:206
FieldManager::setBackgroundMesh
void setBackgroundMesh(int iView)
Definition: Field.cpp:3280
BoundaryLayerField::iRecombine
int iRecombine
Definition: Field.h:206
OctreeField::_inFieldId
int _inFieldId
Definition: Field.cpp:2361
SVector3::x
double x(void) const
Definition: SVector3.h:30
BoundaryLayerField::_attFields
std::list< DistanceField * > _attFields
Definition: Field.h:193
GModel::getEntities
void getEntities(std::vector< GEntity * > &entities, int dim=-1) const
Definition: GModel.cpp:651
DistanceField::_pc2kdtree
SPoint3CloudAdaptor< SPoint3Cloud > _pc2kdtree
Definition: Field.cpp:2454
ParametricField::_f
std::string _f[3]
Definition: Field.cpp:1500
MinField::getDescription
std::string getDescription()
Definition: Field.cpp:1850
ExternalProcessField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:1411
LonLatField::getDescription
std::string getDescription()
Definition: Field.cpp:279
DistanceField::update
void update()
Definition: Field.cpp:2523
LaplacianField::getDescription
std::string getDescription()
Definition: Field.cpp:892
BoxField::getName
const char * getName()
Definition: Field.cpp:363
IntersectAnisoField::_fieldIds
std::list< int > _fieldIds
Definition: Field.cpp:1772
RestrictField::_curveTags
std::list< int > _curveTags
Definition: Field.cpp:1941
S
#define S
Definition: DefaultOptions.h:21
PViewData::getNumVectors
virtual int getNumVectors(int step=-1)
Definition: PViewData.h:112
ExternalProcessField
Definition: Field.cpp:1386
IntersectAnisoField::isotropic
virtual bool isotropic() const
Definition: Field.cpp:1780
PViewData
Definition: PViewData.h:29
DistanceField::_curveTags
std::list< int > _curveTags
Definition: Field.cpp:2449
GenericField::cbs_extended_with_data
std::vector< std::pair< ptrfunctionextended, void * > > cbs_extended_with_data
Definition: Field.h:472
MaxField::getDescription
std::string getDescription()
Definition: Field.cpp:1899
MathEvalField::getDescription
std::string getDescription()
Definition: Field.cpp:1167
DistanceField::_pc
SPoint3Cloud _pc
Definition: Field.cpp:2453
ExternalProcessField::closePipes
void closePipes()
Definition: Field.cpp:1390
GVertex::x
virtual double x() const =0
FieldOptionPath
Definition: Field.h:392
nanoflann::KDTreeSingleIndexAdaptorParams
Definition: nanoflann.hpp:409
BoxField::_xMin
double _xMin
Definition: Field.cpp:328
OctreeField::Cell::_data
void * _data
Definition: Field.cpp:2262
GEdge::curvature
virtual double curvature(double par) const
Definition: GEdge.cpp:492
ExternalProcessField::ExternalProcessField
ExternalProcessField()
Definition: Field.cpp:1402
ExtendField::_sizeSurfaces
std::vector< double > _sizeSurfaces
Definition: Field.cpp:2606
PointCloudAdaptor::PointCloudAdaptor
PointCloudAdaptor(const Derived &obj_)
Definition: Field.cpp:2422
BoxField::_thick
double _thick
Definition: Field.cpp:328
ExtendField::_sizeMax
double _sizeMax
Definition: Field.cpp:2610
GVertex::y
virtual double y() const =0
MinField::_fieldIds
std::list< int > _fieldIds
Definition: Field.cpp:1841
BallField::_vOut
double _vOut
Definition: Field.cpp:476
BoundaryLayerField::betaLaw
int betaLaw
Definition: Field.h:206
ThresholdField::_lcMax
double _lcMax
Definition: Field.cpp:631
Field::getName
virtual const char * getName()=0
MathEvalExpression::set_function
bool set_function(const std::string &f)
Definition: Field.cpp:986
FrustumField
Definition: Field.cpp:525
BoxField::getDescription
std::string getDescription()
Definition: Field.cpp:331
FrustumField::_y1
double _y1
Definition: Field.cpp:527
OctreeField::Cell::init
void init(double x0, double y0, double z0, double l, Field &field, int level)
Definition: Field.cpp:2276
LonLatField::_inField
int _inField
Definition: Field.cpp:275
Context.h
StructuredField::StructuredField
StructuredField()
Definition: Field.cpp:141
ExtendField::operator()
virtual double operator()(double X, double Y, double Z, GEntity *ge=nullptr)
Definition: Field.cpp:2703
MathEvalExpression::evaluate
double evaluate(double x, double y, double z)
Definition: Field.cpp:1026
LaplacianField::_delta
double _delta
Definition: Field.cpp:888
Popen2::read
bool read(void *data, size_t size)
Definition: Field.cpp:1374
Field::options
std::map< std::string, FieldOption * > options
Definition: Field.h:112
FrustumField::_y2
double _y2
Definition: Field.cpp:528
PViewData::getNumComponents
virtual int getNumComponents(int step, int ent, int ele)
Definition: PViewData.h:152
GEdge::parBounds
virtual Range< double > parBounds(int i) const =0
DistanceField::~DistanceField
~DistanceField()
Definition: Field.cpp:2505
CylinderField
Definition: Field.cpp:415
PViewData::getNumTensors
virtual int getNumTensors(int step=-1)
Definition: PViewData.h:113
FrustumField::_r2i
double _r2i
Definition: Field.cpp:529
SVector3::y
double y(void) const
Definition: SVector3.h:31
StructuredField::_d
double _d[3]
Definition: Field.cpp:132
GFace::embeddedEdges
std::vector< GEdge * > & embeddedEdges()
Definition: GFace.h:156
z
const double z
Definition: GaussQuadratureQuad.cpp:56
ParametricField::ParametricField
ParametricField()
Definition: Field.cpp:1504
Field::id
int id
Definition: Field.h:111
CurvatureField::grad_norm
void grad_norm(Field &f, double x, double y, double z, double *g)
Definition: Field.cpp:795
NSAMPLE
#define NSAMPLE
DistanceField::DistanceField
DistanceField(int dim, int tag, int nbe)
Definition: Field.cpp:2493
BoxField::_vOut
double _vOut
Definition: Field.cpp:328
CurvatureField::_delta
double _delta
Definition: Field.cpp:773
contextMeshOptions::lcFactor
double lcFactor
Definition: Context.h:21
MaxField::_fieldIds
std::list< int > _fieldIds
Definition: Field.cpp:1890
RestrictField::_boundary
bool _boundary
Definition: Field.cpp:1940
ExtendField::recomputeSurfaces
void recomputeSurfaces()
Definition: Field.cpp:2674
DistanceField::_outIndex
std::size_t _outIndex
Definition: Field.cpp:2456
DistanceField::getDescription
std::string getDescription()
Definition: Field.cpp:2510
Popen2::_fdOut
int _fdOut
Definition: Field.cpp:1340
GEdge::point
virtual GPoint point(double p) const =0
OctreeField::update
void update()
Definition: Field.cpp:2384
MathEvalFieldAniso::getDescription
std::string getDescription()
Definition: Field.cpp:1252
BoundaryLayerField::_fanSizes
std::list< int > _fanSizes
Definition: Field.h:198
OctreeField::Cell::_isleaf
bool _isleaf
Definition: Field.cpp:2263
STensor3.h
GEdge
Definition: GEdge.h:26
SVector3::z
double z(void) const
Definition: SVector3.h:32
AttractorInfo::ent
int ent
Definition: Field.cpp:2094
CylinderField::_vIn
double _vIn
Definition: Field.cpp:417
MathEvalExpressionAniso::_fields
std::set< int > _fields[6]
Definition: Field.cpp:1054
OctreeField::Cell::Cell
Cell()
Definition: Field.cpp:2275
MathEvalFieldAniso
Definition: Field.cpp:1175
MeanField
Definition: Field.cpp:929
Field::putOnNewView
void putOnNewView(int viewTag=-1)
Definition: Field.cpp:3231
BallField::_vIn
double _vIn
Definition: Field.cpp:476
StructuredField::~StructuredField
virtual ~StructuredField()
Definition: Field.cpp:181
MaxEigenHessianField::getName
const char * getName()
Definition: Field.cpp:833
DistanceField::getAttractorInfo
std::pair< AttractorInfo, SPoint3 > getAttractorInfo() const
Definition: Field.cpp:2517
Field::update
virtual void update()
Definition: Field.h:110
ConstantField::_volumeTags
std::list< int > _volumeTags
Definition: Field.cpp:2026
FrustumField::getName
const char * getName()
Definition: Field.cpp:599
eigenvalue
void eigenvalue(double mat[3][3], double v[3])
Definition: Numeric.cpp:550
ExtendField::ExtendField
ExtendField()
Definition: Field.cpp:2612
nanoflann::KNNResultSet
Definition: nanoflann.hpp:79
ThresholdField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:681
LaplacianField
Definition: Field.cpp:885
MaxEigenHessianField::MaxEigenHessianField
MaxEigenHessianField()
Definition: Field.cpp:841
SPoint3::z
double z(void) const
Definition: SPoint3.h:129
Field::operator()
virtual double operator()(double x, double y, double z, GEntity *ge=nullptr)=0
BoxField::_xMax
double _xMax
Definition: Field.cpp:328
PViewData::getNumElements
virtual int getNumElements(int step=-1, int ent=-1)
Definition: PViewData.h:131
BackgroundMeshTools.h
PViewData::searchTensorClosest
bool searchTensorClosest(double x, double y, double z, double &distance, double *values, int step=-1, double *size=nullptr, int qn=0, double *qx=nullptr, double *qy=nullptr, double *qz=nullptr, bool grad=false, int dim=-1)
Definition: PViewData.cpp:418
CylinderField::_vOut
double _vOut
Definition: Field.cpp:417
MeanField::_delta
double _delta
Definition: Field.cpp:932
GModel.h
MinAnisoField::operator()
virtual void operator()(double x, double y, double z, SMetric3 &metr, GEntity *ge=nullptr)
Definition: Field.cpp:1723
ExtendField::recomputeCurves
void recomputeCurves()
Definition: Field.cpp:2648
BoundaryLayerField::currentDistance
double currentDistance
Definition: Field.h:205
intersection_alauzet
SMetric3 intersection_alauzet(const SMetric3 &m1, const SMetric3 &m2)
Definition: STensor3.cpp:146
MinField
Definition: Field.cpp:1839
MVertex::y
double y() const
Definition: MVertex.h:61
BoxField::_zMin
double _zMin
Definition: Field.cpp:328
StructuredField
Definition: Field.cpp:130
OctreeField::Cell::~Cell
~Cell()
Definition: Field.cpp:2332
Popen2::_fdIn
int _fdIn
Definition: Field.cpp:1340
MathEvalField::MathEvalField
MathEvalField()
Definition: Field.cpp:1144
GEdge::getEndVertex
virtual GVertex * getEndVertex() const
Definition: GEdge.h:64
IntersectAnisoField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:1811
nanoflann::KDTreeSingleIndexAdaptor
Definition: nanoflann.hpp:746
intersection_conserveM1
SMetric3 intersection_conserveM1(const SMetric3 &m1, const SMetric3 &m2)
Definition: STensor3.cpp:164
CylinderField::getDescription
std::string getDescription()
Definition: Field.cpp:423
ExtendField
Definition: Field.cpp:2604
Range::low
T low() const
Definition: Range.h:18
FieldOptionListDouble
Definition: Field.h:363
ExtendField::~ExtendField
~ExtendField()
Definition: Field.cpp:2630
BoxField::_zMax
double _zMax
Definition: Field.cpp:328
DistanceField::_zFieldId
int _zFieldId
Definition: Field.cpp:2452
FrustumField::_z2
double _z2
Definition: Field.cpp:528
MaxEigenHessianField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:855
OctreeField::getDescription
std::string getDescription()
Definition: Field.cpp:2380
PView::list
static std::vector< PView * > list
Definition: PView.h:112
GEO_Internals::synchronize
void synchronize(GModel *model, bool resetMeshAttributes=true)
Definition: GModelIO_GEO.cpp:1370
FieldManager::newField
Field * newField(int id, const std::string &type_name)
Definition: Field.cpp:81
BoundaryLayerField::operator()
void operator()(DistanceField *cc, double dist, double x, double y, double z, SMetric3 &metr, GEntity *ge)
Definition: Field.cpp:3033
SBoundingBox3d::max
SPoint3 max() const
Definition: SBoundingBox3d.h:91
GModel::getVertexByTag
GVertex * getVertexByTag(int n) const
Definition: GModel.cpp:346
GradientField::_inField
int _inField
Definition: Field.cpp:707
BoundaryLayerField::ratio
double ratio
Definition: Field.h:204
GModel::getGEOInternals
GEO_Internals * getGEOInternals()
Definition: GModel.h:315
ThresholdField::_inField
int _inField
Definition: Field.cpp:630
LaplacianField::getName
const char * getName()
Definition: Field.cpp:891
GPoint::x
double x() const
Definition: GPoint.h:21
FrustumField::_x1
double _x1
Definition: Field.cpp:527
BoundaryLayerField::hWallN
double hWallN
Definition: Field.h:204
BallField::_thick
double _thick
Definition: Field.cpp:478
MathEvalField
Definition: Field.cpp:1138
MaxField::getName
const char * getName()
Definition: Field.cpp:1934
GFace::curvatures
virtual double curvatures(const SPoint2 &param, SVector3 &dirMax, SVector3 &dirMin, double &curvMax, double &curvMin) const
Definition: GFace.cpp:1031
BoundaryLayerField::tgtAnisoRatio
double tgtAnisoRatio
Definition: Field.h:205
DistanceField
Definition: Field.cpp:2448
SBoundingBox3d
Definition: SBoundingBox3d.h:21
PViewData::finalize
virtual bool finalize(bool computeMinMax=true, const std::string &interpolationScheme="")
Definition: PViewData.cpp:30
MinAnisoField::isotropic
virtual bool isotropic() const
Definition: Field.cpp:1718
ThresholdField::_sigmoid
bool _sigmoid
Definition: Field.cpp:632
IntersectAnisoField::getDescription
std::string getDescription()
Definition: Field.cpp:1781
fullMatrix.h
MinField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:1855
MinAnisoField
Definition: Field.cpp:1708
FrustumField::_r1o
double _r1o
Definition: Field.cpp:529
StructuredField::operator()
double operator()(double x, double y, double z, GEntity *ge=nullptr)
Definition: Field.cpp:186
PointCloudAdaptor::kdtree_get_pt
double kdtree_get_pt(const size_t idx, int dim) const
Definition: Field.cpp:2433
BoundaryLayerField::beta
double beta
Definition: Field.h:205
GModel::current
static GModel * current(int index=-1)
Definition: GModel.cpp:136
MathEvalFieldAniso::isotropic
virtual bool isotropic() const
Definition: Field.cpp:1181
OctreeField::Cell::evaluate
double evaluate(double x, double y, double z) const
Definition: Field.cpp:2266
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
StructuredField::_outsideValue
double _outsideValue
Definition: Field.cpp:137
MVertex::x
double x() const
Definition: MVertex.h:60
StructuredField::getName
const char * getName()
Definition: Field.cpp:180
SVector3::normalize
double normalize()
Definition: SVector3.h:38
Popen2::Popen2
Popen2()
Definition: Field.cpp:1343
FieldManager::setBackgroundField
void setBackgroundField(Field *BGF)
Definition: Field.cpp:3224
DistanceField::_sampling
int _sampling
Definition: Field.cpp:2451
OctreeField::_l0
double _l0
Definition: Field.cpp:2364
FieldOption
Definition: Field.h:50
GenericField::GenericField
GenericField()
Definition: Field.cpp:3289
Field::updateNeeded
bool updateNeeded
Definition: Field.h:129