1 // Gmsh - Copyright (C) 1997-2021 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 #ifndef FIELD_H
7 #define FIELD_H
8 
9 #include <string>
10 #include <map>
11 #include <vector>
12 #include <list>
13 #include "GmshConfig.h"
14 #include "Context.h"
15 #include "STensor3.h"
16 #include <fstream>
17 #include <string>
18 #include <string.h>
19 #include <sstream>
20 #include <algorithm>
21 
22 #if defined(HAVE_POST)
23 class PView;
24 #endif
25 
26 class Field;
27 class GEntity;
28 
29 typedef enum {
30   FIELD_OPTION_DOUBLE = 0,
31   FIELD_OPTION_INT,
32   FIELD_OPTION_STRING,
33   FIELD_OPTION_PATH,
34   FIELD_OPTION_BOOL,
35   FIELD_OPTION_LIST,
36   FIELD_OPTION_LIST_DOUBLE
37 } FieldOptionType;
38 
39 class FieldCallback {
40 private:
41   std::string _help;
42 
43 public:
44   virtual void run() = 0;
FieldCallback(const std::string & help)45   FieldCallback(const std::string &help) { _help = help; }
~FieldCallback()46   virtual ~FieldCallback(){};
getDescription()47   virtual std::string getDescription() { return _help; }
48 };
49 
50 class FieldOption {
51 private:
52   std::string _help;
53   bool _deprecated;
54 
55 protected:
56   bool *status;
modified()57   inline void modified()
58   {
59     if(status) *status = true;
60   }
61 
62 public:
FieldOption(const std::string & help,bool * _status,bool deprecated)63   FieldOption(const std::string &help, bool *_status, bool deprecated)
64     : _help(help), _deprecated(deprecated), status(_status)
65   {
66   }
~FieldOption()67   virtual ~FieldOption() {}
68   virtual FieldOptionType getType() = 0;
69   virtual void getTextRepresentation(std::string &v_str) = 0;
getDescription()70   virtual std::string getDescription() { return _help; }
getTypeName()71   std::string getTypeName()
72   {
73     switch(getType()) {
74     case FIELD_OPTION_INT: return "integer";
75     case FIELD_OPTION_DOUBLE: return "float";
76     case FIELD_OPTION_BOOL: return "boolean";
77     case FIELD_OPTION_PATH: return "path";
78     case FIELD_OPTION_STRING: return "string";
79     case FIELD_OPTION_LIST: return "list";
80     case FIELD_OPTION_LIST_DOUBLE: return "list_double";
81     default: return "unknown";
82     }
83   }
numericalValue(double val)84   virtual void numericalValue(double val) {}
numericalValue()85   virtual double numericalValue() const { return 0.; }
list()86   virtual const std::list<int> &list() const
87   {
88     static std::list<int> l;
89     return l;
90   }
listdouble()91   virtual const std::list<double> &listdouble() const
92   {
93     static std::list<double> l;
94     return l;
95   }
list(std::list<int> value)96   virtual void list(std::list<int> value) {}
listdouble(std::list<double> value)97   virtual void listdouble(std::list<double> value) {}
string()98   virtual std::string string() const { return ""; }
string(const std::string value)99   virtual void string(const std::string value) {}
isDeprecated()100   bool isDeprecated() { return _deprecated; }
101 };
102 
103 class Field {
104 protected:
105   bool _deprecated;
106 public:
Field()107   Field() : _deprecated(false), updateNeeded(false) {}
108   virtual ~Field();
isDeprecated()109   bool isDeprecated() { return _deprecated; }
update()110   virtual void update() {}
111   int id;
112   std::map<std::string, FieldOption *> options;
113   std::map<std::string, FieldCallback *> callbacks;
numComponents()114   virtual int numComponents() const { return 1; }
isotropic()115   virtual bool isotropic() const { return true; }
116   // isotropic
117   virtual double operator()(double x, double y, double z,
118                             GEntity *ge = nullptr) = 0;
119   // vector value
operator()120   virtual void operator()(double x, double y, double z, SVector3 &,
121                           GEntity *ge = 0)
122   {
123   }
124   // anisotropic
operator()125   virtual void operator()(double x, double y, double z, SMetric3 &,
126                           GEntity *ge = nullptr)
127   {
128   }
129   bool updateNeeded;
130   virtual const char *getName() = 0;
131 #if defined(HAVE_POST)
132   void putOnView(PView *view, int comp = -1);
133 #endif
134   void putOnNewView(int viewTag = -1);
getDescription()135   virtual std::string getDescription() { return ""; }
136   FieldOption *getOption(const std::string &optionName);
137 };
138 
139 class FieldFactory {
140 public:
~FieldFactory()141   virtual ~FieldFactory() {}
142   virtual Field *operator()() = 0;
143 };
144 
145 class FieldManager : public std::map<int, Field *> {
146 private:
147   int _backgroundField;
148   std::vector<int> _boundaryLayerFields;
149 
150 public:
151   std::map<std::string, FieldFactory *> mapTypeName;
152   void initialize();
153   void reset();
154   Field *get(int id);
155   Field *newField(int id, const std::string &type_name);
156   void deleteField(int id);
157   int newId();
158   int maxId();
159   FieldManager();
160   ~FieldManager();
161   // compatibility with -bgm
162   void setBackgroundMesh(int iView);
163   // set and get background field
164   void setBackgroundField(Field *BGF);
setBackgroundFieldId(int id)165   inline void setBackgroundFieldId(int id) { _backgroundField = id; };
addBoundaryLayerFieldId(int id)166   inline void addBoundaryLayerFieldId(int id)
167   {
168     for(std::size_t i = 0; i < _boundaryLayerFields.size(); ++i) {
169       if(_boundaryLayerFields[i] == id) return;
170     }
171     _boundaryLayerFields.push_back(id);
172   }
addBoundaryLayerFieldId(std::vector<int> & tags)173   inline void addBoundaryLayerFieldId(std::vector<int> &tags)
174   {
175     for(std::size_t i = 0; i < tags.size(); ++i)
176       addBoundaryLayerFieldId(tags[i]);
177   }
getBackgroundField()178   inline int getBackgroundField() { return _backgroundField; }
getNumBoundaryLayerFields()179   inline int getNumBoundaryLayerFields()
180   {
181     return (int)_boundaryLayerFields.size();
182   }
getBoundaryLayerField(int i)183   inline int getBoundaryLayerField(int i) { return _boundaryLayerFields[i]; }
184 };
185 
186 // Boundary Layer Field (used both for anisotropic meshing and BL
187 // extrusion)
188 
189 class DistanceField;
190 
191 class BoundaryLayerField : public Field {
192 private:
193   std::list<DistanceField *> _attFields;
194   std::list<double> _hWallNNodes;
195   std::list<int> _pointTags, _curveTags;
196   std::list<int> _pointTagsSaved, _curveTagsSaved, _fanPointTags;
197   std::list<int> _excludedSurfaceTags;
198   std::list<int> _fanSizes;
199   SPoint3 _closestPoint;
200   void operator()(DistanceField *cc, double dist, double x, double y, double z,
201                   SMetric3 &metr, GEntity *ge);
202 
203 public:
204   double hWallN, ratio, hFar, thickness;
205   double currentDistance, tgtAnisoRatio, beta;
206   int iRecombine, iIntersect, betaLaw, nb_divisions;
207   DistanceField *currentClosest;
isotropic()208   virtual bool isotropic() const { return false; }
209   virtual const char *getName();
210   virtual std::string getDescription();
211   BoundaryLayerField();
~BoundaryLayerField()212   ~BoundaryLayerField() { removeAttractors(); }
213   virtual double operator()(double x, double y, double z,
214                             GEntity *ge = nullptr);
215   virtual void operator()(double x, double y, double z, SMetric3 &metr,
216                           GEntity *ge = nullptr);
isEdgeBL(int iE)217   bool isEdgeBL(int iE) const
218   {
219     return std::find(_curveTags.begin(), _curveTags.end(), iE) !=
220            _curveTags.end();
221   }
isEdgeBLSaved(int iE)222   bool isEdgeBLSaved(int iE) const
223   {
224     return std::find(_curveTagsSaved.begin(), _curveTagsSaved.end(), iE) !=
225            _curveTagsSaved.end();
226   }
isFanNode(int iV)227   bool isFanNode(int iV) const
228   {
229     return std::find(_fanPointTags.begin(), _fanPointTags.end(), iV) !=
230            _fanPointTags.end();
231   }
fanSize(int iV)232   int fanSize(int iV)
233   {
234     if(_fanPointTags.size() != _fanSizes.size())
235       return CTX::instance()->mesh.boundaryLayerFanElements;
236     auto it1 = _fanPointTags.begin();
237     auto it2 = _fanSizes.begin();
238     for(; it1 != _fanPointTags.end(); ++it1, ++it2) {
239       if(*it1 == iV) return *it2;
240     }
241     return 0;
242   }
243 
isEndNode(int iV)244   bool isEndNode(int iV) const
245   {
246     return std::find(_pointTags.begin(), _pointTags.end(), iV) !=
247            _pointTags.end();
248   }
hWall(int iV)249   double hWall(int iV)
250   {
251     for(auto it = _hWallNNodes.begin(); it != _hWallNNodes.end(); ++it) {
252       int i = (int)*it;
253       ++it;
254       double h = *it;
255       if(i == iV) return h;
256     }
257     return hWallN;
258   }
259   void computeFor1dMesh(double x, double y, double z, SMetric3 &metr);
260   void setupFor1d(int iE);
261   bool setupFor2d(int iF);
262   void removeAttractors();
263 };
264 
265 class FieldOptionString : public FieldOption {
266 public:
267   std::string &val;
getType()268   virtual FieldOptionType getType() { return FIELD_OPTION_STRING; }
269   FieldOptionString(std::string &_val, const std::string &help,
270                     bool *status = nullptr, bool deprecated = false)
FieldOption(help,status,deprecated)271     : FieldOption(help, status, deprecated), val(_val)
272   {
273   }
string(const std::string value)274   void string(const std::string value)
275   {
276     modified();
277     val = value;
278   }
string()279   std::string string() const { return val; }
getTextRepresentation(std::string & v_str)280   void getTextRepresentation(std::string &v_str)
281   {
282     std::ostringstream sstream;
283     sstream << "\"" << val << "\"";
284     v_str = sstream.str();
285   }
286 };
287 
288 class FieldOptionDouble : public FieldOption {
289 public:
290   double &val;
getType()291   FieldOptionType getType() { return FIELD_OPTION_DOUBLE; }
292   FieldOptionDouble(double &_val, const std::string &help,
293                     bool *status = nullptr, bool deprecated = false)
FieldOption(help,status,deprecated)294     : FieldOption(help, status, deprecated), val(_val)
295   {
296   }
numericalValue()297   double numericalValue() const { return val; }
numericalValue(double v)298   void numericalValue(double v)
299   {
300     modified();
301     val = v;
302   }
getTextRepresentation(std::string & v_str)303   void getTextRepresentation(std::string &v_str)
304   {
305     std::ostringstream sstream;
306     sstream.precision(16);
307     sstream << val;
308     v_str = sstream.str();
309   }
310 };
311 
312 class FieldOptionInt : public FieldOption {
313 public:
314   int &val;
getType()315   FieldOptionType getType() { return FIELD_OPTION_INT; }
316   FieldOptionInt(int &_val, const std::string &help, bool *status = nullptr,
317                  bool deprecated = false)
FieldOption(help,status,deprecated)318     : FieldOption(help, status, deprecated), val(_val)
319   {
320   }
numericalValue()321   double numericalValue() const { return val; }
numericalValue(double v)322   void numericalValue(double v)
323   {
324     modified();
325     val = (int)v;
326   }
getTextRepresentation(std::string & v_str)327   void getTextRepresentation(std::string &v_str)
328   {
329     std::ostringstream sstream;
330     sstream << val;
331     v_str = sstream.str();
332   }
333 };
334 
335 class FieldOptionList : public FieldOption {
336 public:
337   std::list<int> &val;
getType()338   FieldOptionType getType() { return FIELD_OPTION_LIST; }
339   FieldOptionList(std::list<int> &_val, const std::string &help,
340                   bool *status = nullptr, bool deprecated = false)
FieldOption(help,status,deprecated)341     : FieldOption(help, status, deprecated), val(_val)
342   {
343   }
list(std::list<int> value)344   void list(std::list<int> value)
345   {
346     modified();
347     val = value;
348   }
list()349   const std::list<int> &list() const { return val; }
getTextRepresentation(std::string & v_str)350   void getTextRepresentation(std::string &v_str)
351   {
352     std::ostringstream sstream;
353     sstream << "{";
354     for(auto it = val.begin(); it != val.end(); it++) {
355       if(it != val.begin()) sstream << ", ";
356       sstream << *it;
357     }
358     sstream << "}";
359     v_str = sstream.str();
360   }
361 };
362 
363 class FieldOptionListDouble : public FieldOption {
364 public:
365   std::list<double> &val;
getType()366   FieldOptionType getType() { return FIELD_OPTION_LIST_DOUBLE; }
367   FieldOptionListDouble(std::list<double> &_val, const std::string &help,
368                         bool *status = nullptr, bool deprecated = false)
FieldOption(help,status,deprecated)369     : FieldOption(help, status, deprecated), val(_val)
370   {
371   }
listdouble(std::list<double> value)372   void listdouble(std::list<double> value)
373   {
374     modified();
375     val = value;
376   }
listdouble()377   const std::list<double> &listdouble() const { return val; }
getTextRepresentation(std::string & v_str)378   void getTextRepresentation(std::string &v_str)
379   {
380     std::ostringstream sstream;
381     sstream.precision(16);
382     sstream << "{";
383     for(auto it = val.begin(); it != val.end(); it++) {
384       if(it != val.begin()) sstream << ", ";
385       sstream << *it;
386     }
387     sstream << "}";
388     v_str = sstream.str();
389   }
390 };
391 
392 class FieldOptionPath : public FieldOptionString {
393 public:
getType()394   virtual FieldOptionType getType() { return FIELD_OPTION_PATH; }
395   FieldOptionPath(std::string &val, const std::string &help,
396                   bool *status = nullptr, bool deprecated = false)
FieldOptionString(val,help,status,deprecated)397     : FieldOptionString(val, help, status, deprecated)
398   {
399   }
400 };
401 
402 class FieldOptionBool : public FieldOption {
403 public:
404   bool &val;
getType()405   FieldOptionType getType() { return FIELD_OPTION_BOOL; }
406   FieldOptionBool(bool &_val, const std::string &help, bool *status = nullptr,
407                   bool deprecated = false)
FieldOption(help,status,deprecated)408     : FieldOption(help, status, deprecated), val(_val)
409   {
410   }
numericalValue()411   double numericalValue() const { return val; }
numericalValue(double v)412   void numericalValue(double v)
413   {
414     modified();
415     val = v;
416   }
getTextRepresentation(std::string & v_str)417   void getTextRepresentation(std::string &v_str)
418   {
419     std::ostringstream sstream;
420     sstream << val;
421     v_str = sstream.str();
422   }
423 };
424 
425 template <class t> class FieldCallbackGeneric : public FieldCallback {
426   t *_field;
427   void (t::*_callback)();
428 
429 public:
run()430   void run() { (_field->*_callback)(); }
FieldCallbackGeneric(t * field,void (t::* callback)(),const std::string description)431   FieldCallbackGeneric(t *field, void (t::*callback)(),
432                        const std::string description)
433     : FieldCallback(description)
434   {
435     _field = field;
436     _callback = callback;
437   }
438 };
439 
440 template <class F> class FieldFactoryT : public FieldFactory {
441 public:
operator()442   Field *operator()() { return new F; }
443 };
444 
445 // the class GenericField contains a set of void* functions, which give a mesh
446 // size All these functions are called when calling operator() ; then, the
447 // minimum size is returned.
448 class GenericField : public Field {
449 public:
450   // callback prototypes:
451   // this callback is called with a void* previously given to the GenericField !
452   typedef bool (*ptrfunction)(double, double, double, void *, double &);
453   // this callback also takes the GEntity object into account
454   typedef bool (*ptrfunctionextended)(double, double, double, void *, void *,
455                                       double &);
456 
457   GenericField();
458   ~GenericField();
459   using Field::operator();
460   virtual double operator()(double x, double y, double z,
461                             GEntity *ge = nullptr);
getName()462   virtual const char *getName() { return "GenericField"; };
463 
464   // sets the callbacks
465   void setCallbackWithData(ptrfunction fct, void *data);
466   void setCallbackWithData(ptrfunctionextended fct, void *data);
467 
468 private:
469   std::vector<std::pair<ptrfunction, void *> >
470     cbs_with_data; // the callbacks with the data to be sent to them
471   std::vector<std::pair<ptrfunctionextended, void *> >
472     cbs_extended_with_data; // the extended callbacks with the data to be sent
473                             // to them
474 };
475 
476 #endif
477