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 #include <sstream>
7 #include "GmshConfig.h"
8 #include "GmshDefines.h"
9 #include "GmshGlobal.h"
10 #include "MallocUtils.h"
11 #include "GModel.h"
12 #include "GModelIO_GEO.h"
13 #include "GModelIO_OCC.h"
14 #include "GVertex.h"
15 #include "GEdge.h"
16 #include "GFace.h"
17 #include "GRegion.h"
18 #include "discreteVertex.h"
19 #include "discreteEdge.h"
20 #include "discreteFace.h"
21 #include "discreteRegion.h"
22 #include "partitionVertex.h"
23 #include "partitionEdge.h"
24 #include "partitionFace.h"
25 #include "partitionRegion.h"
26 #include "ghostEdge.h"
27 #include "ghostFace.h"
28 #include "ghostRegion.h"
29 #include "MVertex.h"
30 #include "MPoint.h"
31 #include "MLine.h"
32 #include "MTriangle.h"
33 #include "MQuadrangle.h"
34 #include "MTetrahedron.h"
35 #include "MHexahedron.h"
36 #include "MPrism.h"
37 #include "MPyramid.h"
38 #include "ExtrudeParams.h"
39 #include "StringUtils.h"
40 #include "Context.h"
41 #include "polynomialBasis.h"
42 #include "pyramidalBasis.h"
43 #include "Numeric.h"
44 #include "OS.h"
45 #include "HierarchicalBasisH1Quad.h"
46 #include "HierarchicalBasisH1Tria.h"
47 #include "HierarchicalBasisH1Line.h"
48 #include "HierarchicalBasisH1Brick.h"
49 #include "HierarchicalBasisH1Tetra.h"
50 #include "HierarchicalBasisH1Pri.h"
51 #include "HierarchicalBasisH1Point.h"
52 #include "HierarchicalBasisHcurlLine.h"
53 #include "HierarchicalBasisHcurlQuad.h"
54 #include "HierarchicalBasisHcurlBrick.h"
55 #include "HierarchicalBasisHcurlTria.h"
56 #include "HierarchicalBasisHcurlTetra.h"
57 #include "HierarchicalBasisHcurlPri.h"
58
59 #if defined(HAVE_MESH)
60 #include "Field.h"
61 #include "meshGFace.h"
62 #include "meshGFaceDelaunayInsertion.h"
63 #include "meshGFaceOptimize.h"
64 #include "meshGRegionDelaunayInsertion.h"
65 #include "meshGRegionHxt.h"
66 #include "gmshCrossFields.h"
67 #endif
68
69 #if defined(HAVE_POST)
70 #include "PView.h"
71 #include "PViewData.h"
72 #include "PViewDataList.h"
73 #include "PViewDataGModel.h"
74 #include "PViewOptions.h"
75 #endif
76
77 #if defined(HAVE_PLUGINS)
78 #include "PluginManager.h"
79 #endif
80
81 #if defined(HAVE_OPENGL)
82 #include "drawContext.h"
83 #endif
84
85 #if defined(HAVE_FLTK)
86 #include "FlGui.h"
87 #endif
88
89 #if defined(HAVE_ONELAB)
90 #include "onelab.h"
91 #include "onelabUtils.h"
92 #endif
93
94 // automatically generated C++ and C headers (in gmsh/api)
95 #include "gmsh.h"
96 extern "C" {
97 #include "gmshc.h"
98 }
99
100 static int _initialized = 0;
101 static int _argc = 0;
102 static char **_argv = nullptr;
103
_checkInit()104 static bool _checkInit()
105 {
106 if(!_initialized) {
107 Msg::Error("Gmsh has not been initialized");
108 return false;
109 }
110 if(!GModel::current()) {
111 Msg::Error("Gmsh has no current model");
112 return false;
113 }
114 return true;
115 }
116
117 // gmsh
118
initialize(int argc,char ** argv,bool readConfigFiles,bool run)119 GMSH_API void gmsh::initialize(int argc, char **argv, bool readConfigFiles,
120 bool run)
121 {
122 if(_initialized) {
123 Msg::Warning("Gmsh has aleady been initialized");
124 return;
125 }
126
127 // when running the app, create a model (that will be used in GmshInitialize
128 // to e.g. set the project name)
129 if(run) new GModel();
130
131 if(GmshInitialize(argc, argv, readConfigFiles, false)) {
132 _initialized = 1;
133 _argc = argc;
134 _argv = new char *[_argc + 1];
135 for(int i = 0; i < argc; i++) _argv[i] = argv[i];
136 if(run) {
137 if(CTX::instance()->batch) {
138 if(!Msg::GetGmshClient()) CTX::instance()->terminal = 1;
139 GmshBatch();
140 }
141 else {
142 GmshFLTK(argc, argv);
143 }
144 }
145 else {
146 // throw an exception as soon as an error occurs, unless the GUI is
147 // running (by default the Gmsh app - and thus also when "run" is set -
148 // always keeps going after errors)
149 CTX::instance()->abortOnError = 2;
150 // show messages on the terminal
151 CTX::instance()->terminal = 1;
152 }
153 return;
154 }
155 Msg::Error("Something went wrong when initializing Gmsh");
156 }
157
finalize()158 GMSH_API void gmsh::finalize()
159 {
160 if(!_checkInit()) return;
161 if(GmshFinalize()) {
162 _argc = 0;
163 if(_argv) delete[] _argv;
164 _argv = nullptr;
165 _initialized = 0;
166 return;
167 }
168 Msg::Error("Something went wrong when finalizing Gmsh");
169 }
170
open(const std::string & fileName)171 GMSH_API void gmsh::open(const std::string &fileName)
172 {
173 if(!_checkInit()) return;
174 if(!GmshOpenProject(fileName))
175 Msg::Error("Could not open file '%s'", fileName.c_str());
176 }
177
merge(const std::string & fileName)178 GMSH_API void gmsh::merge(const std::string &fileName)
179 {
180 if(!_checkInit()) return;
181 if(!GmshMergeFile(fileName))
182 Msg::Error("Could not merge file '%s'", fileName.c_str());
183 }
184
write(const std::string & fileName)185 GMSH_API void gmsh::write(const std::string &fileName)
186 {
187 if(!_checkInit()) return;
188 if(!GmshWriteFile(fileName))
189 Msg::Error("Could not write file '%s'", fileName.c_str());
190 }
191
clear()192 GMSH_API void gmsh::clear()
193 {
194 if(!_checkInit()) return;
195 if(!GmshClearProject()) Msg::Error("Could not clear project");
196 }
197
198 // gmsh::option
199
setNumber(const std::string & name,const double value)200 GMSH_API void gmsh::option::setNumber(const std::string &name,
201 const double value)
202 {
203 if(!_checkInit()) return;
204 std::string c, n;
205 int i;
206 SplitOptionName(name, c, n, i);
207 if(!GmshSetOption(c, n, value, i))
208 Msg::Error("Could not set option '%s'", name.c_str());
209 }
210
getNumber(const std::string & name,double & value)211 GMSH_API void gmsh::option::getNumber(const std::string &name, double &value)
212 {
213 if(!_checkInit()) return;
214 std::string c, n;
215 int i;
216 SplitOptionName(name, c, n, i);
217 if(!GmshGetOption(c, n, value, i))
218 Msg::Error("Could not get option '%s'", name.c_str());
219 }
220
setString(const std::string & name,const std::string & value)221 GMSH_API void gmsh::option::setString(const std::string &name,
222 const std::string &value)
223 {
224 if(!_checkInit()) return;
225 std::string c, n;
226 int i;
227 SplitOptionName(name, c, n, i);
228 if(!GmshSetOption(c, n, value, i))
229 Msg::Error("Could not set option '%s'", name.c_str());
230 }
231
getString(const std::string & name,std::string & value)232 GMSH_API void gmsh::option::getString(const std::string &name,
233 std::string &value)
234 {
235 if(!_checkInit()) return;
236 std::string c, n;
237 int i;
238 SplitOptionName(name, c, n, i);
239 if(!GmshGetOption(c, n, value, i))
240 Msg::Error("Could not get option '%s'", name.c_str());
241 }
242
setColor(const std::string & name,const int r,const int g,const int b,const int a)243 GMSH_API void gmsh::option::setColor(const std::string &name, const int r,
244 const int g, const int b, const int a)
245 {
246 if(!_checkInit()) return;
247 std::string c, n;
248 int i;
249 SplitOptionName(name, c, n, i);
250 // allow "Category.Color.Option" name for compatibility with .geo parser
251 n = ReplaceSubString("Color.", "", n);
252 unsigned int value = CTX::instance()->packColor(r, g, b, a);
253 if(!GmshSetOption(c, n, value, i))
254 Msg::Error("Could not set option '%s'", name.c_str());
255 }
256
getColor(const std::string & name,int & r,int & g,int & b,int & a)257 GMSH_API void gmsh::option::getColor(const std::string &name, int &r, int &g,
258 int &b, int &a)
259 {
260 if(!_checkInit()) return;
261 std::string c, n;
262 int i;
263 SplitOptionName(name, c, n, i);
264 // allow "Category.Color.Option" name for compatibility with .geo parser
265 n = ReplaceSubString("Color.", "", n);
266 unsigned int value;
267 if(GmshGetOption(c, n, value, i)) {
268 r = CTX::instance()->unpackRed(value);
269 g = CTX::instance()->unpackGreen(value);
270 b = CTX::instance()->unpackBlue(value);
271 a = CTX::instance()->unpackAlpha(value);
272 }
273 else {
274 Msg::Error("Could not get option '%s'", name.c_str());
275 }
276 }
277
278 // gmsh::model
279
add(const std::string & name)280 GMSH_API void gmsh::model::add(const std::string &name)
281 {
282 if(!_checkInit()) return;
283 GModel *m = new GModel(name);
284 GModel::current(GModel::list.size() - 1);
285 if(!m) Msg::Error("Could not add model '%s'", name.c_str());
286 }
287
remove()288 GMSH_API void gmsh::model::remove()
289 {
290 if(!_checkInit()) return;
291 GModel *m = GModel::current();
292 if(m)
293 delete m;
294 else
295 Msg::Error("Could not remove current model");
296 }
297
list(std::vector<std::string> & names)298 GMSH_API void gmsh::model::list(std::vector<std::string> &names)
299 {
300 if(!_checkInit()) return;
301 for(std::size_t i = 0; i < GModel::list.size(); i++)
302 names.push_back(GModel::list[i]->getName());
303 }
304
getCurrent(std::string & name)305 GMSH_API void gmsh::model::getCurrent(std::string &name)
306 {
307 if(!_checkInit()) return;
308 name = GModel::current()->getName();
309 }
310
setCurrent(const std::string & name)311 GMSH_API void gmsh::model::setCurrent(const std::string &name)
312 {
313 if(!_checkInit()) return;
314 GModel *m = GModel::findByName(name);
315 if(!m) {
316 Msg::Error("Could find model '%s'", name.c_str());
317 return;
318 }
319 GModel::setCurrent(m);
320 for(std::size_t i = 0; i < GModel::list.size(); i++)
321 GModel::list[i]->setVisibility(0);
322 GModel::current()->setVisibility(1);
323 CTX::instance()->mesh.changed = ENT_ALL;
324 }
325
getFileName(std::string & fileName)326 GMSH_API void gmsh::model::getFileName(std::string &fileName)
327 {
328 if(!_checkInit()) return;
329 fileName = GModel::current()->getFileName();
330 }
331
setFileName(const std::string & fileName)332 GMSH_API void gmsh::model::setFileName(const std::string &fileName)
333 {
334 if(!_checkInit()) return;
335 GModel::current()->setFileName(fileName);
336 }
337
getEntities(vectorpair & dimTags,const int dim)338 GMSH_API void gmsh::model::getEntities(vectorpair &dimTags, const int dim)
339 {
340 if(!_checkInit()) return;
341 dimTags.clear();
342 std::vector<GEntity *> entities;
343 GModel::current()->getEntities(entities, dim);
344 for(std::size_t i = 0; i < entities.size(); i++)
345 dimTags.push_back(
346 std::make_pair(entities[i]->dim(), entities[i]->tag()));
347 }
348
setEntityName(const int dim,const int tag,const std::string & name)349 GMSH_API void gmsh::model::setEntityName(const int dim, const int tag,
350 const std::string &name)
351 {
352 if(!_checkInit()) return;
353 GModel::current()->setElementaryName(dim, tag, name);
354 }
355
getEntityName(const int dim,const int tag,std::string & name)356 GMSH_API void gmsh::model::getEntityName(const int dim, const int tag,
357 std::string &name)
358 {
359 if(!_checkInit()) return;
360 name = GModel::current()->getElementaryName(dim, tag);
361 }
362
getPhysicalGroups(vectorpair & dimTags,const int dim)363 GMSH_API void gmsh::model::getPhysicalGroups(vectorpair &dimTags, const int dim)
364 {
365 if(!_checkInit()) return;
366 dimTags.clear();
367 std::map<int, std::vector<GEntity *> > groups[4];
368 GModel::current()->getPhysicalGroups(groups);
369 for(int d = 0; d < 4; d++) {
370 if(dim < 0 || d == dim) {
371 for(auto it = groups[d].begin(); it != groups[d].end(); it++)
372 dimTags.push_back(std::make_pair(d, it->first));
373 }
374 }
375 }
376
_getEntityName(int dim,int tag)377 static std::string _getEntityName(int dim, int tag)
378 {
379 std::stringstream stream;
380 switch(dim) {
381 case 0: stream << "Point "; break;
382 case 1: stream << "Curve "; break;
383 case 2: stream << "Surface "; break;
384 case 3: stream << "Volume "; break;
385 }
386 stream << tag;
387 return stream.str();
388 }
389
getEntitiesForPhysicalGroup(const int dim,const int tag,std::vector<int> & tags)390 GMSH_API void gmsh::model::getEntitiesForPhysicalGroup(const int dim,
391 const int tag,
392 std::vector<int> &tags)
393 {
394 if(!_checkInit()) return;
395 tags.clear();
396 std::map<int, std::vector<GEntity *> > groups;
397 GModel::current()->getPhysicalGroups(dim, groups);
398 auto it = groups.find(tag);
399 if(it != groups.end()) {
400 for(std::size_t j = 0; j < it->second.size(); j++)
401 tags.push_back(it->second[j]->tag());
402 }
403 else {
404 Msg::Error("Physical %s does not exist", _getEntityName(dim, tag).c_str());
405 }
406 }
407
408 GMSH_API void
getPhysicalGroupsForEntity(const int dim,const int tag,std::vector<int> & physicalTags)409 gmsh::model::getPhysicalGroupsForEntity(const int dim, const int tag,
410 std::vector<int> &physicalTags)
411 {
412 if(!_checkInit()) return;
413 physicalTags.clear();
414 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
415 if(!ge) {
416 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
417 return;
418 }
419 std::vector<int> phy = ge->getPhysicalEntities();
420 physicalTags.resize(phy.size());
421 for(std::size_t i = 0; i < phy.size(); i++) { physicalTags[i] = phy[i]; }
422 }
423
addPhysicalGroup(const int dim,const std::vector<int> & tags,const int tag)424 GMSH_API int gmsh::model::addPhysicalGroup(const int dim,
425 const std::vector<int> &tags,
426 const int tag)
427 {
428 // FIXME: 1) the "master" physical group definitions are still stored in the
429 // buil-in CAD kernel, so that built-in CAD operations (e.g. Coherence) can
430 // track physical groups; and 2) the synchronization of the built-in CAD
431 // kernel triggers a reset of physical groups in GModel, followed by a
432 // copy. So we currently need to maintain both copies when playing with
433 // physical groups in the api at the model level.
434 if(!_checkInit()) return -1;
435 int outTag = tag;
436 if(outTag < 0) {
437 outTag =
438 std::max(GModel::current()->getMaxPhysicalNumber(dim),
439 GModel::current()->getGEOInternals()->getMaxPhysicalTag()) +
440 1;
441 }
442 if(!GModel::current()->getGEOInternals()->modifyPhysicalGroup(dim, outTag, 0,
443 tags)) {
444 Msg::Error("Could not add physical group");
445 return -1;
446 }
447 GModel::current()->addPhysicalGroup(dim, outTag, tags);
448 return outTag;
449 }
450
removePhysicalGroups(const vectorpair & dimTags)451 GMSH_API void gmsh::model::removePhysicalGroups(const vectorpair &dimTags)
452 {
453 if(!_checkInit()) return;
454 if(dimTags.empty()) {
455 GModel::current()->getGEOInternals()->resetPhysicalGroups();
456 GModel::current()->removePhysicalGroups();
457 }
458 else {
459 // FIXME: rewrite the unerlying code: it's slow
460 for(std::size_t i = 0; i < dimTags.size(); i++) {
461 std::vector<int> tags; // empty to delete the group
462 GModel::current()->getGEOInternals()->modifyPhysicalGroup(
463 dimTags[i].first, dimTags[i].second, 2, tags);
464 GModel::current()->removePhysicalGroup(dimTags[i].first,
465 dimTags[i].second);
466 }
467 }
468 }
469
setPhysicalName(const int dim,const int tag,const std::string & name)470 GMSH_API void gmsh::model::setPhysicalName(const int dim, const int tag,
471 const std::string &name)
472 {
473 if(!_checkInit()) return;
474 GModel::current()->setPhysicalName(name, dim, tag);
475 }
476
removePhysicalName(const std::string & name)477 GMSH_API void gmsh::model::removePhysicalName(const std::string &name)
478 {
479 if(!_checkInit()) return;
480 GModel::current()->removePhysicalName(name);
481 }
482
getPhysicalName(const int dim,const int tag,std::string & name)483 GMSH_API void gmsh::model::getPhysicalName(const int dim, const int tag,
484 std::string &name)
485 {
486 if(!_checkInit()) return;
487 name = GModel::current()->getPhysicalName(dim, tag);
488 }
489
setTag(const int dim,const int tag,const int newTag)490 GMSH_API void gmsh::model::setTag(const int dim, const int tag, const int newTag)
491 {
492 if(!_checkInit()) return;
493 GModel::current()->changeEntityTag(dim, tag, newTag);
494 }
495
getBoundary(const vectorpair & dimTags,vectorpair & outDimTags,const bool combined,const bool oriented,const bool recursive)496 GMSH_API void gmsh::model::getBoundary(const vectorpair &dimTags,
497 vectorpair &outDimTags,
498 const bool combined, const bool oriented,
499 const bool recursive)
500 {
501 if(!_checkInit()) return;
502 outDimTags.clear();
503 if(!GModel::current()->getBoundaryTags(dimTags, outDimTags, combined,
504 oriented, recursive)) {
505 Msg::Error("Could not get boundary");
506 }
507 }
508
getAdjacencies(const int dim,const int tag,std::vector<int> & upward,std::vector<int> & downward)509 GMSH_API void gmsh::model::getAdjacencies(const int dim, const int tag,
510 std::vector<int> &upward,
511 std::vector<int> &downward)
512 {
513 if(!_checkInit()) return;
514 upward.clear();
515 downward.clear();
516 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
517 if(!ge) {
518 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
519 return;
520 }
521 switch(dim) {
522 case 0:
523 for(auto &e : static_cast<GVertex *>(ge)->edges())
524 upward.push_back(e->tag());
525 break;
526 case 1:
527 for(auto &e : static_cast<GEdge *>(ge)->faces()) upward.push_back(e->tag());
528 for(auto &e : static_cast<GEdge *>(ge)->vertices())
529 downward.push_back(e->tag());
530 break;
531 case 2:
532 for(auto &e : static_cast<GFace *>(ge)->regions())
533 upward.push_back(e->tag());
534 for(auto &e : static_cast<GFace *>(ge)->edges())
535 downward.push_back(e->tag());
536 break;
537 case 3:
538 for(auto &e : static_cast<GRegion *>(ge)->faces())
539 downward.push_back(e->tag());
540 break;
541 }
542 }
543
getEntitiesInBoundingBox(const double xmin,const double ymin,const double zmin,const double xmax,const double ymax,const double zmax,vectorpair & dimTags,const int dim)544 GMSH_API void gmsh::model::getEntitiesInBoundingBox(
545 const double xmin, const double ymin, const double zmin, const double xmax,
546 const double ymax, const double zmax, vectorpair &dimTags, const int dim)
547 {
548 if(!_checkInit()) return;
549 dimTags.clear();
550 SBoundingBox3d box(xmin, ymin, zmin, xmax, ymax, zmax);
551 std::vector<GEntity *> entities;
552 GModel::current()->getEntitiesInBox(entities, box, dim);
553 for(std::size_t i = 0; i < entities.size(); i++)
554 dimTags.push_back(
555 std::make_pair(entities[i]->dim(), entities[i]->tag()));
556 }
557
getBoundingBox(const int dim,const int tag,double & xmin,double & ymin,double & zmin,double & xmax,double & ymax,double & zmax)558 GMSH_API void gmsh::model::getBoundingBox(const int dim, const int tag,
559 double &xmin, double &ymin,
560 double &zmin, double &xmax,
561 double &ymax, double &zmax)
562 {
563 if(!_checkInit()) return;
564
565 SBoundingBox3d box;
566 if(dim < 0 && tag < 0) {
567 box = GModel::current()->bounds();
568 if(box.empty()) {
569 Msg::Error("Empty bounding box");
570 return;
571 }
572 }
573 else {
574 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
575 if(!ge) {
576 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
577 return;
578 }
579 box = ge->bounds();
580 }
581 if(box.empty()) {
582 Msg::Error("Empty bounding box");
583 return;
584 }
585 xmin = box.min().x();
586 ymin = box.min().y();
587 zmin = box.min().z();
588 xmax = box.max().x();
589 ymax = box.max().y();
590 zmax = box.max().z();
591 }
592
getDimension()593 GMSH_API int gmsh::model::getDimension()
594 {
595 if(!_checkInit()) return -1;
596 return GModel::current()->getDim();
597 }
598
addDiscreteEntity(const int dim,const int tag,const std::vector<int> & boundary)599 GMSH_API int gmsh::model::addDiscreteEntity(const int dim, const int tag,
600 const std::vector<int> &boundary)
601 {
602 if(!_checkInit()) return -1;
603 int outTag = tag;
604 if(outTag < 0) {
605 outTag = GModel::current()->getMaxElementaryNumber(dim) + 1;
606 }
607 GEntity *e = GModel::current()->getEntityByTag(dim, outTag);
608 if(e) {
609 Msg::Error("%s already exists", _getEntityName(dim, outTag).c_str());
610 return -1;
611 }
612 switch(dim) {
613 case 0: {
614 discreteVertex *gv = new discreteVertex(GModel::current(), outTag);
615 GModel::current()->add(gv);
616 break;
617 }
618 case 1: {
619 GVertex *v0 = nullptr, *v1 = nullptr;
620 if(boundary.size() >= 1)
621 v0 = GModel::current()->getVertexByTag(boundary[0]);
622 if(boundary.size() >= 2)
623 v1 = GModel::current()->getVertexByTag(boundary[1]);
624 discreteEdge *ge = new discreteEdge(GModel::current(), outTag, v0, v1);
625 GModel::current()->add(ge);
626 break;
627 }
628 case 2: {
629 discreteFace *gf = new discreteFace(GModel::current(), outTag);
630 std::vector<int> tagEdges, signEdges;
631 for(std::size_t i = 0; i < boundary.size(); i++) {
632 tagEdges.push_back(std::abs(boundary[i]));
633 signEdges.push_back(gmsh_sign(boundary[i]));
634 }
635 if(!tagEdges.empty()) gf->setBoundEdges(tagEdges, signEdges);
636 GModel::current()->add(gf);
637 break;
638 }
639 case 3: {
640 discreteRegion *gr = new discreteRegion(GModel::current(), outTag);
641 std::vector<int> tagFaces, signFaces;
642 for(std::size_t i = 0; i < boundary.size(); i++) {
643 tagFaces.push_back(std::abs(boundary[i]));
644 signFaces.push_back(gmsh_sign(boundary[i]));
645 }
646 if(!tagFaces.empty()) gr->setBoundFaces(tagFaces, signFaces);
647 GModel::current()->add(gr);
648 break;
649 }
650 }
651 return outTag;
652 }
653
removeEntities(const vectorpair & dimTags,const bool recursive)654 GMSH_API void gmsh::model::removeEntities(const vectorpair &dimTags,
655 const bool recursive)
656 {
657 if(!_checkInit()) return;
658 std::vector<GEntity*> removed;
659 GModel::current()->remove(dimTags, removed, recursive);
660 Msg::Debug("Destroying %lu entities in model", removed.size());
661 for(std::size_t i = 0; i < removed.size(); i++) delete removed[i];
662 }
663
removeEntityName(const std::string & name)664 GMSH_API void gmsh::model::removeEntityName(const std::string &name)
665 {
666 if(!_checkInit()) return;
667 GModel::current()->removeElementaryName(name);
668 }
669
getType(const int dim,const int tag,std::string & entityType)670 GMSH_API void gmsh::model::getType(const int dim, const int tag,
671 std::string &entityType)
672 {
673 if(!_checkInit()) return;
674 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
675 if(!ge) {
676 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
677 return;
678 }
679 entityType = ge->getTypeString();
680 }
681
getParent(const int dim,const int tag,int & parentDim,int & parentTag)682 GMSH_API void gmsh::model::getParent(const int dim, const int tag,
683 int &parentDim, int &parentTag)
684 {
685 if(!_checkInit()) return;
686 parentDim = -1;
687 parentTag = -1;
688 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
689 if(!ge) {
690 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
691 return;
692 }
693 GEntity *parent = ge->getParentEntity();
694 if(parent) {
695 parentDim = parent->dim();
696 parentTag = parent->tag();
697 }
698 }
699
getPartitions(const int dim,const int tag,std::vector<int> & partitions)700 GMSH_API void gmsh::model::getPartitions(const int dim, const int tag,
701 std::vector<int> &partitions)
702 {
703 if(!_checkInit()) return;
704 partitions.clear();
705 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
706 if(!ge) {
707 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
708 return;
709 }
710 std::vector<int> p;
711 if(ge->geomType() == GEntity::PartitionPoint)
712 p = static_cast<partitionVertex *>(ge)->getPartitions();
713 else if(ge->geomType() == GEntity::PartitionCurve)
714 p = static_cast<partitionEdge *>(ge)->getPartitions();
715 else if(ge->geomType() == GEntity::PartitionSurface)
716 p = static_cast<partitionFace *>(ge)->getPartitions();
717 else if(ge->geomType() == GEntity::PartitionVolume)
718 p = static_cast<partitionRegion *>(ge)->getPartitions();
719 else if(ge->geomType() == GEntity::GhostCurve)
720 p.push_back(static_cast<ghostEdge *>(ge)->getPartition());
721 else if(ge->geomType() == GEntity::GhostSurface)
722 p.push_back(static_cast<ghostFace *>(ge)->getPartition());
723 else if(ge->geomType() == GEntity::GhostVolume)
724 p.push_back(static_cast<ghostRegion *>(ge)->getPartition());
725
726 for(std::size_t i = 0; i < p.size(); i++) partitions.push_back(p[i]);
727 }
728
getNumberOfPartitions()729 GMSH_API int gmsh::model::getNumberOfPartitions()
730 {
731 if(!_checkInit()) return 0;
732 return GModel::current()->getNumPartitions();
733 }
734
getValue(const int dim,const int tag,const std::vector<double> & parametricCoord,std::vector<double> & coord)735 GMSH_API void gmsh::model::getValue(const int dim, const int tag,
736 const std::vector<double> ¶metricCoord,
737 std::vector<double> &coord)
738 {
739 if(!_checkInit()) return;
740 coord.clear();
741 GEntity *entity = GModel::current()->getEntityByTag(dim, tag);
742 if(!entity) {
743 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
744 return;
745 }
746 if(dim == 0) {
747 coord.push_back(static_cast<GVertex *>(entity)->x());
748 coord.push_back(static_cast<GVertex *>(entity)->y());
749 coord.push_back(static_cast<GVertex *>(entity)->z());
750 }
751 else if(dim == 1) {
752 GEdge *ge = static_cast<GEdge *>(entity);
753 for(std::size_t i = 0; i < parametricCoord.size(); i++) {
754 GPoint gp = ge->point(parametricCoord[i]);
755 coord.push_back(gp.x());
756 coord.push_back(gp.y());
757 coord.push_back(gp.z());
758 }
759 }
760 else if(dim == 2) {
761 if(parametricCoord.size() % 2) {
762 Msg::Error("Number of parametric coordinates should be even");
763 return;
764 }
765 GFace *gf = static_cast<GFace *>(entity);
766 for(std::size_t i = 0; i < parametricCoord.size(); i += 2) {
767 SPoint2 param(parametricCoord[i], parametricCoord[i + 1]);
768 GPoint gp = gf->point(param);
769 coord.push_back(gp.x());
770 coord.push_back(gp.y());
771 coord.push_back(gp.z());
772 }
773 }
774 }
775
776 GMSH_API void
getDerivative(const int dim,const int tag,const std::vector<double> & parametricCoord,std::vector<double> & deriv)777 gmsh::model::getDerivative(const int dim, const int tag,
778 const std::vector<double> ¶metricCoord,
779 std::vector<double> &deriv)
780 {
781 if(!_checkInit()) return;
782 deriv.clear();
783 GEntity *entity = GModel::current()->getEntityByTag(dim, tag);
784 if(!entity) {
785 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
786 return;
787 }
788 if(dim == 1) {
789 GEdge *ge = static_cast<GEdge *>(entity);
790 for(std::size_t i = 0; i < parametricCoord.size(); i++) {
791 SVector3 d = ge->firstDer(parametricCoord[i]);
792 deriv.push_back(d.x());
793 deriv.push_back(d.y());
794 deriv.push_back(d.z());
795 }
796 }
797 else if(dim == 2) {
798 if(parametricCoord.size() % 2) {
799 Msg::Error("Number of parametric coordinates should be even");
800 return;
801 }
802 GFace *gf = static_cast<GFace *>(entity);
803 for(std::size_t i = 0; i < parametricCoord.size(); i += 2) {
804 SPoint2 param(parametricCoord[i], parametricCoord[i + 1]);
805 Pair<SVector3, SVector3> d = gf->firstDer(param);
806 deriv.push_back(d.left().x());
807 deriv.push_back(d.left().y());
808 deriv.push_back(d.left().z());
809 deriv.push_back(d.right().x());
810 deriv.push_back(d.right().y());
811 deriv.push_back(d.right().z());
812 }
813 }
814 }
815
816 GMSH_API void
getSecondDerivative(const int dim,const int tag,const std::vector<double> & parametricCoord,std::vector<double> & deriv)817 gmsh::model::getSecondDerivative(const int dim, const int tag,
818 const std::vector<double> ¶metricCoord,
819 std::vector<double> &deriv)
820 {
821 if(!_checkInit()) return;
822 deriv.clear();
823 GEntity *entity = GModel::current()->getEntityByTag(dim, tag);
824 if(!entity) {
825 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
826 return;
827 }
828 if(dim == 1) {
829 GEdge *ge = static_cast<GEdge *>(entity);
830 for(std::size_t i = 0; i < parametricCoord.size(); i++) {
831 SVector3 d = ge->secondDer(parametricCoord[i]);
832 deriv.push_back(d.x());
833 deriv.push_back(d.y());
834 deriv.push_back(d.z());
835 }
836 }
837 else if(dim == 2) {
838 if(parametricCoord.size() % 2) {
839 Msg::Error("Number of parametric coordinates should be even");
840 return;
841 }
842 GFace *gf = static_cast<GFace *>(entity);
843 for(std::size_t i = 0; i < parametricCoord.size(); i += 2) {
844 SPoint2 param(parametricCoord[i], parametricCoord[i + 1]);
845 SVector3 dudu, dvdv, dudv;
846 gf->secondDer(param, dudu, dvdv, dudv);
847 deriv.push_back(dudu.x());
848 deriv.push_back(dudu.y());
849 deriv.push_back(dudu.z());
850 deriv.push_back(dvdv.x());
851 deriv.push_back(dvdv.y());
852 deriv.push_back(dvdv.z());
853 deriv.push_back(dudv.x());
854 deriv.push_back(dudv.y());
855 deriv.push_back(dudv.z());
856 }
857 }
858 }
859
860 GMSH_API void
getCurvature(const int dim,const int tag,const std::vector<double> & parametricCoord,std::vector<double> & curvatures)861 gmsh::model::getCurvature(const int dim, const int tag,
862 const std::vector<double> ¶metricCoord,
863 std::vector<double> &curvatures)
864 {
865 if(!_checkInit()) return;
866 curvatures.clear();
867 GEntity *entity = GModel::current()->getEntityByTag(dim, tag);
868 if(!entity) {
869 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
870 return;
871 }
872 if(dim == 1) {
873 GEdge *ge = static_cast<GEdge *>(entity);
874 for(std::size_t i = 0; i < parametricCoord.size(); i++)
875 curvatures.push_back(ge->curvature(parametricCoord[i]));
876 }
877 else if(dim == 2) {
878 if(parametricCoord.size() % 2) {
879 Msg::Error("Number of parametric coordinates should be even");
880 return;
881 }
882 GFace *gf = static_cast<GFace *>(entity);
883 for(std::size_t i = 0; i < parametricCoord.size(); i += 2) {
884 SPoint2 param(parametricCoord[i], parametricCoord[i + 1]);
885 curvatures.push_back(gf->curvatureMax(param));
886 }
887 }
888 }
889
getPrincipalCurvatures(const int tag,const std::vector<double> & parametricCoord,std::vector<double> & curvaturesMax,std::vector<double> & curvaturesMin,std::vector<double> & directionsMax,std::vector<double> & directionsMin)890 GMSH_API void gmsh::model::getPrincipalCurvatures(
891 const int tag, const std::vector<double> ¶metricCoord,
892 std::vector<double> &curvaturesMax, std::vector<double> &curvaturesMin,
893 std::vector<double> &directionsMax, std::vector<double> &directionsMin)
894 {
895 if(!_checkInit()) return;
896 GFace *gf = GModel::current()->getFaceByTag(tag);
897 if(!gf) {
898 Msg::Error("%s does not exist", _getEntityName(2, tag).c_str());
899 return;
900 }
901 curvaturesMax.clear();
902 curvaturesMin.clear();
903 directionsMax.clear();
904 directionsMin.clear();
905 if(parametricCoord.size() % 2) {
906 Msg::Error("Number of parametric coordinates should be even");
907 return;
908 }
909 for(std::size_t i = 0; i < parametricCoord.size(); i += 2) {
910 SPoint2 param(parametricCoord[i], parametricCoord[i + 1]);
911 double cmin, cmax;
912 SVector3 dmin, dmax;
913 gf->curvatures(param, dmax, dmin, cmax, cmin);
914 curvaturesMax.push_back(cmax);
915 curvaturesMin.push_back(cmin);
916 directionsMax.push_back(dmax.x());
917 directionsMax.push_back(dmax.y());
918 directionsMax.push_back(dmax.z());
919 directionsMin.push_back(dmin.x());
920 directionsMin.push_back(dmin.y());
921 directionsMin.push_back(dmin.z());
922 }
923 }
924
getNormal(const int tag,const std::vector<double> & parametricCoord,std::vector<double> & normals)925 GMSH_API void gmsh::model::getNormal(const int tag,
926 const std::vector<double> ¶metricCoord,
927 std::vector<double> &normals)
928 {
929 if(!_checkInit()) return;
930 GFace *gf = GModel::current()->getFaceByTag(tag);
931 if(!gf) {
932 Msg::Error("%s does not exist", _getEntityName(2, tag).c_str());
933 return;
934 }
935 normals.clear();
936 if(parametricCoord.size() % 2) {
937 Msg::Error("Number of parametric coordinates should be even");
938 return;
939 }
940 for(std::size_t i = 0; i < parametricCoord.size(); i += 2) {
941 SPoint2 param(parametricCoord[i], parametricCoord[i + 1]);
942 SVector3 n = gf->normal(param);
943 normals.push_back(n.x());
944 normals.push_back(n.y());
945 normals.push_back(n.z());
946 }
947 }
948
949 GMSH_API void
getParametrization(const int dim,const int tag,const std::vector<double> & coord,std::vector<double> & parametricCoord)950 gmsh::model::getParametrization(const int dim, const int tag,
951 const std::vector<double> &coord,
952 std::vector<double> ¶metricCoord)
953 {
954 if(!_checkInit()) return;
955 parametricCoord.clear();
956 GEntity *entity = GModel::current()->getEntityByTag(dim, tag);
957 if(!entity) {
958 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
959 return;
960 }
961 if(coord.size() % 3) {
962 Msg::Error("Number of coordinates should be a multiple of 3");
963 return;
964 }
965 if(dim == 1) {
966 GEdge *ge = static_cast<GEdge *>(entity);
967 for(std::size_t i = 0; i < coord.size(); i += 3) {
968 SPoint3 p(coord[i], coord[i + 1], coord[i + 2]);
969 double t = ge->parFromPoint(p);
970 parametricCoord.push_back(t);
971 }
972 }
973 else if(dim == 2) {
974 GFace *gf = static_cast<GFace *>(entity);
975 for(std::size_t i = 0; i < coord.size(); i += 3) {
976 SPoint3 p(coord[i], coord[i + 1], coord[i + 2]);
977 SPoint2 uv = gf->parFromPoint(p, true, true);
978 parametricCoord.push_back(uv.x());
979 parametricCoord.push_back(uv.y());
980 }
981 }
982 }
983
getParametrizationBounds(const int dim,const int tag,std::vector<double> & min,std::vector<double> & max)984 GMSH_API void gmsh::model::getParametrizationBounds(const int dim,
985 const int tag,
986 std::vector<double> &min,
987 std::vector<double> &max)
988 {
989 if(!_checkInit()) return;
990 min.clear();
991 max.clear();
992 GEntity *entity = GModel::current()->getEntityByTag(dim, tag);
993 if(!entity) {
994 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
995 return;
996 }
997 for(int dim = 0; dim < entity->dim(); dim++) {
998 Range<double> r = entity->parBounds(dim);
999 min.push_back(r.low());
1000 max.push_back(r.high());
1001 }
1002 }
1003
isInside(const int dim,const int tag,const std::vector<double> & coord,const bool parametric)1004 GMSH_API int gmsh::model::isInside(const int dim, const int tag,
1005 const std::vector<double> &coord,
1006 const bool parametric)
1007 {
1008 if(!_checkInit()) return -1;
1009 GEntity *entity = GModel::current()->getEntityByTag(dim, tag);
1010 if(!entity) {
1011 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
1012 return 0;
1013 }
1014 int num = 0;
1015 if(parametric) {
1016 if(dim == 1) {
1017 GEdge *ge = static_cast<GEdge *>(entity);
1018 for(std::size_t i = 0; i < coord.size(); i++) {
1019 if(ge->containsParam(coord[i])) num++;
1020 }
1021 }
1022 else if(dim == 2) {
1023 GFace *gf = static_cast<GFace *>(entity);
1024 if(coord.size() % 2) {
1025 Msg::Error("Number of parametric coordinates should be even");
1026 return num;
1027 }
1028 for(std::size_t i = 0; i < coord.size(); i += 2) {
1029 SPoint2 param(coord[i], coord[i + 1]);
1030 if(gf->containsParam(param)) num++;
1031 }
1032 }
1033 }
1034 else {
1035 if(coord.size() % 3) {
1036 Msg::Error("Number of coordinates should be a multiple of 3");
1037 return 0;
1038 }
1039 for(std::size_t i = 0; i < coord.size(); i += 3) {
1040 SPoint3 pt(coord[i], coord[i + 1], coord[i + 2]);
1041 if(entity->containsPoint(pt)) num++;
1042 }
1043 }
1044 return num;
1045 }
1046
reparametrizeOnSurface(const int dim,const int tag,const std::vector<double> & parametricCoord,const int surfaceTag,std::vector<double> & surfaceParametricCoord,const int which)1047 GMSH_API void gmsh::model::reparametrizeOnSurface(
1048 const int dim, const int tag, const std::vector<double> ¶metricCoord,
1049 const int surfaceTag, std::vector<double> &surfaceParametricCoord,
1050 const int which)
1051 {
1052 if(!_checkInit()) return;
1053 surfaceParametricCoord.clear();
1054 GEntity *entity = GModel::current()->getEntityByTag(dim, tag);
1055 if(!entity) {
1056 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
1057 return;
1058 }
1059 GFace *gf = GModel::current()->getFaceByTag(surfaceTag);
1060 if(!gf) {
1061 Msg::Error("%s does not exist", _getEntityName(2, surfaceTag).c_str());
1062 return;
1063 }
1064 if(dim == 0) {
1065 GVertex *gv = static_cast<GVertex *>(entity);
1066 SPoint2 p = gv->reparamOnFace(gf, which);
1067 surfaceParametricCoord.push_back(p.x());
1068 surfaceParametricCoord.push_back(p.y());
1069 }
1070 else if(dim == 1) {
1071 GEdge *ge = static_cast<GEdge *>(entity);
1072 for(std::size_t i = 0; i < parametricCoord.size(); i++) {
1073 SPoint2 p = ge->reparamOnFace(gf, parametricCoord[i], which);
1074 surfaceParametricCoord.push_back(p.x());
1075 surfaceParametricCoord.push_back(p.y());
1076 }
1077 }
1078 }
1079
getClosestPoint(const int dim,const int tag,const std::vector<double> & coord,std::vector<double> & closestCoord,std::vector<double> & parametricCoord)1080 GMSH_API void gmsh::model::getClosestPoint(const int dim, const int tag,
1081 const std::vector<double> &coord,
1082 std::vector<double> &closestCoord,
1083 std::vector<double> ¶metricCoord)
1084 {
1085 if(!_checkInit()) return;
1086 closestCoord.clear();
1087 parametricCoord.clear();
1088 GEntity *entity = GModel::current()->getEntityByTag(dim, tag);
1089 if(!entity) {
1090 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
1091 return;
1092 }
1093 if(coord.size() % 3) {
1094 Msg::Error("Number of coordinates should be a multiple of 3");
1095 return;
1096 }
1097 if(dim == 1) {
1098 GEdge *ge = static_cast<GEdge *>(entity);
1099 for(std::size_t i = 0; i < coord.size(); i += 3) {
1100 SPoint3 p(coord[i], coord[i + 1], coord[i + 2]);
1101 double t;
1102 GPoint pp = ge->closestPoint(p, t);
1103 closestCoord.push_back(pp.x());
1104 closestCoord.push_back(pp.y());
1105 closestCoord.push_back(pp.z());
1106 parametricCoord.push_back(t);
1107 }
1108 }
1109 else if(dim == 2) {
1110 GFace *gf = static_cast<GFace *>(entity);
1111 for(std::size_t i = 0; i < coord.size(); i += 3) {
1112 SPoint3 p(coord[i], coord[i + 1], coord[i + 2]);
1113 double uv[2] = {0, 0};
1114 GPoint pp = gf->closestPoint(p, uv);
1115 closestCoord.push_back(pp.x());
1116 closestCoord.push_back(pp.y());
1117 closestCoord.push_back(pp.z());
1118 parametricCoord.push_back(uv[0]);
1119 parametricCoord.push_back(uv[1]);
1120 }
1121 }
1122 }
1123
setVisibility(const vectorpair & dimTags,const int value,const bool recursive)1124 GMSH_API void gmsh::model::setVisibility(const vectorpair &dimTags,
1125 const int value, const bool recursive)
1126 {
1127 if(!_checkInit()) return;
1128 for(std::size_t i = 0; i < dimTags.size(); i++) {
1129 GEntity *ge = GModel::current()->getEntityByTag(
1130 dimTags[i].first, std::abs(dimTags[i].second));
1131 if(ge) ge->setVisibility(value, recursive);
1132 }
1133 }
1134
getVisibility(const int dim,const int tag,int & value)1135 GMSH_API void gmsh::model::getVisibility(const int dim, const int tag,
1136 int &value)
1137 {
1138 if(!_checkInit()) return;
1139 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
1140 if(!ge) {
1141 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
1142 return;
1143 }
1144 value = ge->getVisibility();
1145 }
1146
setVisibilityPerWindow(const int value,const int windowIndex)1147 GMSH_API void gmsh::model::setVisibilityPerWindow(const int value,
1148 const int windowIndex)
1149 {
1150 if(!_checkInit()) return;
1151 #if defined(HAVE_FLTK)
1152 FlGui::instance()->setCurrentOpenglWindow(windowIndex);
1153 drawContext *ctx = FlGui::instance()->getCurrentDrawContext();
1154 GModel *m = GModel::current();
1155 if(value)
1156 ctx->show(m);
1157 else
1158 ctx->hide(m);
1159 #endif
1160 }
1161
setColor(const vectorpair & dimTags,const int r,const int g,const int b,const int a,const bool recursive)1162 GMSH_API void gmsh::model::setColor(const vectorpair &dimTags, const int r,
1163 const int g, const int b, const int a,
1164 const bool recursive)
1165 {
1166 if(!_checkInit()) return;
1167 for(std::size_t i = 0; i < dimTags.size(); i++) {
1168 GEntity *ge = GModel::current()->getEntityByTag(
1169 dimTags[i].first, std::abs(dimTags[i].second));
1170 if(ge) {
1171 unsigned int val = CTX::instance()->packColor(r, g, b, a);
1172 ge->setColor(val, recursive);
1173 }
1174 }
1175 }
1176
getColor(const int dim,const int tag,int & r,int & g,int & b,int & a)1177 GMSH_API void gmsh::model::getColor(const int dim, const int tag, int &r,
1178 int &g, int &b, int &a)
1179 {
1180 if(!_checkInit()) return;
1181 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
1182 if(!ge) {
1183 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
1184 return;
1185 }
1186 unsigned int value = ge->getColor();
1187 r = CTX::instance()->unpackRed(value);
1188 g = CTX::instance()->unpackGreen(value);
1189 b = CTX::instance()->unpackBlue(value);
1190 a = CTX::instance()->unpackAlpha(value);
1191 }
1192
setCoordinates(const int tag,const double x,const double y,const double z)1193 GMSH_API void gmsh::model::setCoordinates(const int tag, const double x,
1194 const double y, const double z)
1195 {
1196 if(!_checkInit()) return;
1197 GVertex *gv = GModel::current()->getVertexByTag(tag);
1198 if(!gv) {
1199 Msg::Error("%s does not exist", _getEntityName(0, tag).c_str());
1200 return;
1201 }
1202 GPoint p(x, y, z);
1203 gv->setPosition(p);
1204 }
1205
1206 // gmsh::model::mesh
1207
generate(const int dim)1208 GMSH_API void gmsh::model::mesh::generate(const int dim)
1209 {
1210 if(!_checkInit()) return;
1211 GModel::current()->mesh(dim);
1212 CTX::instance()->mesh.changed = ENT_ALL;
1213 }
1214
1215 GMSH_API void
partition(const int numPart,const std::vector<std::size_t> & elementTags,const std::vector<int> & partitions)1216 gmsh::model::mesh::partition(const int numPart,
1217 const std::vector<std::size_t> &elementTags,
1218 const std::vector<int> &partitions)
1219 {
1220 if(!_checkInit()) return;
1221 std::vector<std::pair<MElement *, int> > epart;
1222 if(elementTags.size()) {
1223 if(elementTags.size() != partitions.size()) {
1224 Msg::Error("Number of element tags (%d) does not match number of "
1225 "partitions (%d)",
1226 elementTags.size(), partitions.size());
1227 return;
1228 }
1229 epart.reserve(elementTags.size());
1230 for(std::size_t i = 0; i < elementTags.size(); i++) {
1231 MElement *el = GModel::current()->getMeshElementByTag(elementTags[i]);
1232 if(el)
1233 epart.push_back(std::make_pair(el, partitions[i]));
1234 else
1235 Msg::Error("Unknown element %d", elementTags[i]);
1236 }
1237 }
1238 GModel::current()->partitionMesh(
1239 numPart >= 0 ? numPart : CTX::instance()->mesh.numPartitions, epart);
1240 CTX::instance()->mesh.changed = ENT_ALL;
1241 }
1242
unpartition()1243 GMSH_API void gmsh::model::mesh::unpartition()
1244 {
1245 if(!_checkInit()) return;
1246 GModel::current()->unpartitionMesh();
1247 CTX::instance()->mesh.changed = ENT_ALL;
1248 }
1249
refine()1250 GMSH_API void gmsh::model::mesh::refine()
1251 {
1252 if(!_checkInit()) return;
1253 GModel::current()->refineMesh(CTX::instance()->mesh.secondOrderLinear,
1254 CTX::instance()->mesh.algoSubdivide == 1,
1255 CTX::instance()->mesh.algoSubdivide == 2,
1256 CTX::instance()->mesh.algoSubdivide == 3);
1257 CTX::instance()->mesh.changed = ENT_ALL;
1258 }
1259
recombine()1260 GMSH_API void gmsh::model::mesh::recombine()
1261 {
1262 if(!_checkInit()) return;
1263 GModel::current()->recombineMesh();
1264 CTX::instance()->mesh.changed = ENT_ALL;
1265 }
1266
optimize(const std::string & how,const bool force,const int niter,const vectorpair & dimTags)1267 GMSH_API void gmsh::model::mesh::optimize(const std::string &how,
1268 const bool force, const int niter,
1269 const vectorpair &dimTags)
1270 {
1271 if(!_checkInit()) return;
1272 if(dimTags.size()) {
1273 Msg::Warning(
1274 "Optimization of specified model entities is not interfaced yet");
1275 }
1276 GModel::current()->optimizeMesh(how, force, niter);
1277 CTX::instance()->mesh.changed = ENT_ALL;
1278 }
1279
computeCrossField(std::vector<int> & tags)1280 GMSH_API void gmsh::model::mesh::computeCrossField(std::vector<int> &tags)
1281 {
1282 if(!_checkInit()) return;
1283 #if defined(HAVE_MESH)
1284 if(computeCrossField(GModel::current(), tags)) {
1285 Msg::Error("Could not compute cross field");
1286 return;
1287 }
1288 #else
1289 Msg::Error("computeCrossField requires the mesh module");
1290 #endif
1291 }
1292
splitQuadrangles(const double quality,const int tag)1293 GMSH_API void gmsh::model::mesh::splitQuadrangles(const double quality,
1294 const int tag)
1295 {
1296 if(!_checkInit()) return;
1297 #if defined(HAVE_MESH)
1298 std::vector<GEntity *> entities;
1299 if(tag < 0) { GModel::current()->getEntities(entities, 2); }
1300 else {
1301 GEntity *ge = GModel::current()->getEntityByTag(2, tag);
1302 if(!ge) {
1303 Msg::Error("%s does not exist", _getEntityName(2, tag).c_str());
1304 return;
1305 }
1306 entities.push_back(ge);
1307 }
1308 for(std::size_t i = 0; i < entities.size(); i++) {
1309 GFace *gf = static_cast<GFace *>(entities[i]);
1310 quadsToTriangles(gf, quality);
1311 }
1312 CTX::instance()->mesh.changed = ENT_ALL;
1313 #else
1314 Msg::Error("splitQuadrangles requires the mesh module");
1315 #endif
1316 }
1317
setOrder(const int order)1318 GMSH_API void gmsh::model::mesh::setOrder(const int order)
1319 {
1320 if(!_checkInit()) return;
1321 GModel::current()->setOrderN(order, CTX::instance()->mesh.secondOrderLinear,
1322 CTX::instance()->mesh.secondOrderIncomplete);
1323 CTX::instance()->mesh.changed = ENT_ALL;
1324 }
1325
getLastEntityError(vectorpair & dimTags)1326 GMSH_API void gmsh::model::mesh::getLastEntityError(vectorpair &dimTags)
1327 {
1328 if(!_checkInit()) return;
1329 std::vector<GEntity *> e = GModel::current()->getLastMeshEntityError();
1330 dimTags.clear();
1331 for(std::size_t i = 0; i < e.size(); i++)
1332 dimTags.push_back(std::make_pair(e[i]->dim(), e[i]->tag()));
1333 }
1334
1335 GMSH_API void
getLastNodeError(std::vector<std::size_t> & nodeTags)1336 gmsh::model::mesh::getLastNodeError(std::vector<std::size_t> &nodeTags)
1337 {
1338 if(!_checkInit()) return;
1339 std::vector<MVertex *> v = GModel::current()->getLastMeshVertexError();
1340 nodeTags.clear();
1341 for(std::size_t i = 0; i < v.size(); i++) nodeTags.push_back(v[i]->getNum());
1342 }
1343
clear(const vectorpair & dimTags)1344 GMSH_API void gmsh::model::mesh::clear(const vectorpair &dimTags)
1345 {
1346 if(!_checkInit()) return;
1347 std::vector<GEntity *> entities;
1348 for(std::size_t i = 0; i < dimTags.size(); i++) {
1349 int dim = dimTags[i].first;
1350 int tag = dimTags[i].second;
1351 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
1352 if(!ge) {
1353 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
1354 return;
1355 }
1356 entities.push_back(ge);
1357 }
1358 GModel::current()->deleteMesh(entities);
1359 }
1360
_getEntities(const gmsh::vectorpair & dimTags,std::vector<GEntity * > & entities)1361 static void _getEntities(const gmsh::vectorpair &dimTags,
1362 std::vector<GEntity *> &entities)
1363 {
1364 if(dimTags.empty()) { GModel::current()->getEntities(entities); }
1365 else {
1366 for(auto dimTag : dimTags) {
1367 int dim = dimTag.first, tag = dimTag.second;
1368 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
1369 if(!ge) {
1370 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
1371 return;
1372 }
1373 entities.push_back(ge);
1374 }
1375 }
1376 }
1377
reverse(const vectorpair & dimTags)1378 GMSH_API void gmsh::model::mesh::reverse(const vectorpair &dimTags)
1379 {
1380 if(!_checkInit()) return;
1381 std::vector<GEntity *> entities;
1382 _getEntities(dimTags, entities);
1383 for(auto ge : entities) {
1384 for(std::size_t j = 0; j < ge->getNumMeshElements(); j++) {
1385 ge->getMeshElement(j)->reverse();
1386 }
1387 }
1388 GModel::current()->destroyMeshCaches();
1389 }
1390
1391 GMSH_API void
affineTransform(const std::vector<double> & affineTransform,const vectorpair & dimTags)1392 gmsh::model::mesh::affineTransform(const std::vector<double> &affineTransform,
1393 const vectorpair &dimTags)
1394 {
1395 if(!_checkInit()) return;
1396 std::vector<GEntity *> entities;
1397 _getEntities(dimTags, entities);
1398 for(auto ge : entities) {
1399 for(std::size_t j = 0; j < ge->getNumMeshVertices(); j++) {
1400 MVertex *v = ge->getMeshVertex(j);
1401 SPoint3 pt = v->point();
1402 if(pt.transform(affineTransform))
1403 v->setXYZ(pt);
1404 else
1405 Msg::Error("Could not transform node %d (%g, %g, %g) on %s",
1406 v->getNum(), v->x(), v->y(), v->z(),
1407 _getEntityName(ge->dim(), ge->tag()).c_str());
1408 }
1409 }
1410 }
1411
_getAdditionalNodesOnBoundary(GEntity * entity,std::vector<std::size_t> & nodeTags,std::vector<double> & coord,std::vector<double> & parametricCoord,bool parametric)1412 static void _getAdditionalNodesOnBoundary(GEntity *entity,
1413 std::vector<std::size_t> &nodeTags,
1414 std::vector<double> &coord,
1415 std::vector<double> ¶metricCoord,
1416 bool parametric)
1417 {
1418 std::vector<GFace *> f;
1419 std::vector<GEdge *> e;
1420 std::vector<GVertex *> v;
1421 if(entity->dim() > 2) f = entity->faces();
1422 if(entity->dim() > 1) e = entity->edges();
1423 if(entity->dim() > 0) v = entity->vertices();
1424 for(auto it = f.begin(); it != f.end(); it++) {
1425 GFace *gf = *it;
1426 for(std::size_t j = 0; j < gf->mesh_vertices.size(); j++) {
1427 MVertex *v = gf->mesh_vertices[j];
1428 nodeTags.push_back(v->getNum());
1429 coord.push_back(v->x());
1430 coord.push_back(v->y());
1431 coord.push_back(v->z());
1432 }
1433 }
1434 for(auto it = e.begin(); it != e.end(); it++) {
1435 GEdge *ge = *it;
1436 for(std::size_t j = 0; j < ge->mesh_vertices.size(); j++) {
1437 MVertex *v = ge->mesh_vertices[j];
1438 nodeTags.push_back(v->getNum());
1439 coord.push_back(v->x());
1440 coord.push_back(v->y());
1441 coord.push_back(v->z());
1442 if(entity->dim() == 2 && parametric) {
1443 SPoint2 param;
1444 if(!reparamMeshVertexOnFace(v, (GFace *)entity, param, true, false))
1445 Msg::Warning("Failed to compute parameters of node %d on surface %d",
1446 v->getNum(), entity->tag());
1447 parametricCoord.push_back(param.x());
1448 parametricCoord.push_back(param.y());
1449 }
1450 }
1451 }
1452 for(auto it = v.begin(); it != v.end(); it++) {
1453 GVertex *gv = *it;
1454 for(std::size_t j = 0; j < gv->mesh_vertices.size(); j++) {
1455 MVertex *v = gv->mesh_vertices[j];
1456 nodeTags.push_back(v->getNum());
1457 coord.push_back(v->x());
1458 coord.push_back(v->y());
1459 coord.push_back(v->z());
1460 if(entity->dim() == 2 && parametric) {
1461 SPoint2 param;
1462 if(!reparamMeshVertexOnFace(v, (GFace *)entity, param, true, false))
1463 Msg::Warning("Failed to compute parameters of node %d on surface %d",
1464 v->getNum(), entity->tag());
1465 parametricCoord.push_back(param.x());
1466 parametricCoord.push_back(param.y());
1467 }
1468 else if(entity->dim() == 1 && parametric) {
1469 double param;
1470 if(!reparamMeshVertexOnEdge(v, (GEdge *)entity, param))
1471 Msg::Warning("Failed to compute parameters of node %d on curve %d",
1472 v->getNum(), entity->tag());
1473 parametricCoord.push_back(param);
1474 }
1475 }
1476 }
1477 }
1478
getNodes(std::vector<std::size_t> & nodeTags,std::vector<double> & coord,std::vector<double> & parametricCoord,const int dim,const int tag,const bool includeBoundary,const bool returnParametricCoord)1479 GMSH_API void gmsh::model::mesh::getNodes(std::vector<std::size_t> &nodeTags,
1480 std::vector<double> &coord,
1481 std::vector<double> ¶metricCoord,
1482 const int dim, const int tag,
1483 const bool includeBoundary,
1484 const bool returnParametricCoord)
1485 {
1486 if(!_checkInit()) return;
1487 nodeTags.clear();
1488 coord.clear();
1489 parametricCoord.clear();
1490 std::vector<GEntity *> entities;
1491 if(dim >= 0 && tag >= 0) {
1492 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
1493 if(!ge) {
1494 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
1495 return;
1496 }
1497 entities.push_back(ge);
1498 }
1499 else {
1500 GModel::current()->getEntities(entities, dim);
1501 }
1502 for(std::size_t i = 0; i < entities.size(); i++) {
1503 GEntity *ge = entities[i];
1504 for(std::size_t j = 0; j < ge->mesh_vertices.size(); j++) {
1505 MVertex *v = ge->mesh_vertices[j];
1506 nodeTags.push_back(v->getNum());
1507 coord.push_back(v->x());
1508 coord.push_back(v->y());
1509 coord.push_back(v->z());
1510 if(dim > 0 && returnParametricCoord) {
1511 double par;
1512 for(int k = 0; k < dim; k++) {
1513 if(v->getParameter(k, par)) parametricCoord.push_back(par);
1514 }
1515 }
1516 }
1517 if(includeBoundary)
1518 _getAdditionalNodesOnBoundary(ge, nodeTags, coord, parametricCoord,
1519 dim > 0 && returnParametricCoord);
1520 }
1521 }
1522
getNodesByElementType(const int elementType,std::vector<std::size_t> & nodeTags,std::vector<double> & coord,std::vector<double> & parametricCoord,const int tag,const bool returnParametricCoord)1523 GMSH_API void gmsh::model::mesh::getNodesByElementType(
1524 const int elementType, std::vector<std::size_t> &nodeTags,
1525 std::vector<double> &coord, std::vector<double> ¶metricCoord,
1526 const int tag, const bool returnParametricCoord)
1527 {
1528 if(!_checkInit()) return;
1529 nodeTags.clear();
1530 coord.clear();
1531 parametricCoord.clear();
1532 std::vector<GEntity *> entities;
1533 int dim = ElementType::getDimension(elementType);
1534 if(dim >= 0 && tag >= 0) {
1535 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
1536 if(!ge) {
1537 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
1538 return;
1539 }
1540 entities.push_back(ge);
1541 }
1542 else {
1543 GModel::current()->getEntities(entities, dim);
1544 }
1545
1546 int familyType = ElementType::getParentType(elementType);
1547 int numNodesByElements = ElementType::getNumVertices(elementType);
1548 std::size_t numElements = 0;
1549 for(std::size_t i = 0; i < entities.size(); ++i) {
1550 numElements += entities[i]->getNumMeshElementsByType(familyType);
1551 }
1552 std::size_t numNodes = numElements * numNodesByElements;
1553
1554 nodeTags.reserve(numNodes);
1555 coord.reserve(numNodes * 3);
1556 if(returnParametricCoord) { parametricCoord.reserve(numNodes * 3); }
1557
1558 for(std::size_t i = 0; i < entities.size(); i++) {
1559 GEntity *ge = entities[i];
1560 for(std::size_t j = 0;
1561 j < entities[i]->getNumMeshElementsByType(familyType); j++) {
1562 MElement *e = ge->getMeshElementByType(familyType, j);
1563 for(std::size_t k = 0; k < e->getNumVertices(); ++k) {
1564 MVertex *v = e->getVertex(k);
1565 nodeTags.push_back(v->getNum());
1566 coord.push_back(v->x());
1567 coord.push_back(v->y());
1568 coord.push_back(v->z());
1569 if(dim > 0 && returnParametricCoord) {
1570 double par;
1571 for(int k = 0; k < dim; k++) {
1572 if(v->getParameter(k, par)) parametricCoord.push_back(par);
1573 }
1574 }
1575 }
1576 }
1577 }
1578 }
1579
getNode(const std::size_t nodeTag,std::vector<double> & coord,std::vector<double> & parametricCoord,int & dim,int & tag)1580 GMSH_API void gmsh::model::mesh::getNode(const std::size_t nodeTag,
1581 std::vector<double> &coord,
1582 std::vector<double> ¶metricCoord,
1583 int &dim, int &tag)
1584 {
1585 if(!_checkInit()) return;
1586 MVertex *v = GModel::current()->getMeshVertexByTag(nodeTag);
1587 if(!v) {
1588 Msg::Error("Unknown node %d", nodeTag);
1589 return;
1590 }
1591 coord.resize(3);
1592 coord[0] = v->x();
1593 coord[1] = v->y();
1594 coord[2] = v->z();
1595 parametricCoord.reserve(2);
1596 double u;
1597 if(v->getParameter(0, u)) parametricCoord.push_back(u);
1598 if(v->getParameter(1, u)) parametricCoord.push_back(u);
1599 if(v->onWhat()) {
1600 dim = v->onWhat()->dim();
1601 tag = v->onWhat()->tag();
1602 }
1603 else {
1604 Msg::Warning("Node %d is not classified on any entity", nodeTag);
1605 dim = -1;
1606 tag = -1;
1607 }
1608 }
1609
1610 GMSH_API void
setNode(const std::size_t nodeTag,const std::vector<double> & coord,const std::vector<double> & parametricCoord)1611 gmsh::model::mesh::setNode(const std::size_t nodeTag,
1612 const std::vector<double> &coord,
1613 const std::vector<double> ¶metricCoord)
1614 {
1615 if(!_checkInit()) return;
1616 MVertex *v = GModel::current()->getMeshVertexByTag(nodeTag);
1617 if(!v) {
1618 Msg::Error("Unknown node %d", nodeTag);
1619 return;
1620 }
1621 if(coord.size() < 3) {
1622 Msg::Error("Less than three coordinates provided for node %d", nodeTag);
1623 return;
1624 }
1625 v->setXYZ(coord[0], coord[1], coord[2]);
1626 if(parametricCoord.size() >= 1) v->setParameter(0, parametricCoord[0]);
1627 if(parametricCoord.size() >= 2) v->setParameter(1, parametricCoord[1]);
1628 }
1629
rebuildNodeCache(bool onlyIfNecessary)1630 GMSH_API void gmsh::model::mesh::rebuildNodeCache(bool onlyIfNecessary)
1631 {
1632 if(!_checkInit()) return;
1633 GModel::current()->rebuildMeshVertexCache(onlyIfNecessary);
1634 }
1635
rebuildElementCache(bool onlyIfNecessary)1636 GMSH_API void gmsh::model::mesh::rebuildElementCache(bool onlyIfNecessary)
1637 {
1638 if(!_checkInit()) return;
1639 GModel::current()->rebuildMeshElementCache(onlyIfNecessary);
1640 }
1641
1642 GMSH_API void
getNodesForPhysicalGroup(const int dim,const int tag,std::vector<std::size_t> & nodeTags,std::vector<double> & coord)1643 gmsh::model::mesh::getNodesForPhysicalGroup(const int dim, const int tag,
1644 std::vector<std::size_t> &nodeTags,
1645 std::vector<double> &coord)
1646 {
1647 if(!_checkInit()) return;
1648 nodeTags.clear();
1649 coord.clear();
1650 std::vector<MVertex *> v;
1651 GModel::current()->getMeshVerticesForPhysicalGroup(dim, tag, v);
1652 if(v.empty()) return;
1653 nodeTags.resize(v.size());
1654 coord.resize(v.size() * 3);
1655 for(std::size_t i = 0; i < v.size(); i++) {
1656 nodeTags[i] = v[i]->getNum();
1657 coord[3 * i + 0] = v[i]->x();
1658 coord[3 * i + 1] = v[i]->y();
1659 coord[3 * i + 2] = v[i]->z();
1660 }
1661 }
1662
getMaxNodeTag(std::size_t & maxTag)1663 GMSH_API void gmsh::model::mesh::getMaxNodeTag(std::size_t &maxTag)
1664 {
1665 if(!_checkInit()) return;
1666 maxTag = GModel::current()->getMaxVertexNumber();
1667 }
1668
addNodes(const int dim,const int tag,const std::vector<std::size_t> & nodeTags,const std::vector<double> & coord,const std::vector<double> & parametricCoord)1669 GMSH_API void gmsh::model::mesh::addNodes(
1670 const int dim, const int tag, const std::vector<std::size_t> &nodeTags,
1671 const std::vector<double> &coord, const std::vector<double> ¶metricCoord)
1672 {
1673 if(!_checkInit()) return;
1674 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
1675 if(!ge) {
1676 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
1677 return;
1678 }
1679 int numNodeTags = nodeTags.size(), numNodes = nodeTags.size();
1680 if(!numNodeTags) { // this is allowed: we will assign new tags
1681 numNodes = coord.size() / 3;
1682 }
1683 if((int)coord.size() != 3 * numNodes) {
1684 Msg::Error("Wrong number of coordinates");
1685 return;
1686 }
1687 bool param = false;
1688 if(parametricCoord.size()) {
1689 if((int)parametricCoord.size() != dim * numNodes) {
1690 Msg::Error("Wrong number of parametric coordinates");
1691 return;
1692 }
1693 param = true;
1694 }
1695 for(int i = 0; i < numNodes; i++) {
1696 std::size_t tag = (numNodeTags ? nodeTags[i] : 0); // 0 = automatic tag
1697 double x = coord[3 * i];
1698 double y = coord[3 * i + 1];
1699 double z = coord[3 * i + 2];
1700 MVertex *vv = nullptr;
1701 if(param && dim == 1) {
1702 double u = parametricCoord[i];
1703 vv = new MEdgeVertex(x, y, z, ge, u, tag);
1704 }
1705 else if(param && dim == 2) {
1706 double u = parametricCoord[2 * i];
1707 double v = parametricCoord[2 * i + 1];
1708 vv = new MFaceVertex(x, y, z, ge, u, v, tag);
1709 }
1710 else
1711 vv = new MVertex(x, y, z, ge, tag);
1712 ge->mesh_vertices.push_back(vv);
1713 }
1714 GModel::current()->destroyMeshCaches();
1715 }
1716
reclassifyNodes()1717 GMSH_API void gmsh::model::mesh::reclassifyNodes()
1718 {
1719 if(!_checkInit()) return;
1720 GModel::current()->pruneMeshVertexAssociations();
1721 }
1722
relocateNodes(const int dim,const int tag)1723 GMSH_API void gmsh::model::mesh::relocateNodes(const int dim, const int tag)
1724 {
1725 if(!_checkInit()) return;
1726 std::vector<GEntity *> entities;
1727 if(dim >= 0 && tag >= 0) {
1728 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
1729 if(!ge) {
1730 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
1731 return;
1732 }
1733 entities.push_back(ge);
1734 }
1735 else {
1736 GModel::current()->getEntities(entities, dim);
1737 }
1738 for(std::size_t i = 0; i < entities.size(); i++)
1739 entities[i]->relocateMeshVertices();
1740 }
1741
1742 static void
_getEntitiesForElementTypes(int dim,int tag,std::map<int,std::vector<GEntity * >> & typeEnt)1743 _getEntitiesForElementTypes(int dim, int tag,
1744 std::map<int, std::vector<GEntity *> > &typeEnt)
1745 {
1746 std::vector<GEntity *> entities;
1747 if(dim >= 0 && tag >= 0) {
1748 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
1749 if(!ge) {
1750 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
1751 return;
1752 }
1753 entities.push_back(ge);
1754 }
1755 else {
1756 GModel::current()->getEntities(entities, dim);
1757 }
1758 for(std::size_t i = 0; i < entities.size(); i++) {
1759 GEntity *ge = entities[i];
1760 switch(ge->dim()) {
1761 case 0: {
1762 GVertex *v = static_cast<GVertex *>(ge);
1763 if(v->points.size())
1764 typeEnt[v->points.front()->getTypeForMSH()].push_back(ge);
1765 break;
1766 }
1767 case 1: {
1768 GEdge *e = static_cast<GEdge *>(ge);
1769 if(e->lines.size())
1770 typeEnt[e->lines.front()->getTypeForMSH()].push_back(ge);
1771 break;
1772 }
1773 case 2: {
1774 GFace *f = static_cast<GFace *>(ge);
1775 if(f->triangles.size())
1776 typeEnt[f->triangles.front()->getTypeForMSH()].push_back(ge);
1777 if(f->quadrangles.size())
1778 typeEnt[f->quadrangles.front()->getTypeForMSH()].push_back(ge);
1779 break;
1780 }
1781 case 3: {
1782 GRegion *r = static_cast<GRegion *>(ge);
1783 if(r->tetrahedra.size())
1784 typeEnt[r->tetrahedra.front()->getTypeForMSH()].push_back(ge);
1785 if(r->hexahedra.size())
1786 typeEnt[r->hexahedra.front()->getTypeForMSH()].push_back(ge);
1787 if(r->prisms.size())
1788 typeEnt[r->prisms.front()->getTypeForMSH()].push_back(ge);
1789 if(r->pyramids.size())
1790 typeEnt[r->pyramids.front()->getTypeForMSH()].push_back(ge);
1791 break;
1792 }
1793 }
1794 }
1795 }
1796
getElements(std::vector<int> & elementTypes,std::vector<std::vector<std::size_t>> & elementTags,std::vector<std::vector<std::size_t>> & nodeTags,const int dim,const int tag)1797 GMSH_API void gmsh::model::mesh::getElements(
1798 std::vector<int> &elementTypes,
1799 std::vector<std::vector<std::size_t> > &elementTags,
1800 std::vector<std::vector<std::size_t> > &nodeTags, const int dim,
1801 const int tag)
1802 {
1803 if(!_checkInit()) return;
1804 elementTypes.clear();
1805 elementTags.clear();
1806 nodeTags.clear();
1807 std::map<int, std::vector<GEntity *> > typeEnt;
1808 _getEntitiesForElementTypes(dim, tag, typeEnt);
1809 for(auto it = typeEnt.begin(); it != typeEnt.end(); it++) {
1810 elementTypes.push_back(it->first);
1811 elementTags.push_back(std::vector<std::size_t>());
1812 nodeTags.push_back(std::vector<std::size_t>());
1813 int elementType = it->first;
1814 for(std::size_t i = 0; i < it->second.size(); i++) {
1815 GEntity *ge = it->second[i];
1816 for(std::size_t j = 0; j < ge->getNumMeshElements(); j++) {
1817 MElement *e = ge->getMeshElement(j);
1818 if(e->getTypeForMSH() == elementType) {
1819 elementTags.back().push_back(e->getNum());
1820 for(std::size_t k = 0; k < e->getNumVertices(); k++) {
1821 nodeTags.back().push_back(e->getVertex(k)->getNum());
1822 }
1823 }
1824 }
1825 }
1826 }
1827 }
1828
getElement(const std::size_t elementTag,int & elementType,std::vector<std::size_t> & nodeTags,int & dim,int & tag)1829 GMSH_API void gmsh::model::mesh::getElement(const std::size_t elementTag,
1830 int &elementType,
1831 std::vector<std::size_t> &nodeTags,
1832 int &dim, int &tag)
1833 {
1834 if(!_checkInit()) return;
1835 int entityTag;
1836 MElement *e = GModel::current()->getMeshElementByTag(elementTag, entityTag);
1837 if(!e) {
1838 Msg::Error("Unknown element %d", elementTag);
1839 return;
1840 }
1841 elementType = e->getTypeForMSH();
1842 nodeTags.clear();
1843 for(std::size_t i = 0; i < e->getNumVertices(); i++) {
1844 MVertex *v = e->getVertex(i);
1845 if(!v) {
1846 Msg::Error("Unknown node in element %d", elementTag);
1847 return;
1848 }
1849 nodeTags.push_back(v->getNum());
1850 }
1851 dim = e->getDim();
1852 tag = entityTag;
1853 }
1854
getElementByCoordinates(const double x,const double y,const double z,std::size_t & elementTag,int & elementType,std::vector<std::size_t> & nodeTags,double & u,double & v,double & w,const int dim,const bool strict)1855 GMSH_API void gmsh::model::mesh::getElementByCoordinates(
1856 const double x, const double y, const double z, std::size_t &elementTag,
1857 int &elementType, std::vector<std::size_t> &nodeTags, double &u, double &v,
1858 double &w, const int dim, const bool strict)
1859 {
1860 if(!_checkInit()) return;
1861 SPoint3 xyz(x, y, z), uvw;
1862 MElement *e = GModel::current()->getMeshElementByCoord(xyz, uvw, dim, strict);
1863 if(!e) {
1864 Msg::Error("No element found at (%g, %g, %g)", x, y, z);
1865 return;
1866 }
1867 elementTag = e->getNum();
1868 elementType = e->getTypeForMSH();
1869 nodeTags.clear();
1870 for(std::size_t i = 0; i < e->getNumVertices(); i++) {
1871 MVertex *v = e->getVertex(i);
1872 if(!v) {
1873 Msg::Error("Unknown node in element %d", elementTag);
1874 return;
1875 }
1876 nodeTags.push_back(v->getNum());
1877 }
1878 u = uvw.x();
1879 v = uvw.y();
1880 w = uvw.z();
1881 }
1882
getElementsByCoordinates(const double x,const double y,const double z,std::vector<std::size_t> & elementTags,const int dim,const bool strict)1883 GMSH_API void gmsh::model::mesh::getElementsByCoordinates(
1884 const double x, const double y, const double z,
1885 std::vector<std::size_t> &elementTags, const int dim, const bool strict)
1886 {
1887 if(!_checkInit()) return;
1888 SPoint3 xyz(x, y, z), uvw;
1889 elementTags.clear();
1890 std::vector<MElement *> e =
1891 GModel::current()->getMeshElementsByCoord(xyz, dim, strict);
1892 if(e.empty()) {
1893 Msg::Error("No element found at (%g, %g, %g)", x, y, z);
1894 return;
1895 }
1896 for(std::size_t i = 0; i < e.size(); i++) {
1897 elementTags.push_back(e[i]->getNum());
1898 }
1899 }
1900
getLocalCoordinatesInElement(const std::size_t elementTag,const double x,const double y,const double z,double & u,double & v,double & w)1901 GMSH_API void gmsh::model::mesh::getLocalCoordinatesInElement(
1902 const std::size_t elementTag, const double x, const double y, const double z,
1903 double &u, double &v, double &w)
1904 {
1905 if(!_checkInit()) return;
1906 MElement *e = GModel::current()->getMeshElementByTag(elementTag);
1907 if(!e) {
1908 Msg::Error("Unknown element %d", elementTag);
1909 return;
1910 }
1911 double xyz[3] = {x, y, z}, uvw[3];
1912 e->xyz2uvw(xyz, uvw);
1913 u = uvw[0];
1914 v = uvw[1];
1915 w = uvw[2];
1916 }
1917
1918 template <class T>
_addElements(int dim,int tag,const std::vector<MElement * > & src,std::vector<T * > & dst)1919 static void _addElements(int dim, int tag, const std::vector<MElement *> &src,
1920 std::vector<T *> &dst)
1921 {
1922 for(std::size_t i = 0; i < src.size(); i++)
1923 dst.push_back(static_cast<T *>(src[i]));
1924 }
1925
_addElements(int dim,int tag,GEntity * ge,int type,const std::vector<std::size_t> & elementTags,const std::vector<std::size_t> & nodeTags)1926 static void _addElements(int dim, int tag, GEntity *ge, int type,
1927 const std::vector<std::size_t> &elementTags,
1928 const std::vector<std::size_t> &nodeTags)
1929 {
1930 unsigned int numNodesPerEle = MElement::getInfoMSH(type);
1931 if(!numNodesPerEle) return;
1932 std::size_t numEleTags = elementTags.size();
1933 std::size_t numEle = numEleTags;
1934 if(!numEle) { numEle = nodeTags.size() / numNodesPerEle; }
1935 if(!numEle) return;
1936 if(numEle * numNodesPerEle != nodeTags.size()) {
1937 Msg::Error("Wrong number of node tags for element type %d", type);
1938 return;
1939 }
1940 std::vector<MElement *> elements(numEle);
1941 std::vector<MVertex *> nodes(numNodesPerEle);
1942 for(std::size_t j = 0; j < numEle; j++) {
1943 std::size_t etag = (numEleTags ? elementTags[j] : 0); // 0 = automatic tag
1944 MElementFactory f;
1945 for(std::size_t k = 0; k < numNodesPerEle; k++) {
1946 std::size_t vtag = nodeTags[numNodesPerEle * j + k];
1947 // this will rebuild the node cache if necessary
1948 nodes[k] = GModel::current()->getMeshVertexByTag(vtag);
1949 if(!nodes[k]) {
1950 Msg::Error("Unknown node %d", vtag);
1951 return;
1952 }
1953 }
1954 elements[j] = f.create(type, nodes, etag);
1955 }
1956 bool ok = true;
1957 switch(dim) {
1958 case 0:
1959 if(elements[0]->getType() == TYPE_PNT)
1960 _addElements(dim, tag, elements, static_cast<GVertex *>(ge)->points);
1961 else
1962 ok = false;
1963 break;
1964 case 1:
1965 if(elements[0]->getType() == TYPE_LIN)
1966 _addElements(dim, tag, elements, static_cast<GEdge *>(ge)->lines);
1967 else
1968 ok = false;
1969 break;
1970 case 2:
1971 if(elements[0]->getType() == TYPE_TRI)
1972 _addElements(dim, tag, elements, static_cast<GFace *>(ge)->triangles);
1973 else if(elements[0]->getType() == TYPE_QUA)
1974 _addElements(dim, tag, elements, static_cast<GFace *>(ge)->quadrangles);
1975 else
1976 ok = false;
1977 break;
1978 case 3:
1979 if(elements[0]->getType() == TYPE_TET)
1980 _addElements(dim, tag, elements, static_cast<GRegion *>(ge)->tetrahedra);
1981 else if(elements[0]->getType() == TYPE_HEX)
1982 _addElements(dim, tag, elements, static_cast<GRegion *>(ge)->hexahedra);
1983 else if(elements[0]->getType() == TYPE_PRI)
1984 _addElements(dim, tag, elements, static_cast<GRegion *>(ge)->prisms);
1985 else if(elements[0]->getType() == TYPE_PYR)
1986 _addElements(dim, tag, elements, static_cast<GRegion *>(ge)->pyramids);
1987 else
1988 ok = false;
1989 break;
1990 }
1991 if(!ok)
1992 Msg::Error("Wrong type of element for %s",
1993 _getEntityName(dim, tag).c_str());
1994 }
1995
getMaxElementTag(std::size_t & maxTag)1996 GMSH_API void gmsh::model::mesh::getMaxElementTag(std::size_t &maxTag)
1997 {
1998 if(!_checkInit()) return;
1999 maxTag = GModel::current()->getMaxElementNumber();
2000 }
2001
addElements(const int dim,const int tag,const std::vector<int> & elementTypes,const std::vector<std::vector<std::size_t>> & elementTags,const std::vector<std::vector<std::size_t>> & nodeTags)2002 GMSH_API void gmsh::model::mesh::addElements(
2003 const int dim, const int tag, const std::vector<int> &elementTypes,
2004 const std::vector<std::vector<std::size_t> > &elementTags,
2005 const std::vector<std::vector<std::size_t> > &nodeTags)
2006 {
2007 if(!_checkInit()) return;
2008 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
2009 if(!ge) {
2010 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
2011 return;
2012 }
2013 if(elementTypes.size() != elementTags.size()) {
2014 Msg::Error("Wrong number of element tags");
2015 return;
2016 }
2017 if(elementTypes.size() != nodeTags.size()) {
2018 Msg::Error("Wrong number of node tags");
2019 return;
2020 }
2021
2022 for(std::size_t i = 0; i < elementTypes.size(); i++)
2023 _addElements(dim, tag, ge, elementTypes[i], elementTags[i], nodeTags[i]);
2024 GModel::current()->destroyMeshCaches();
2025 }
2026
addElementsByType(const int tag,const int elementType,const std::vector<std::size_t> & elementTags,const std::vector<std::size_t> & nodeTags)2027 GMSH_API void gmsh::model::mesh::addElementsByType(
2028 const int tag, const int elementType,
2029 const std::vector<std::size_t> &elementTags,
2030 const std::vector<std::size_t> &nodeTags)
2031 {
2032 if(!_checkInit()) return;
2033 int dim = ElementType::getDimension(elementType);
2034 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
2035 if(!ge) {
2036 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
2037 return;
2038 }
2039 _addElements(dim, tag, ge, elementType, elementTags, nodeTags);
2040 GModel::current()->destroyMeshCaches();
2041 }
2042
getElementTypes(std::vector<int> & elementTypes,const int dim,const int tag)2043 GMSH_API void gmsh::model::mesh::getElementTypes(std::vector<int> &elementTypes,
2044 const int dim, const int tag)
2045 {
2046 if(!_checkInit()) return;
2047 elementTypes.clear();
2048 std::map<int, std::vector<GEntity *> > typeEnt;
2049 _getEntitiesForElementTypes(dim, tag, typeEnt);
2050 for(auto it = typeEnt.begin(); it != typeEnt.end(); it++) {
2051 elementTypes.push_back(it->first);
2052 }
2053 }
2054
getElementType(const std::string & family,const int order,const bool serendip)2055 GMSH_API int gmsh::model::mesh::getElementType(const std::string &family,
2056 const int order,
2057 const bool serendip)
2058 {
2059 if(!_checkInit()) return -1;
2060 int familyType =
2061 (family == "Point" || family == "point") ? TYPE_PNT :
2062 (family == "Line" || family == "line") ? TYPE_LIN :
2063 (family == "Triangle" || family == "triangle") ? TYPE_TRI :
2064 (family == "Quadrangle" || family == "quadrangle") ? TYPE_QUA :
2065 (family == "Tetrahedron" || family == "tetrahedron") ? TYPE_TET :
2066 (family == "Pyramid" || family == "pyramid") ? TYPE_PYR :
2067 (family == "Prism" || family == "prism") ? TYPE_PRI :
2068 (family == "Hexahedron" || family == "hexahedron") ? TYPE_HEX :
2069 (family == "Polygon" || family == "polygon") ? TYPE_POLYG :
2070 (family == "Polyhedron" || family == "polyhedron") ? TYPE_POLYH :
2071 (family == "Trihedron" || family == "trihedron") ? TYPE_TRIH :
2072 -1;
2073 return ElementType::getType(familyType, order, serendip);
2074 }
2075
getElementProperties(const int elementType,std::string & name,int & dim,int & order,int & numNodes,std::vector<double> & localNodeCoord,int & numPrimaryNodes)2076 GMSH_API void gmsh::model::mesh::getElementProperties(
2077 const int elementType, std::string &name, int &dim, int &order, int &numNodes,
2078 std::vector<double> &localNodeCoord, int &numPrimaryNodes)
2079 {
2080 if(!_checkInit()) return;
2081 const char *n;
2082 MElement::getInfoMSH(elementType, &n);
2083 name = n;
2084 int parentType = ElementType::getParentType(elementType);
2085 nodalBasis *basis = nullptr;
2086 if(parentType == TYPE_PYR)
2087 basis = new pyramidalBasis(elementType);
2088 else
2089 basis = new polynomialBasis(elementType);
2090 dim = basis->dimension;
2091 order = basis->order;
2092 numNodes = basis->points.size1();
2093 if(numNodes != ElementType::getNumVertices(elementType)) {
2094 Msg::Error("Size of basis incompatible with element type");
2095 return;
2096 }
2097 for(int i = 0; i < basis->points.size1(); i++)
2098 for(int j = 0; j < basis->points.size2(); j++)
2099 localNodeCoord.push_back(basis->points(i, j));
2100 delete basis;
2101 numPrimaryNodes =
2102 ElementType::getNumVertices(ElementType::getPrimaryType(elementType));
2103 }
2104
getElementsByType(const int elementType,std::vector<std::size_t> & elementTags,std::vector<std::size_t> & nodeTags,const int tag,const std::size_t task,const std::size_t numTasks)2105 GMSH_API void gmsh::model::mesh::getElementsByType(
2106 const int elementType, std::vector<std::size_t> &elementTags,
2107 std::vector<std::size_t> &nodeTags, const int tag, const std::size_t task,
2108 const std::size_t numTasks)
2109 {
2110 if(!_checkInit()) return;
2111 int dim = ElementType::getDimension(elementType);
2112 std::map<int, std::vector<GEntity *> > typeEnt;
2113 _getEntitiesForElementTypes(dim, tag, typeEnt);
2114 const std::vector<GEntity *> &entities(typeEnt[elementType]);
2115 int familyType = ElementType::getParentType(elementType);
2116 std::size_t numElements = 0;
2117 for(std::size_t i = 0; i < entities.size(); i++)
2118 numElements += entities[i]->getNumMeshElementsByType(familyType);
2119 const int numNodes = ElementType::getNumVertices(elementType);
2120 if(!numTasks) {
2121 Msg::Error("Number of tasks should be > 0");
2122 return;
2123 }
2124 const std::size_t begin = (task * numElements) / numTasks;
2125 const std::size_t end = ((task + 1) * numElements) / numTasks;
2126 // check arrays
2127 bool haveElementTags = elementTags.size();
2128 bool haveNodeTags = nodeTags.size();
2129 if(!haveElementTags && !haveNodeTags) {
2130 if(numTasks > 1)
2131 Msg::Warning("ElementTags and nodeTags should be preallocated "
2132 "if numTasks > 1");
2133 haveElementTags = haveNodeTags = true;
2134 preallocateElementsByType(elementType, haveElementTags, haveNodeTags,
2135 elementTags, nodeTags, tag);
2136 }
2137 if(haveElementTags && (elementTags.size() < numElements)) {
2138 Msg::Error("Wrong size of elementTags array (%d < %d)", elementTags.size(),
2139 numElements);
2140 return;
2141 }
2142 if(haveNodeTags && (nodeTags.size() < numElements * numNodes)) {
2143 Msg::Error("Wrong size of nodeTags array (%d < %d)", nodeTags.size(),
2144 numElements * numNodes);
2145 return;
2146 }
2147 size_t o = 0;
2148 size_t idx = begin * numNodes;
2149 for(std::size_t i = 0; i < entities.size(); i++) {
2150 GEntity *ge = entities[i];
2151 for(std::size_t j = 0; j < ge->getNumMeshElementsByType(familyType); j++) {
2152 if(o >= begin && o < end) {
2153 MElement *e = ge->getMeshElementByType(familyType, j);
2154 if(haveElementTags) elementTags[o] = e->getNum();
2155 if(haveNodeTags) {
2156 for(std::size_t k = 0; k < e->getNumVertices(); k++) {
2157 nodeTags[idx++] = e->getVertex(k)->getNum();
2158 }
2159 }
2160 }
2161 o++;
2162 }
2163 }
2164 }
2165
preallocateElementsByType(const int elementType,const bool elementTag,const bool nodeTag,std::vector<std::size_t> & elementTags,std::vector<std::size_t> & nodeTags,const int tag)2166 GMSH_API void gmsh::model::mesh::preallocateElementsByType(
2167 const int elementType, const bool elementTag, const bool nodeTag,
2168 std::vector<std::size_t> &elementTags, std::vector<std::size_t> &nodeTags,
2169 const int tag)
2170 {
2171 if(!_checkInit()) return;
2172 int dim = ElementType::getDimension(elementType);
2173 std::map<int, std::vector<GEntity *> > typeEnt;
2174 _getEntitiesForElementTypes(dim, tag, typeEnt);
2175 const std::vector<GEntity *> &entities(typeEnt[elementType]);
2176 int familyType = ElementType::getParentType(elementType);
2177 std::size_t numElements = 0;
2178 for(std::size_t i = 0; i < entities.size(); i++)
2179 numElements += entities[i]->getNumMeshElementsByType(familyType);
2180 const int numNodesPerEle = ElementType::getNumVertices(elementType);
2181 if(!numElements) return;
2182 if(elementTag) {
2183 elementTags.clear();
2184 elementTags.resize(numElements, 0);
2185 }
2186 if(nodeTag) {
2187 nodeTags.clear();
2188 nodeTags.resize(numElements * numNodesPerEle, 0);
2189 }
2190 }
2191
_getFunctionSpaceInfo(const std::string & fsType,std::string & fsName,int & fsOrder,int & fsComp)2192 static bool _getFunctionSpaceInfo(const std::string &fsType,
2193 std::string &fsName, int &fsOrder,
2194 int &fsComp)
2195 {
2196 if(fsType.empty() || fsType == "None") {
2197 fsName = "";
2198 fsOrder = 0;
2199 fsComp = 0;
2200 return true;
2201 }
2202 if(fsType.size() > 8 && fsType.substr(0,8) == "Lagrange") {
2203 fsName = "Lagrange";
2204 fsOrder = atoi(fsType.substr(8).c_str());
2205 fsComp = 1;
2206 return true;
2207 }
2208 if(fsType.size() > 12 && fsType.substr(0,12) == "GradLagrange") {
2209 fsName = "GradLagrange";
2210 fsOrder = atoi(fsType.substr(12).c_str());
2211 fsComp = 3;
2212 return true;
2213 }
2214 if(fsType == "IsoParametric" || fsType == "Lagrange") {
2215 fsName = "Lagrange";
2216 fsOrder = -1;
2217 fsComp = 1;
2218 return true;
2219 }
2220 if(fsType == "GradIsoParametric" || fsType == "GradLagrange") {
2221 fsName = "GradLagrange";
2222 fsOrder = -1;
2223 fsComp = 3;
2224 return true;
2225 }
2226 if(fsType.substr(0, 10) == "H1Legendre") {
2227 fsName = "H1Legendre";
2228 fsOrder = atoi(fsType.substr(10).c_str());
2229 fsComp = 1;
2230 return true;
2231 }
2232 if(fsType.substr(0, 14) == "GradH1Legendre") {
2233 fsName = "GradH1Legendre";
2234 fsOrder = atoi(fsType.substr(14).c_str());
2235 fsComp = 3;
2236 return true;
2237 }
2238 if(fsType.substr(0, 13) == "HcurlLegendre") {
2239 fsName = "HcurlLegendre";
2240 fsOrder = atoi(fsType.substr(13).c_str());
2241 fsComp = 3;
2242 return true;
2243 }
2244 if(fsType.substr(0, 17) == "CurlHcurlLegendre") {
2245 fsName = "CurlHcurlLegendre";
2246 fsOrder = atoi(fsType.substr(17).c_str());
2247 fsComp = 3;
2248 return true;
2249 }
2250 return false;
2251 }
2252
getJacobians(const int elementType,const std::vector<double> & localCoord,std::vector<double> & jacobians,std::vector<double> & determinants,std::vector<double> & coord,const int tag,const std::size_t task,const std::size_t numTasks)2253 GMSH_API void gmsh::model::mesh::getJacobians(
2254 const int elementType, const std::vector<double> &localCoord,
2255 std::vector<double> &jacobians, std::vector<double> &determinants,
2256 std::vector<double> &coord, const int tag, const std::size_t task,
2257 const std::size_t numTasks)
2258 {
2259 if(!_checkInit()) return;
2260 int dim = ElementType::getDimension(elementType);
2261 std::map<int, std::vector<GEntity *> > typeEnt;
2262 _getEntitiesForElementTypes(dim, tag, typeEnt);
2263 const std::vector<GEntity *> &entities(typeEnt[elementType]);
2264 int familyType = ElementType::getParentType(elementType);
2265 int numPoints = localCoord.size() / 3;
2266 if(!numPoints) {
2267 Msg::Warning("No evaluation points in getJacobians");
2268 return;
2269 }
2270
2271 // check arrays
2272 bool haveJacobians = jacobians.size();
2273 bool haveDeterminants = determinants.size();
2274 bool havePoints = coord.size();
2275 if(!haveDeterminants && !haveJacobians && !havePoints) {
2276 if(numTasks > 1)
2277 Msg::Warning("Jacobians, determinants and points should be preallocated "
2278 "if numTasks > 1");
2279 haveJacobians = haveDeterminants = havePoints = true;
2280 preallocateJacobians(elementType, numPoints, haveJacobians,
2281 haveDeterminants, havePoints, jacobians, determinants,
2282 coord, tag);
2283 }
2284 // get data
2285 {
2286 std::size_t numElements = 0;
2287 for(std::size_t i = 0; i < entities.size(); i++) {
2288 GEntity *ge = entities[i];
2289 numElements += ge->getNumMeshElementsByType(familyType);
2290 }
2291 if(!numTasks) {
2292 Msg::Error("Number of tasks should be > 0");
2293 return;
2294 }
2295 const size_t begin = (task * numElements) / numTasks;
2296 const size_t end = ((task + 1) * numElements) / numTasks;
2297 if(haveDeterminants && (end * numPoints > determinants.size())) {
2298 Msg::Error("Wrong size of determinants array (%d < %d)",
2299 determinants.size(), end * numPoints);
2300 return;
2301 }
2302 if(haveJacobians && (9 * end * numPoints > jacobians.size())) {
2303 Msg::Error("Wrong size of jacobians array (%d < %d)", jacobians.size(),
2304 9 * end * numPoints);
2305 return;
2306 }
2307 if(havePoints && (3 * end * numPoints > coord.size())) {
2308 Msg::Error("Wrong size of points array (%d < %d)", coord.size(),
2309 3 * end * numPoints);
2310 return;
2311 }
2312 if(haveDeterminants && haveJacobians && havePoints) {
2313 std::vector<std::vector<SVector3> > gsf;
2314 size_t o = 0;
2315 size_t idx = begin * numPoints;
2316 for(std::size_t i = 0; i < entities.size(); i++) {
2317 GEntity *ge = entities[i];
2318 for(std::size_t j = 0; j < ge->getNumMeshElementsByType(familyType);
2319 j++) {
2320 if(o >= begin && o < end) {
2321 MElement *e = ge->getMeshElementByType(familyType, j);
2322 if(gsf.size() == 0) {
2323 gsf.resize(numPoints);
2324 for(int k = 0; k < numPoints; k++) {
2325 double value[1256][3];
2326 e->getGradShapeFunctions(localCoord[3 * k],
2327 localCoord[3 * k + 1],
2328 localCoord[3 * k + 2], value);
2329 gsf[k].resize(e->getNumShapeFunctions());
2330 for(std::size_t l = 0; l < e->getNumShapeFunctions(); l++) {
2331 gsf[k][l][0] = value[l][0];
2332 gsf[k][l][1] = value[l][1];
2333 gsf[k][l][2] = value[l][2];
2334 }
2335 }
2336 }
2337 for(int k = 0; k < numPoints; k++) {
2338 e->pnt(localCoord[3 * k], localCoord[3 * k + 1],
2339 localCoord[3 * k + 2], &coord[idx * 3]);
2340 determinants[idx] = e->getJacobian(gsf[k], &jacobians[idx * 9]);
2341 idx++;
2342 }
2343 }
2344 o++;
2345 }
2346 }
2347 }
2348 else if(haveDeterminants && haveJacobians && !havePoints) {
2349 std::vector<std::vector<SVector3> > gsf;
2350 size_t o = 0;
2351 size_t idx = begin * numPoints;
2352 for(std::size_t i = 0; i < entities.size(); i++) {
2353 GEntity *ge = entities[i];
2354 for(std::size_t j = 0; j < ge->getNumMeshElementsByType(familyType);
2355 j++) {
2356 if(o >= begin && o < end) {
2357 MElement *e = ge->getMeshElementByType(familyType, j);
2358 if(gsf.size() == 0) {
2359 gsf.resize(numPoints);
2360 for(int k = 0; k < numPoints; k++) {
2361 double value[1256][3];
2362 e->getGradShapeFunctions(localCoord[3 * k],
2363 localCoord[3 * k + 1],
2364 localCoord[3 * k + 2], value);
2365 gsf[k].resize(e->getNumShapeFunctions());
2366 for(std::size_t l = 0; l < e->getNumShapeFunctions(); l++) {
2367 gsf[k][l][0] = value[l][0];
2368 gsf[k][l][1] = value[l][1];
2369 gsf[k][l][2] = value[l][2];
2370 }
2371 }
2372 }
2373 for(int k = 0; k < numPoints; k++) {
2374 determinants[idx] = e->getJacobian(gsf[k], &jacobians[idx * 9]);
2375 idx++;
2376 }
2377 }
2378 o++;
2379 }
2380 }
2381 }
2382 else if(haveDeterminants && !haveJacobians && havePoints) {
2383 std::vector<double> jac(9, 0.);
2384 std::vector<std::vector<SVector3> > gsf;
2385 size_t o = 0;
2386 size_t idx = begin * numPoints;
2387 for(std::size_t i = 0; i < entities.size(); i++) {
2388 GEntity *ge = entities[i];
2389 for(std::size_t j = 0; j < ge->getNumMeshElementsByType(familyType);
2390 j++) {
2391 if(o >= begin && o < end) {
2392 MElement *e = ge->getMeshElementByType(familyType, j);
2393 if(gsf.size() == 0) {
2394 gsf.resize(numPoints);
2395 for(int k = 0; k < numPoints; k++) {
2396 double value[1256][3];
2397 e->getGradShapeFunctions(localCoord[3 * k],
2398 localCoord[3 * k + 1],
2399 localCoord[3 * k + 2], value);
2400 gsf[k].resize(e->getNumShapeFunctions());
2401 for(std::size_t l = 0; l < e->getNumShapeFunctions(); l++) {
2402 gsf[k][l][0] = value[l][0];
2403 gsf[k][l][1] = value[l][1];
2404 gsf[k][l][2] = value[l][2];
2405 }
2406 }
2407 }
2408 for(int k = 0; k < numPoints; k++) {
2409 e->pnt(localCoord[3 * k], localCoord[3 * k + 1],
2410 localCoord[3 * k + 2], &coord[idx * 3]);
2411 determinants[idx] = e->getJacobian(gsf[k], &jac[0]);
2412 idx++;
2413 }
2414 }
2415 o++;
2416 }
2417 }
2418 }
2419 else if(haveDeterminants && !haveJacobians && !havePoints) {
2420 std::vector<double> jac(9, 0.);
2421 std::vector<std::vector<SVector3> > gsf;
2422 size_t o = 0;
2423 size_t idx = begin * numPoints;
2424 for(std::size_t i = 0; i < entities.size(); i++) {
2425 GEntity *ge = entities[i];
2426 for(std::size_t j = 0; j < ge->getNumMeshElementsByType(familyType);
2427 j++) {
2428 if(o >= begin && o < end) {
2429 MElement *e = ge->getMeshElementByType(familyType, j);
2430 if(gsf.size() == 0) {
2431 gsf.resize(numPoints);
2432 for(int k = 0; k < numPoints; k++) {
2433 double value[1256][3];
2434 e->getGradShapeFunctions(localCoord[3 * k],
2435 localCoord[3 * k + 1],
2436 localCoord[3 * k + 2], value);
2437 gsf[k].resize(e->getNumShapeFunctions());
2438 for(std::size_t l = 0; l < e->getNumShapeFunctions(); l++) {
2439 gsf[k][l][0] = value[l][0];
2440 gsf[k][l][1] = value[l][1];
2441 gsf[k][l][2] = value[l][2];
2442 }
2443 }
2444 }
2445 for(int k = 0; k < numPoints; k++) {
2446 determinants[idx] = e->getJacobian(gsf[k], &jac[0]);
2447 idx++;
2448 }
2449 }
2450 o++;
2451 }
2452 }
2453 }
2454 else if(!haveDeterminants && haveJacobians && !havePoints) {
2455 std::vector<std::vector<SVector3> > gsf;
2456 size_t o = 0;
2457 size_t idx = begin * numPoints;
2458 for(std::size_t i = 0; i < entities.size(); i++) {
2459 GEntity *ge = entities[i];
2460 for(std::size_t j = 0; j < ge->getNumMeshElementsByType(familyType);
2461 j++) {
2462 if(o >= begin && o < end) {
2463 MElement *e = ge->getMeshElementByType(familyType, j);
2464 if(gsf.size() == 0) {
2465 gsf.resize(numPoints);
2466 for(int k = 0; k < numPoints; k++) {
2467 double value[1256][3];
2468 e->getGradShapeFunctions(localCoord[3 * k],
2469 localCoord[3 * k + 1],
2470 localCoord[3 * k + 2], value);
2471 gsf[k].resize(e->getNumShapeFunctions());
2472 for(std::size_t l = 0; l < e->getNumShapeFunctions(); l++) {
2473 gsf[k][l][0] = value[l][0];
2474 gsf[k][l][1] = value[l][1];
2475 gsf[k][l][2] = value[l][2];
2476 }
2477 }
2478 }
2479 for(int k = 0; k < numPoints; k++) {
2480 e->getJacobian(gsf[k], &jacobians[idx * 9]);
2481 idx++;
2482 }
2483 }
2484 o++;
2485 }
2486 }
2487 }
2488 else {
2489 Msg::Error("The case with 'haveDeterminants = %s', `haveJacobians = %s` "
2490 "and 'havePoints = %s' is not yet implemented",
2491 (haveDeterminants ? "true" : "false"),
2492 (haveJacobians ? "true" : "false"),
2493 (havePoints ? "true" : "false"));
2494 return;
2495 }
2496 // Add other combinaisons if necessary
2497 }
2498 }
2499
preallocateJacobians(const int elementType,const int numPoints,const bool allocateJacobians,const bool allocateDeterminants,const bool allocateCoord,std::vector<double> & jacobians,std::vector<double> & determinants,std::vector<double> & coord,const int tag)2500 GMSH_API void gmsh::model::mesh::preallocateJacobians(
2501 const int elementType, const int numPoints, const bool allocateJacobians,
2502 const bool allocateDeterminants, const bool allocateCoord,
2503 std::vector<double> &jacobians, std::vector<double> &determinants,
2504 std::vector<double> &coord, const int tag)
2505 {
2506 if(!_checkInit()) return;
2507 int dim = ElementType::getDimension(elementType);
2508 BasisFactory::getNodalBasis(elementType);
2509 std::map<int, std::vector<GEntity *> > typeEnt;
2510 _getEntitiesForElementTypes(dim, tag, typeEnt);
2511 const std::vector<GEntity *> &entities(typeEnt[elementType]);
2512 int familyType = ElementType::getParentType(elementType);
2513 std::size_t numElements = 0;
2514 for(std::size_t i = 0; i < entities.size(); i++)
2515 numElements += entities[i]->getNumMeshElementsByType(familyType);
2516 if(!numElements) return;
2517 if(allocateJacobians) {
2518 jacobians.clear();
2519 jacobians.resize(9 * numElements * numPoints);
2520 }
2521 if(allocateDeterminants) {
2522 determinants.clear();
2523 determinants.resize(numElements * numPoints);
2524 }
2525 if(allocateCoord) {
2526 coord.clear();
2527 coord.resize(3 * numElements * numPoints);
2528 }
2529 }
2530
getJacobian(const std::size_t elementTag,const std::vector<double> & localCoord,std::vector<double> & jacobians,std::vector<double> & determinants,std::vector<double> & coord)2531 GMSH_API void gmsh::model::mesh::getJacobian(
2532 const std::size_t elementTag, const std::vector<double> &localCoord,
2533 std::vector<double> &jacobians, std::vector<double> &determinants,
2534 std::vector<double> &coord)
2535 {
2536 if(!_checkInit()) return;
2537 MElement *e = GModel::current()->getMeshElementByTag(elementTag);
2538 if(!e) {
2539 Msg::Error("Unknown element %d", elementTag);
2540 return;
2541 }
2542 int numPoints = localCoord.size() / 3;
2543 if(!numPoints) {
2544 Msg::Warning("No evaluation points in getJacobian");
2545 return;
2546 }
2547 std::vector<std::vector<SVector3> > gsf;
2548 gsf.resize(numPoints);
2549 jacobians.resize(9 * numPoints);
2550 determinants.resize(numPoints);
2551 coord.resize(3 * numPoints);
2552 for(int k = 0; k < numPoints; k++) {
2553 double value[1256][3];
2554 e->getGradShapeFunctions(localCoord[3 * k], localCoord[3 * k + 1],
2555 localCoord[3 * k + 2], value);
2556 gsf[k].resize(e->getNumShapeFunctions());
2557 for(std::size_t l = 0; l < e->getNumShapeFunctions(); l++) {
2558 gsf[k][l][0] = value[l][0];
2559 gsf[k][l][1] = value[l][1];
2560 gsf[k][l][2] = value[l][2];
2561 }
2562 }
2563 for(int k = 0; k < numPoints; k++) {
2564 e->pnt(localCoord[3 * k], localCoord[3 * k + 1], localCoord[3 * k + 2],
2565 &coord[3 * k]);
2566 determinants[k] = e->getJacobian(gsf[k], &jacobians[9 * k]);
2567 }
2568 }
2569
getBasisFunctions(const int elementType,const std::vector<double> & localCoord,const std::string & functionSpaceType,int & numComponents,std::vector<double> & basisFunctions,int & numOrientations,const std::vector<int> & wantedOrientations)2570 GMSH_API void gmsh::model::mesh::getBasisFunctions(
2571 const int elementType, const std::vector<double> &localCoord,
2572 const std::string &functionSpaceType, int &numComponents,
2573 std::vector<double> &basisFunctions, int &numOrientations,
2574 const std::vector<int> &wantedOrientations)
2575 {
2576 if(!_checkInit()) return;
2577 numComponents = 0;
2578 basisFunctions.clear();
2579 std::string fsName = "";
2580 int fsOrder = 0;
2581 if(!_getFunctionSpaceInfo(functionSpaceType, fsName, fsOrder,
2582 numComponents)) {
2583 Msg::Error("Unknown function space type '%s'", functionSpaceType.c_str());
2584 return;
2585 }
2586
2587 const std::size_t numberOfGaussPoints = localCoord.size() / 3;
2588 const int familyType = ElementType::getParentType(elementType);
2589
2590 if(fsName == "Lagrange" || fsName == "GradLagrange") { // Lagrange type
2591 // Check if there is no error in wantedOrientations
2592 if(wantedOrientations.size() != 0) {
2593 if(wantedOrientations.size() > 1) {
2594 Msg::Error("Asking for more orientation that there exist");
2595 return;
2596 }
2597
2598 if(wantedOrientations[0] != 0) {
2599 Msg::Error(
2600 "Orientation %i does not exist for function stace named '%s' on %s",
2601 wantedOrientations[0], fsName.c_str(),
2602 ElementType::nameOfParentType(familyType, true).c_str());
2603 return;
2604 }
2605 }
2606
2607 const nodalBasis *basis = nullptr;
2608 if(numComponents) {
2609 if(fsOrder == -1) { // isoparametric
2610 basis = BasisFactory::getNodalBasis(elementType);
2611 }
2612 else {
2613 int newType = ElementType::getType(familyType, fsOrder, false);
2614 basis = BasisFactory::getNodalBasis(newType);
2615 }
2616 }
2617 if(basis) {
2618 const std::size_t n = basis->getNumShapeFunctions();
2619 basisFunctions.resize(n * numComponents * numberOfGaussPoints, 0.);
2620 double s[1256], ds[1256][3];
2621 for(std::size_t i = 0; i < numberOfGaussPoints; i++) {
2622 double u = localCoord[i * 3];
2623 double v = localCoord[i * 3 + 1];
2624 double w = localCoord[i * 3 + 2];
2625 switch(numComponents) {
2626 case 1:
2627 basis->f(u, v, w, s);
2628 for(std::size_t j = 0; j < n; j++) basisFunctions[n * i + j] = s[j];
2629 break;
2630 case 3:
2631 basis->df(u, v, w, ds);
2632 for(std::size_t j = 0; j < n; j++) {
2633 basisFunctions[n * 3 * i + 3 * j] = ds[j][0];
2634 basisFunctions[n * 3 * i + 3 * j + 1] = ds[j][1];
2635 basisFunctions[n * 3 * i + 3 * j + 2] = ds[j][2];
2636 }
2637 break;
2638 }
2639 }
2640 }
2641 numOrientations = 1;
2642 }
2643 else { // Hierarchical type
2644 HierarchicalBasis *basis(nullptr);
2645 if(fsName == "H1Legendre" || fsName == "GradH1Legendre") {
2646 switch(familyType) {
2647 case TYPE_HEX: {
2648 basis = new HierarchicalBasisH1Brick(fsOrder);
2649 } break;
2650 case TYPE_PRI: {
2651 basis = new HierarchicalBasisH1Pri(fsOrder);
2652 } break;
2653 case TYPE_TET: {
2654 basis = new HierarchicalBasisH1Tetra(fsOrder);
2655 } break;
2656 case TYPE_QUA: {
2657 basis = new HierarchicalBasisH1Quad(fsOrder);
2658 } break;
2659 case TYPE_TRI: {
2660 basis = new HierarchicalBasisH1Tria(fsOrder);
2661 } break;
2662 case TYPE_LIN: {
2663 basis = new HierarchicalBasisH1Line(fsOrder);
2664 } break;
2665 case TYPE_PNT: {
2666 basis = new HierarchicalBasisH1Point();
2667 } break;
2668 default:
2669 Msg::Error("Unknown familyType %i for basis function type %s",
2670 familyType, fsName.c_str());
2671 return;
2672 }
2673 }
2674 else if(fsName == "HcurlLegendre" || fsName == "CurlHcurlLegendre") {
2675 switch(familyType) {
2676 case TYPE_QUA: {
2677 basis = new HierarchicalBasisHcurlQuad(fsOrder);
2678 } break;
2679 case TYPE_HEX: {
2680 basis = new HierarchicalBasisHcurlBrick(fsOrder);
2681 } break;
2682 case TYPE_TRI: {
2683 basis = new HierarchicalBasisHcurlTria(fsOrder);
2684 } break;
2685 case TYPE_TET: {
2686 basis = new HierarchicalBasisHcurlTetra(fsOrder);
2687 } break;
2688 case TYPE_PRI: {
2689 basis = new HierarchicalBasisHcurlPri(fsOrder);
2690 } break;
2691 case TYPE_LIN: {
2692 basis = new HierarchicalBasisHcurlLine(fsOrder);
2693 } break;
2694 default:
2695 Msg::Error("Unknown familyType %i for basis function type %s",
2696 familyType, fsName.c_str());
2697 return;
2698 }
2699 }
2700 else {
2701 Msg::Error("Unknown function space named '%s'", fsName.c_str());
2702 return;
2703 }
2704
2705 const std::size_t vSize = basis->getnVertexFunction();
2706 const std::size_t bSize = basis->getnBubbleFunction();
2707 const std::size_t eSize = basis->getnEdgeFunction();
2708 const std::size_t fSize =
2709 basis->getnTriFaceFunction() + basis->getnQuadFaceFunction();
2710 const std::size_t maxOrientation = basis->getNumberOfOrientations();
2711 numOrientations = maxOrientation;
2712 const std::size_t numFunctionsPerElement = vSize + bSize + eSize + fSize;
2713 const unsigned int numVertices =
2714 ElementType::getNumVertices(ElementType::getType(familyType, 1, false));
2715
2716 basisFunctions.resize(
2717 (wantedOrientations.size() == 0 ? maxOrientation :
2718 wantedOrientations.size()) *
2719 numberOfGaussPoints * numFunctionsPerElement * numComponents);
2720
2721 // Check if there is no error in wantedOrientations
2722 if(wantedOrientations.size() != 0) {
2723 if(wantedOrientations.size() > maxOrientation) {
2724 Msg::Error("Asking for more orientation that there exist");
2725 return;
2726 }
2727 for(unsigned int i = 0; i < wantedOrientations.size(); ++i) {
2728 if(wantedOrientations[i] >= static_cast<int>(maxOrientation) ||
2729 wantedOrientations[i] < 0) {
2730 Msg::Error("Orientation %i does not exist for function stace named "
2731 "'%s' on %s",
2732 wantedOrientations[i], fsName.c_str(),
2733 ElementType::nameOfParentType(familyType, true).c_str());
2734 return;
2735 }
2736 }
2737 std::vector<int> sortedWantedOrientations = wantedOrientations;
2738 std::sort(sortedWantedOrientations.begin(),
2739 sortedWantedOrientations.end());
2740 int previousInt = sortedWantedOrientations[0];
2741 for(unsigned int i = 1; i < sortedWantedOrientations.size(); ++i) {
2742 if(previousInt == sortedWantedOrientations[i]) {
2743 Msg::Error("Duplicate wanted orientation found");
2744 return;
2745 }
2746 previousInt = sortedWantedOrientations[i];
2747 }
2748 }
2749
2750 std::vector<MVertex *> vertices(numVertices);
2751 for(unsigned int i = 0; i < numVertices; ++i) {
2752 vertices[i] = new MVertex(0., 0., 0., nullptr, i + 1);
2753 }
2754 MElement *element = nullptr;
2755 switch(familyType) {
2756 case TYPE_HEX: {
2757 element = new MHexahedron(vertices);
2758 } break;
2759 case TYPE_PRI: {
2760 element = new MPrism(vertices);
2761 } break;
2762 case TYPE_TET: {
2763 element = new MTetrahedron(vertices);
2764 } break;
2765 case TYPE_QUA: {
2766 element = new MQuadrangle(vertices);
2767 } break;
2768 case TYPE_TRI: {
2769 element = new MTriangle(vertices);
2770 } break;
2771 case TYPE_LIN: {
2772 element = new MLine(vertices);
2773 } break;
2774 case TYPE_PNT: {
2775 element = new MPoint(vertices);
2776 } break;
2777 default:
2778 Msg::Error("Unknown familyType %i for basis function type %s", familyType,
2779 fsName.c_str());
2780 return;
2781 }
2782
2783 switch(numComponents) {
2784 case 1: {
2785 std::vector<std::vector<double> > vTable(
2786 numberOfGaussPoints,
2787 std::vector<double>(vSize)); // Vertex functions of one element
2788 std::vector<std::vector<double> > bTable(
2789 numberOfGaussPoints,
2790 std::vector<double>(bSize)); // bubble functions of one element
2791 std::vector<std::vector<double> > fTable(
2792 numberOfGaussPoints,
2793 std::vector<double>(fSize)); // face functions of one element
2794 std::vector<std::vector<double> > eTable(
2795 numberOfGaussPoints,
2796 std::vector<double>(eSize)); // edge functions of one element
2797
2798 for(unsigned int q = 0; q < numberOfGaussPoints; ++q) {
2799 const double u = localCoord[3 * q];
2800 const double v = localCoord[3 * q + 1];
2801 const double w = localCoord[3 * q + 2];
2802
2803 basis->generateBasis(u, v, w, vTable[q], eTable[q], fTable[q],
2804 bTable[q]);
2805 }
2806 // compute only one time the value of the edge basis functions for
2807 // each possible orientations
2808 std::vector<std::vector<double> > eTableNegativeFlag(eTable);
2809 if(eSize != 0) {
2810 for(unsigned int q = 0; q < numberOfGaussPoints; ++q) {
2811 basis->orientEdgeFunctionsForNegativeFlag(eTableNegativeFlag[q]);
2812 }
2813 }
2814
2815 // compute only one time the value of the face basis functions for
2816 // each possible orientations
2817 std::vector<std::vector<double> > quadFaceFunctionsAllOrientations(
2818 numberOfGaussPoints,
2819 std::vector<double>(basis->getnQuadFaceFunction() * 8, 0));
2820 std::vector<std::vector<double> > triFaceFunctionsAllOrientations(
2821 numberOfGaussPoints,
2822 std::vector<double>(basis->getnTriFaceFunction() * 6, 0));
2823 if(fSize != 0) {
2824 for(unsigned int q = 0; q < numberOfGaussPoints; ++q) {
2825 const double u = localCoord[3 * q];
2826 const double v = localCoord[3 * q + 1];
2827 const double w = localCoord[3 * q + 2];
2828
2829 basis->addAllOrientedFaceFunctions(
2830 u, v, w, fTable[q], quadFaceFunctionsAllOrientations[q],
2831 triFaceFunctionsAllOrientations[q]);
2832 }
2833 }
2834
2835 std::vector<std::vector<double> > eTableCopy(
2836 numberOfGaussPoints,
2837 std::vector<double>(eSize, 0)); // use eTableCopy to orient the edges
2838 std::vector<std::vector<double> > fTableCopy(
2839 numberOfGaussPoints,
2840 std::vector<double>(fSize, 0)); // use fTableCopy to orient the faces
2841
2842 unsigned int iOrientationIndex = 0;
2843 for(unsigned int iOrientation = 0; iOrientation < maxOrientation;
2844 ++iOrientation) {
2845 if(wantedOrientations.size() != 0) {
2846 auto it = std::find(wantedOrientations.begin(),
2847 wantedOrientations.end(), iOrientation);
2848 if(it != wantedOrientations.end()) {
2849 iOrientationIndex = &(*it) - &wantedOrientations[0];
2850 }
2851 else {
2852 MVertexPtrLessThan comp;
2853 std::next_permutation(vertices.begin(), vertices.end(), comp);
2854 for(unsigned int i = 0; i < numVertices; ++i) {
2855 element->setVertex(i, vertices[i]);
2856 }
2857 continue;
2858 }
2859 }
2860 else {
2861 iOrientationIndex = iOrientation;
2862 }
2863
2864 if(eSize != 0) {
2865 for(int iEdge = 0; iEdge < basis->getNumEdge(); ++iEdge) {
2866 MEdge edge = element->getEdge(iEdge);
2867 MEdge edgeSolin = element->getEdgeSolin(iEdge);
2868 const int orientationFlag =
2869 (edge.getMinVertex() != edgeSolin.getVertex(0)) ? -1 : 1;
2870 for(unsigned int q = 0; q < numberOfGaussPoints; ++q) {
2871 basis->orientEdge(orientationFlag, iEdge, eTableCopy[q],
2872 eTable[q], eTableNegativeFlag[q]);
2873 }
2874 }
2875 }
2876
2877 if(fSize != 0) {
2878 for(int iFace = 0;
2879 iFace < basis->getNumTriFace() + basis->getNumQuadFace();
2880 ++iFace) {
2881 MFace face = element->getFaceSolin(iFace);
2882 std::vector<int> faceOrientationFlag(3);
2883 face.getOrientationFlagForFace(faceOrientationFlag);
2884 for(unsigned int q = 0; q < numberOfGaussPoints; ++q) {
2885 basis->orientFace(faceOrientationFlag[0], faceOrientationFlag[1],
2886 faceOrientationFlag[2], iFace,
2887 quadFaceFunctionsAllOrientations[q],
2888 triFaceFunctionsAllOrientations[q],
2889 fTableCopy[q]);
2890 }
2891 }
2892 }
2893
2894 const std::size_t offsetOrientation =
2895 iOrientationIndex * numberOfGaussPoints * numFunctionsPerElement;
2896 for(unsigned int q = 0; q < numberOfGaussPoints; ++q) {
2897 const std::size_t offsetGP = q * numFunctionsPerElement;
2898
2899 for(unsigned int i = 0; i < vSize; ++i) {
2900 basisFunctions[offsetOrientation + offsetGP + i] = vTable[q][i];
2901 }
2902 unsigned int offset = vSize;
2903 for(unsigned int i = 0; i < eSize; ++i) {
2904 basisFunctions[offsetOrientation + offsetGP + offset + i] =
2905 eTableCopy[q][i];
2906 }
2907 offset += eSize;
2908 for(unsigned int i = 0; i < fSize; ++i) {
2909 basisFunctions[offsetOrientation + offsetGP + offset + i] =
2910 fTableCopy[q][i];
2911 }
2912 offset += fSize;
2913 for(unsigned int i = 0; i < bSize; ++i) {
2914 basisFunctions[offsetOrientation + offsetGP + offset + i] =
2915 bTable[q][i];
2916 }
2917 }
2918
2919 MVertexPtrLessThan comp;
2920 std::next_permutation(vertices.begin(), vertices.end(), comp);
2921 for(unsigned int i = 0; i < numVertices; ++i) {
2922 element->setVertex(i, vertices[i]);
2923 }
2924 }
2925 break;
2926 }
2927 case 3: {
2928 std::vector<std::vector<std::vector<double> > > vTable(
2929 numberOfGaussPoints,
2930 std::vector<std::vector<double> >(
2931 vSize,
2932 std::vector<double>(3, 0.))); // Vertex functions of one element
2933 std::vector<std::vector<std::vector<double> > > bTable(
2934 numberOfGaussPoints,
2935 std::vector<std::vector<double> >(
2936 bSize,
2937 std::vector<double>(3, 0.))); // bubble functions of one element
2938 std::vector<std::vector<std::vector<double> > > fTable(
2939 numberOfGaussPoints,
2940 std::vector<std::vector<double> >(
2941 fSize, std::vector<double>(3, 0.))); // face functions of one element
2942 std::vector<std::vector<std::vector<double> > > eTable(
2943 numberOfGaussPoints,
2944 std::vector<std::vector<double> >(
2945 eSize, std::vector<double>(3, 0.))); // edge functions of one element
2946
2947 for(unsigned int q = 0; q < numberOfGaussPoints; ++q) {
2948 const double u = localCoord[3 * q];
2949 const double v = localCoord[3 * q + 1];
2950 const double w = localCoord[3 * q + 2];
2951
2952 basis->generateBasis(u, v, w, vTable[q], eTable[q], fTable[q],
2953 bTable[q], fsName);
2954 }
2955 // compute only one time the value of the edge basis functions for
2956 // each possible orientations
2957 std::vector<std::vector<std::vector<double> > > eTableNegativeFlag(
2958 eTable);
2959 if(eSize != 0) {
2960 for(unsigned int q = 0; q < numberOfGaussPoints; ++q) {
2961 basis->orientEdgeFunctionsForNegativeFlag(eTableNegativeFlag[q]);
2962 }
2963 }
2964
2965 // compute only one time the value of the face basis functions for
2966 // each possible orientations
2967 std::vector<std::vector<std::vector<double> > >
2968 quadFaceFunctionsAllOrientations(
2969 numberOfGaussPoints,
2970 std::vector<std::vector<double> >(basis->getnQuadFaceFunction() * 8,
2971 std::vector<double>(3, 0.)));
2972 std::vector<std::vector<std::vector<double> > >
2973 triFaceFunctionsAllOrientations(
2974 numberOfGaussPoints,
2975 std::vector<std::vector<double> >(basis->getnTriFaceFunction() * 6,
2976 std::vector<double>(3, 0.)));
2977 if(fSize != 0) {
2978 for(unsigned int q = 0; q < numberOfGaussPoints; ++q) {
2979 const double u = localCoord[3 * q];
2980 const double v = localCoord[3 * q + 1];
2981 const double w = localCoord[3 * q + 2];
2982
2983 basis->addAllOrientedFaceFunctions(
2984 u, v, w, fTable[q], quadFaceFunctionsAllOrientations[q],
2985 triFaceFunctionsAllOrientations[q], fsName);
2986 }
2987 }
2988
2989 std::vector<std::vector<std::vector<double> > > eTableCopy(
2990 numberOfGaussPoints,
2991 std::vector<std::vector<double> >(
2992 eSize,
2993 std::vector<double>(3, 0.))); // use eTableCopy to orient the edges
2994 std::vector<std::vector<std::vector<double> > > fTableCopy(
2995 numberOfGaussPoints,
2996 std::vector<std::vector<double> >(
2997 fSize,
2998 std::vector<double>(3, 0.))); // use fTableCopy to orient the faces
2999
3000 unsigned int iOrientationIndex = 0;
3001 for(unsigned int iOrientation = 0; iOrientation < maxOrientation;
3002 ++iOrientation) {
3003 if(wantedOrientations.size() != 0) {
3004 auto it = std::find(wantedOrientations.begin(),
3005 wantedOrientations.end(), iOrientation);
3006 if(it != wantedOrientations.end()) {
3007 iOrientationIndex = &(*it) - &wantedOrientations[0];
3008 }
3009 else {
3010 MVertexPtrLessThan comp;
3011 std::next_permutation(vertices.begin(), vertices.end(), comp);
3012 for(unsigned int i = 0; i < numVertices; ++i) {
3013 element->setVertex(i, vertices[i]);
3014 }
3015 continue;
3016 }
3017 }
3018 else {
3019 iOrientationIndex = iOrientation;
3020 }
3021
3022 if(eSize != 0) {
3023 for(int iEdge = 0; iEdge < basis->getNumEdge(); ++iEdge) {
3024 MEdge edge = element->getEdge(iEdge);
3025 MEdge edgeSolin = element->getEdgeSolin(iEdge);
3026 const int orientationFlag =
3027 (edge.getMinVertex() != edgeSolin.getVertex(0) ? -1 : 1);
3028 for(unsigned int q = 0; q < numberOfGaussPoints; ++q) {
3029 basis->orientEdge(orientationFlag, iEdge, eTableCopy[q],
3030 eTable[q], eTableNegativeFlag[q]);
3031 }
3032 }
3033 }
3034
3035 if(fSize != 0) {
3036 for(int iFace = 0;
3037 iFace < basis->getNumTriFace() + basis->getNumQuadFace();
3038 ++iFace) {
3039 MFace face = element->getFaceSolin(iFace);
3040 std::vector<int> faceOrientationFlag(3);
3041 face.getOrientationFlagForFace(faceOrientationFlag);
3042 for(unsigned int q = 0; q < numberOfGaussPoints; ++q) {
3043 basis->orientFace(faceOrientationFlag[0], faceOrientationFlag[1],
3044 faceOrientationFlag[2], iFace,
3045 quadFaceFunctionsAllOrientations[q],
3046 triFaceFunctionsAllOrientations[q],
3047 fTableCopy[q]);
3048 }
3049 }
3050 }
3051
3052 const std::size_t offsetOrientation =
3053 iOrientationIndex * numberOfGaussPoints * numFunctionsPerElement * 3;
3054 for(unsigned int q = 0; q < numberOfGaussPoints; ++q) {
3055 const std::size_t offsetGP = q * numFunctionsPerElement * 3;
3056
3057 for(unsigned int i = 0; i < vSize; ++i) {
3058 basisFunctions[offsetOrientation + offsetGP + 3 * i] =
3059 vTable[q][i][0];
3060 basisFunctions[offsetOrientation + offsetGP + 3 * i + 1] =
3061 vTable[q][i][1];
3062 basisFunctions[offsetOrientation + offsetGP + 3 * i + 2] =
3063 vTable[q][i][2];
3064 }
3065 unsigned int offset = 3 * vSize;
3066 for(unsigned int i = 0; i < eSize; ++i) {
3067 basisFunctions[offsetOrientation + offsetGP + offset + 3 * i] =
3068 eTableCopy[q][i][0];
3069 basisFunctions[offsetOrientation + offsetGP + offset + 3 * i + 1] =
3070 eTableCopy[q][i][1];
3071 basisFunctions[offsetOrientation + offsetGP + offset + 3 * i + 2] =
3072 eTableCopy[q][i][2];
3073 }
3074 offset += 3 * eSize;
3075 for(unsigned int i = 0; i < fSize; ++i) {
3076 basisFunctions[offsetOrientation + offsetGP + offset + 3 * i] =
3077 fTableCopy[q][i][0];
3078 basisFunctions[offsetOrientation + offsetGP + offset + 3 * i + 1] =
3079 fTableCopy[q][i][1];
3080 basisFunctions[offsetOrientation + offsetGP + offset + 3 * i + 2] =
3081 fTableCopy[q][i][2];
3082 }
3083 offset += 3 * fSize;
3084 for(unsigned int i = 0; i < bSize; ++i) {
3085 basisFunctions[offsetOrientation + offsetGP + offset + 3 * i] =
3086 bTable[q][i][0];
3087 basisFunctions[offsetOrientation + offsetGP + offset + 3 * i + 1] =
3088 bTable[q][i][1];
3089 basisFunctions[offsetOrientation + offsetGP + offset + 3 * i + 2] =
3090 bTable[q][i][2];
3091 }
3092 }
3093
3094 MVertexPtrLessThan comp;
3095 std::next_permutation(vertices.begin(), vertices.end(), comp);
3096 for(unsigned int i = 0; i < numVertices; ++i) {
3097 element->setVertex(i, vertices[i]);
3098 }
3099 }
3100 break;
3101 }
3102 }
3103
3104 for(unsigned int i = 0; i < numVertices; ++i) { delete vertices[i]; }
3105 delete element;
3106 delete basis;
3107 }
3108
3109 return;
3110 }
3111
getBasisFunctionsOrientation(const int elementType,const std::string & functionSpaceType,std::vector<int> & basisFunctionsOrientation,const int tag,const std::size_t task,const std::size_t numTasks)3112 GMSH_API void gmsh::model::mesh::getBasisFunctionsOrientation(
3113 const int elementType, const std::string &functionSpaceType,
3114 std::vector<int> &basisFunctionsOrientation, const int tag,
3115 const std::size_t task, const std::size_t numTasks)
3116 {
3117 if(!_checkInit()) return;
3118
3119 if(!basisFunctionsOrientation.size()) {
3120 if(numTasks > 1) {
3121 Msg::Warning(
3122 "basisFunctionsOrientation should be preallocated if numTasks > 1");
3123 }
3124 preallocateBasisFunctionsOrientation(
3125 elementType, basisFunctionsOrientation, tag);
3126 }
3127
3128 const int familyType = ElementType::getParentType(elementType);
3129
3130 int basisOrder = 0;
3131 std::string fsName = "";
3132 int numComponents = 0;
3133 if(!_getFunctionSpaceInfo(functionSpaceType, fsName, basisOrder,
3134 numComponents)) {
3135 Msg::Error("Unknown function space type '%s'", functionSpaceType.c_str());
3136 return;
3137 }
3138
3139 const int dim = ElementType::getDimension(elementType);
3140 std::map<int, std::vector<GEntity *> > typeEnt;
3141 _getEntitiesForElementTypes(dim, tag, typeEnt);
3142 const std::vector<GEntity *> &entities(typeEnt[elementType]);
3143
3144 std::size_t numElements = 0;
3145 for(std::size_t i = 0; i < entities.size(); i++) {
3146 const GEntity *ge = entities[i];
3147 numElements += ge->getNumMeshElementsByType(familyType);
3148 }
3149
3150 if(numElements != basisFunctionsOrientation.size()) {
3151 Msg::Error("Wrong size of 'basisFunctionsOrientation' vector (%i != %i)",
3152 numElements, basisFunctionsOrientation.size());
3153 return;
3154 }
3155
3156 if(fsName == "Lagrange" || fsName == "GradLagrange") { // Lagrange type
3157 const std::size_t begin = task * numElements / numTasks;
3158 const std::size_t end = (task + 1) * numElements / numTasks;
3159 for(std::size_t iElement = begin; iElement < end; ++iElement) {
3160 basisFunctionsOrientation[iElement] = 0;
3161 }
3162 }
3163 else { // Hierarchical type
3164 const unsigned int numVertices =
3165 ElementType::getNumVertices(ElementType::getType(familyType, 1, false));
3166 std::vector<MVertex *> vertices(numVertices);
3167 std::vector<unsigned int> verticesOrder(numVertices);
3168 const std::size_t factorial[8] = {1, 1, 2, 6, 24, 120, 720, 5040};
3169
3170 std::size_t entityOffset = 0;
3171
3172 for(std::size_t iEntity = 0; iEntity < entities.size(); ++iEntity) {
3173 const GEntity *ge = entities[iEntity];
3174 std::size_t localNumElements = ge->getNumMeshElementsByType(familyType);
3175
3176 const std::size_t begin = task * localNumElements / numTasks;
3177 const std::size_t end = (task + 1) * localNumElements / numTasks;
3178
3179 for(std::size_t iElement = begin; iElement < end; ++iElement) {
3180 MElement *e = ge->getMeshElementByType(familyType, iElement);
3181 for(std::size_t i = 0; i < numVertices; ++i) {
3182 vertices[i] = e->getVertex(i);
3183 }
3184
3185 for(std::size_t i = 0; i < numVertices; ++i) {
3186 std::size_t max = 0;
3187 std::size_t maxPos = 0;
3188 for(std::size_t j = 0; j < numVertices; ++j) {
3189 if(vertices[j] != nullptr) {
3190 if(max < vertices[j]->getNum()) {
3191 max = vertices[j]->getNum();
3192 maxPos = j;
3193 }
3194 }
3195 }
3196 vertices[maxPos] = nullptr;
3197 verticesOrder[maxPos] = numVertices - i - 1;
3198 }
3199
3200 std::size_t elementOrientation = 0;
3201 for(std::size_t i = 0; i < numVertices; ++i) {
3202 elementOrientation +=
3203 verticesOrder[i] * factorial[numVertices - i - 1];
3204 for(std::size_t j = i + 1; j < numVertices; ++j) {
3205 if(verticesOrder[j] > verticesOrder[i]) --verticesOrder[j];
3206 }
3207 }
3208
3209 basisFunctionsOrientation[entityOffset + iElement] =
3210 (int)elementOrientation;
3211 }
3212
3213 entityOffset += localNumElements;
3214 }
3215 }
3216
3217 return;
3218 }
3219
getBasisFunctionsOrientationForElement(const std::size_t elementTag,const std::string & functionSpaceType,int & basisFunctionsOrientation)3220 GMSH_API void gmsh::model::mesh::getBasisFunctionsOrientationForElement(
3221 const std::size_t elementTag, const std::string &functionSpaceType,
3222 int &basisFunctionsOrientation)
3223 {
3224 if(!_checkInit()) return;
3225
3226 MElement *e = GModel::current()->getMeshElementByTag(elementTag);
3227 int elementType = e->getTypeForMSH();
3228 int familyType = ElementType::getParentType(elementType);
3229
3230 int basisOrder = 0;
3231 std::string fsName = "";
3232 int numComponents = 0;
3233 if(!_getFunctionSpaceInfo(functionSpaceType, fsName, basisOrder,
3234 numComponents)) {
3235 Msg::Error("Unknown function space type '%s'", functionSpaceType.c_str());
3236 return;
3237 }
3238
3239 if(fsName == "Lagrange" || fsName == "GradLagrange") { // Lagrange type
3240 basisFunctionsOrientation = 0;
3241 }
3242 else { // Hierarchical type
3243 const unsigned int numVertices =
3244 ElementType::getNumVertices(ElementType::getType(familyType, 1, false));
3245 std::vector<MVertex *> vertices(numVertices);
3246 std::vector<unsigned int> verticesOrder(numVertices);
3247 const std::size_t factorial[8] = {1, 1, 2, 6, 24, 120, 720, 5040};
3248
3249 for(std::size_t i = 0; i < numVertices; ++i) {
3250 vertices[i] = e->getVertex(i);
3251 }
3252
3253 for(std::size_t i = 0; i < numVertices; ++i) {
3254 std::size_t max = 0;
3255 std::size_t maxPos = 0;
3256 for(std::size_t j = 0; j < numVertices; ++j) {
3257 if(vertices[j] != nullptr) {
3258 if(max < vertices[j]->getNum()) {
3259 max = vertices[j]->getNum();
3260 maxPos = j;
3261 }
3262 }
3263 }
3264 vertices[maxPos] = nullptr;
3265 verticesOrder[maxPos] = numVertices - i - 1;
3266 }
3267
3268 basisFunctionsOrientation = 0;
3269 for(std::size_t i = 0; i < numVertices; ++i) {
3270 basisFunctionsOrientation +=
3271 verticesOrder[i] * factorial[numVertices - i - 1];
3272 for(std::size_t j = i + 1; j < numVertices; ++j) {
3273 if(verticesOrder[j] > verticesOrder[i]) --verticesOrder[j];
3274 }
3275 }
3276 }
3277
3278 return;
3279 }
3280
3281 GMSH_API int
getNumberOfOrientations(const int elementType,const std::string & functionSpaceType)3282 gmsh::model::mesh::getNumberOfOrientations(const int elementType,
3283 const std::string &functionSpaceType)
3284 {
3285 if(!_checkInit()) return -1;
3286
3287 int basisOrder = 0;
3288 std::string fsName = "";
3289 int numComponents = 0;
3290 if(!_getFunctionSpaceInfo(functionSpaceType, fsName, basisOrder,
3291 numComponents)) {
3292 Msg::Error("Unknown function space type '%s'", functionSpaceType.c_str());
3293 return 0;
3294 }
3295
3296 if(fsName == "Lagrange" || fsName == "GradLagrange") { // Lagrange type
3297 return 1;
3298 }
3299 else { // Hierarchical type
3300 const int familyType = ElementType::getParentType(elementType);
3301 const unsigned int numVertices =
3302 ElementType::getNumVertices(ElementType::getType(familyType, 1, false));
3303 const std::size_t factorial[8] = {1, 1, 2, 6, 24, 120, 720, 5040};
3304 return factorial[numVertices];
3305 }
3306
3307 return 0;
3308 }
3309
3310 GMSH_API void
preallocateBasisFunctionsOrientation(const int elementType,std::vector<int> & basisFunctionsOrientation,const int tag)3311 gmsh::model::mesh::preallocateBasisFunctionsOrientation(
3312 const int elementType, std::vector<int> &basisFunctionsOrientation,
3313 const int tag)
3314 {
3315 if(!_checkInit()) return;
3316
3317 const int dim = ElementType::getDimension(elementType);
3318 std::map<int, std::vector<GEntity *> > typeEnt;
3319 _getEntitiesForElementTypes(dim, tag, typeEnt);
3320 const std::vector<GEntity *> &entities(typeEnt[elementType]);
3321
3322 const int familyType = ElementType::getParentType(elementType);
3323
3324 std::size_t numElements = 0;
3325 for(std::size_t i = 0; i < entities.size(); i++) {
3326 const GEntity *ge = entities[i];
3327 numElements += ge->getNumMeshElementsByType(familyType);
3328 }
3329 if(!numElements) return;
3330 basisFunctionsOrientation.resize(numElements);
3331 }
3332
3333 GMSH_API void
getEdges(const std::vector<std::size_t> & nodeTags,std::vector<std::size_t> & edgeTags,std::vector<int> & edgeOrientations)3334 gmsh::model::mesh::getEdges(const std::vector<std::size_t> &nodeTags,
3335 std::vector<std::size_t> &edgeTags,
3336 std::vector<int> &edgeOrientations)
3337 {
3338 edgeTags.clear();
3339 edgeOrientations.clear();
3340 std::size_t numEdges = nodeTags.size() / 2;
3341 if(!numEdges) return;
3342 edgeTags.resize(numEdges);
3343 edgeOrientations.resize(numEdges);
3344 for(std::size_t i = 0; i < numEdges; i++) {
3345 std::size_t n0 = nodeTags[2 * i];
3346 std::size_t n1 = nodeTags[2 * i + 1];
3347 MVertex *v0 = GModel::current()->getMeshVertexByTag(n0);
3348 MVertex *v1 = GModel::current()->getMeshVertexByTag(n1);
3349 if(v0 && v1) {
3350 MEdge edge;
3351 edgeTags[i] = GModel::current()->getMEdge(v0, v1, edge);
3352 if(edge.getMinVertex() == v0 && edge.getMaxVertex() == v1)
3353 edgeOrientations[i] = 1;
3354 else if(edge.getMaxVertex() == v0 && edge.getMinVertex() == v1)
3355 edgeOrientations[i] = -1;
3356 else
3357 edgeOrientations[i] = 0;
3358 }
3359 else {
3360 Msg::Error("Unknown mesh node %d or %d", n0, n1);
3361 }
3362 }
3363 }
3364
getFaces(const int faceType,const std::vector<std::size_t> & nodeTags,std::vector<std::size_t> & faceTags,std::vector<int> & orientations)3365 GMSH_API void gmsh::model::mesh::getFaces(
3366 const int faceType, const std::vector<std::size_t> &nodeTags,
3367 std::vector<std::size_t> &faceTags, std::vector<int> &orientations)
3368 {
3369 faceTags.clear();
3370 orientations.clear();
3371 if(faceType != 3 && faceType != 4) {
3372 Msg::Error("Unknown face type (should be 3 or 4)");
3373 return;
3374 }
3375 std::size_t numFaces = nodeTags.size() / faceType;
3376 if(!numFaces) return;
3377 faceTags.resize(numFaces);
3378 orientations.resize(numFaces, 0); // TODO
3379 for(std::size_t i = 0; i < numFaces; i++) {
3380 std::size_t n0 = nodeTags[faceType * i];
3381 std::size_t n1 = nodeTags[faceType * i + 1];
3382 std::size_t n2 = nodeTags[faceType * i + 2];
3383 std::size_t n3 = (faceType == 4) ? nodeTags[faceType * i + 3] : 0;
3384 MVertex *v0 = GModel::current()->getMeshVertexByTag(n0);
3385 MVertex *v1 = GModel::current()->getMeshVertexByTag(n1);
3386 MVertex *v2 = GModel::current()->getMeshVertexByTag(n2);
3387 MVertex *v3 =
3388 (faceType == 4) ? GModel::current()->getMeshVertexByTag(n3) : nullptr;
3389 if(v0 && v1 && v2) {
3390 MFace face;
3391 faceTags[i] = GModel::current()->getMFace(v0, v1, v2, v3, face);
3392 }
3393 else {
3394 Msg::Error("Unknown mesh node %d, %d or %d", n0, n1, n2);
3395 }
3396 }
3397 }
3398
createEdges(const vectorpair & dimTags)3399 GMSH_API void gmsh::model::mesh::createEdges(const vectorpair &dimTags)
3400 {
3401 if(!_checkInit()) return;
3402 std::vector<GEntity *> entities;
3403 _getEntities(dimTags, entities);
3404 for(std::size_t i = 0; i < entities.size(); i++) {
3405 GEntity *ge = entities[i];
3406 for(std::size_t j = 0; j < ge->getNumMeshElements(); j++) {
3407 MElement *e = ge->getMeshElement(j);
3408 for(int k = 0; k < e->getNumEdges(); k++) {
3409 MEdge edge = e->getEdge(k);
3410 GModel::current()->addMEdge(edge);
3411 }
3412 }
3413 }
3414 }
3415
createFaces(const vectorpair & dimTags)3416 GMSH_API void gmsh::model::mesh::createFaces(const vectorpair &dimTags)
3417 {
3418 if(!_checkInit()) return;
3419 std::vector<GEntity *> entities;
3420 _getEntities(dimTags, entities);
3421 for(std::size_t i = 0; i < entities.size(); i++) {
3422 GEntity *ge = entities[i];
3423 for(std::size_t j = 0; j < ge->getNumMeshElements(); j++) {
3424 MElement *e = ge->getMeshElement(j);
3425 for(int k = 0; k < e->getNumFaces(); k++) {
3426 MFace face = e->getFace(k);
3427 GModel::current()->addMFace(face);
3428 }
3429 }
3430 }
3431 }
3432
getAllEdges(std::vector<std::size_t> & edgeTags,std::vector<std::size_t> & edgeNodes)3433 GMSH_API void gmsh::model::mesh::getAllEdges(std::vector<std::size_t> &edgeTags,
3434 std::vector<std::size_t> &edgeNodes)
3435 {
3436 if(!_checkInit()) return;
3437 edgeTags.clear();
3438 edgeNodes.clear();
3439 GModel *m = GModel::current();
3440 for(auto it = m->firstMEdge(); it != m->lastMEdge(); ++it) {
3441 edgeTags.push_back(it->second);
3442 edgeNodes.push_back(it->first.getVertex(0)->getNum());
3443 edgeNodes.push_back(it->first.getVertex(1)->getNum());
3444 }
3445 }
3446
getAllFaces(const int faceType,std::vector<std::size_t> & faceTags,std::vector<std::size_t> & faceNodes)3447 GMSH_API void gmsh::model::mesh::getAllFaces(const int faceType,
3448 std::vector<std::size_t> &faceTags,
3449 std::vector<std::size_t> &faceNodes)
3450 {
3451 if(!_checkInit()) return;
3452 if(faceType != 3 && faceType != 4) {
3453 Msg::Error("Unknown face type (should be 3 or 4)");
3454 return;
3455 }
3456 faceTags.clear();
3457 faceNodes.clear();
3458 GModel *m = GModel::current();
3459 for(auto it = m->firstMFace(); it != m->lastMFace(); ++it) {
3460 if(faceType == (int)it->first.getNumVertices()) {
3461 faceTags.push_back(it->second);
3462 for(int j = 0; j < faceType; j++)
3463 faceNodes.push_back(it->first.getVertex(j)->getNum());
3464 }
3465 }
3466 }
3467
addEdges(const std::vector<std::size_t> & edgeTags,const std::vector<std::size_t> & edgeNodes)3468 GMSH_API void gmsh::model::mesh::addEdges(const std::vector<std::size_t> &edgeTags,
3469 const std::vector<std::size_t> &edgeNodes)
3470 {
3471 if(!_checkInit()) return;
3472 if(edgeTags.size() * 2 != edgeNodes.size()) {
3473 Msg::Error("Wrong number of edge nodes");
3474 return;
3475 }
3476 GModel *m = GModel::current();
3477 for(std::size_t i = 0; i < edgeTags.size(); i++) {
3478 MVertex *v[2];
3479 for(int j = 0; j < 2; j++) {
3480 v[j] = m->getMeshVertexByTag(edgeNodes[2 * i + j]);
3481 if(!v[j]) {
3482 Msg::Error("Unknown mesh node %lu", edgeNodes[2 * i + j]);
3483 return;
3484 }
3485 }
3486 MEdge e(v[0], v[1]);
3487 m->addMEdge(e, edgeTags[i]);
3488 }
3489 }
3490
addFaces(const int faceType,const std::vector<std::size_t> & faceTags,const std::vector<std::size_t> & faceNodes)3491 GMSH_API void gmsh::model::mesh::addFaces(const int faceType,
3492 const std::vector<std::size_t> &faceTags,
3493 const std::vector<std::size_t> &faceNodes)
3494 {
3495 if(!_checkInit()) return;
3496 if(faceType != 3 && faceType != 4) {
3497 Msg::Error("Unknown face type (should be 3 or 4)");
3498 return;
3499 }
3500 if(faceTags.size() * faceType != faceNodes.size()) {
3501 Msg::Error("Wrong number of face nodes");
3502 return;
3503 }
3504 GModel *m = GModel::current();
3505 for(std::size_t i = 0; i < faceTags.size(); i++) {
3506 MVertex *v[4] = {nullptr, nullptr, nullptr, nullptr};
3507 for(int j = 0; j < faceType; j++) {
3508 v[j] = m->getMeshVertexByTag(faceNodes[faceType * i + j]);
3509 if(!v[j]) {
3510 Msg::Error("Unknown mesh node %lu", faceNodes[faceType * i + j]);
3511 return;
3512 }
3513 }
3514 MFace f(v[0], v[1], v[2], v[3]);
3515 m->addMFace(f, faceTags[i]);
3516 }
3517 }
3518
getKeys(const int elementType,const std::string & functionSpaceType,std::vector<int> & typeKeys,std::vector<std::size_t> & entityKeys,std::vector<double> & coord,const int tag,const bool returnCoord)3519 GMSH_API void gmsh::model::mesh::getKeys(
3520 const int elementType, const std::string &functionSpaceType,
3521 std::vector<int> &typeKeys, std::vector<std::size_t> &entityKeys,
3522 std::vector<double> &coord, const int tag, const bool returnCoord)
3523 {
3524 if(!_checkInit()) return;
3525 coord.clear();
3526 typeKeys.clear();
3527 entityKeys.clear();
3528 int order = 0;
3529 int numComponents = 0;
3530 std::string fsName = "";
3531 if(!_getFunctionSpaceInfo(functionSpaceType, fsName, order, numComponents)) {
3532 Msg::Error("Unknown function space type '%s'", functionSpaceType.c_str());
3533 return;
3534 }
3535 int dim = ElementType::getDimension(elementType);
3536 std::map<int, std::vector<GEntity *> > typeEnt;
3537 _getEntitiesForElementTypes(dim, tag, typeEnt);
3538 const std::vector<GEntity *> &entities(typeEnt[elementType]);
3539 int familyType = ElementType::getParentType(elementType);
3540
3541 HierarchicalBasis *basis(nullptr);
3542 if(fsName == "H1Legendre" || fsName == "GradH1Legendre") {
3543 switch(familyType) {
3544 case TYPE_HEX: {
3545 basis = new HierarchicalBasisH1Brick(order);
3546 } break;
3547 case TYPE_PRI: {
3548 basis = new HierarchicalBasisH1Pri(order);
3549 } break;
3550 case TYPE_TET: {
3551 basis = new HierarchicalBasisH1Tetra(order);
3552 } break;
3553 case TYPE_QUA: {
3554 basis = new HierarchicalBasisH1Quad(order);
3555 } break;
3556 case TYPE_TRI: {
3557 basis = new HierarchicalBasisH1Tria(order);
3558 } break;
3559 case TYPE_LIN: {
3560 basis = new HierarchicalBasisH1Line(order);
3561 } break;
3562 case TYPE_PNT: {
3563 basis = new HierarchicalBasisH1Point();
3564 } break;
3565 default:
3566 Msg::Error("Unknown familyType %i for basis function type %s", familyType,
3567 fsName.c_str());
3568 return;
3569 }
3570 }
3571 else if(fsName == "HcurlLegendre" || fsName == "CurlHcurlLegendre") {
3572 switch(familyType) {
3573 case TYPE_QUA: {
3574 basis = new HierarchicalBasisHcurlQuad(order);
3575 } break;
3576 case TYPE_HEX: {
3577 basis = new HierarchicalBasisHcurlBrick(order);
3578 } break;
3579 case TYPE_TRI: {
3580 basis = new HierarchicalBasisHcurlTria(order);
3581 } break;
3582 case TYPE_TET: {
3583 basis = new HierarchicalBasisHcurlTetra(order);
3584 } break;
3585 case TYPE_PRI: {
3586 basis = new HierarchicalBasisHcurlPri(order);
3587 } break;
3588 case TYPE_LIN: {
3589 basis = new HierarchicalBasisHcurlLine(order);
3590 } break;
3591 default:
3592 Msg::Error("Unknown familyType %i for basis function type %s", familyType,
3593 fsName.c_str());
3594 return;
3595 }
3596 }
3597 else if(fsName == "IsoParametric" || fsName == "Lagrange" ||
3598 fsName == "GradIsoParametric" || fsName == "GradLagrange") {
3599 const nodalBasis *nodalB(nullptr);
3600 if(order == -1) { // isoparametric
3601 nodalB = BasisFactory::getNodalBasis(elementType);
3602 }
3603 else {
3604 int familyType = ElementType::getParentType(elementType);
3605 int newType = ElementType::getType(familyType, order, false);
3606 nodalB = BasisFactory::getNodalBasis(newType);
3607 }
3608
3609 for(std::size_t i = 0; i < entities.size(); ++i) {
3610 GEntity *ge = entities[i];
3611 std::size_t numElementsInEntitie =
3612 ge->getNumMeshElementsByType(familyType);
3613 if(returnCoord) {
3614 coord.reserve(coord.size() + numElementsInEntitie *
3615 nodalB->getNumShapeFunctions() * 3);
3616 }
3617 typeKeys.reserve(typeKeys.size() +
3618 numElementsInEntitie * nodalB->getNumShapeFunctions());
3619 entityKeys.reserve(entityKeys.size() +
3620 numElementsInEntitie * nodalB->getNumShapeFunctions());
3621
3622 for(std::size_t j = 0; j < numElementsInEntitie; ++j) {
3623 MElement *e = ge->getMeshElementByType(familyType, j);
3624 for(size_t k = 0; k < e->getNumVertices(); ++k) {
3625 typeKeys.push_back(0);
3626 entityKeys.push_back(e->getVertex(k)->getNum());
3627 if(returnCoord) {
3628 coord.push_back(e->getVertex(k)->x());
3629 coord.push_back(e->getVertex(k)->y());
3630 coord.push_back(e->getVertex(k)->z());
3631 }
3632 }
3633 }
3634 }
3635 return;
3636 }
3637 else {
3638 Msg::Error("Unknown function space named '%s'", fsName.c_str());
3639 return;
3640 }
3641
3642 int vSize = basis->getnVertexFunction();
3643 int bSize = basis->getnBubbleFunction();
3644 int eSize = basis->getnEdgeFunction();
3645 int quadFSize = basis->getnQuadFaceFunction();
3646 int triFSize = basis->getnTriFaceFunction();
3647 int fSize = quadFSize + triFSize;
3648 int numDofsPerElement = vSize + bSize + eSize + fSize;
3649 int numberQuadFaces = basis->getNumQuadFace();
3650 int numberTriFaces = basis->getNumTriFace();
3651 int numTriFaceFunction = 0;
3652 if(basis->getNumTriFace() != 0) {
3653 numTriFaceFunction =
3654 triFSize /
3655 basis->getNumTriFace(); // number of Tri face functions for one face
3656 }
3657 int numQuadFaceFunction = 0;
3658 if(basis->getNumQuadFace() != 0) {
3659 numQuadFaceFunction =
3660 quadFSize /
3661 basis->getNumQuadFace(); // number of Tri face functions for one face
3662 }
3663 int numEdgeFunction = 0;
3664 if(basis->getNumEdge() != 0) {
3665 numEdgeFunction =
3666 eSize / basis->getNumEdge(); // number of edge functions for one edge
3667 }
3668 int const1 = numEdgeFunction + 1;
3669 int const2 = const1 + numQuadFaceFunction;
3670 int const3 = const1 + numTriFaceFunction;
3671 int const4 = bSize + std::max(const3, const2);
3672 delete basis;
3673
3674 for(std::size_t i = 0; i < entities.size(); i++) {
3675 GEntity *ge = entities[i];
3676 std::size_t numElementsInEntitie = ge->getNumMeshElementsByType(familyType);
3677 if(returnCoord) {
3678 coord.reserve(coord.size() +
3679 numElementsInEntitie * numDofsPerElement * 3);
3680 }
3681 typeKeys.reserve(typeKeys.size() +
3682 numElementsInEntitie * numDofsPerElement);
3683 entityKeys.reserve(entityKeys.size() +
3684 numElementsInEntitie * numDofsPerElement);
3685
3686 for(std::size_t j = 0; j < numElementsInEntitie; j++) {
3687 MElement *e = ge->getMeshElementByType(familyType, j);
3688 // vertices
3689 for(int k = 0; k < vSize; k++) {
3690 typeKeys.push_back(0);
3691 entityKeys.push_back(e->getVertex(k)->getNum());
3692 if(returnCoord) {
3693 coord.push_back(e->getVertex(k)->x());
3694 coord.push_back(e->getVertex(k)->y());
3695 coord.push_back(e->getVertex(k)->z());
3696 }
3697 }
3698 // edges
3699 if(eSize > 0) {
3700 for(int jj = 0; jj < e->getNumEdges(); jj++) {
3701 MEdge edge = e->getEdge(jj);
3702 double coordEdge[3];
3703 if(returnCoord) {
3704 MVertex *v1 = edge.getVertex(0);
3705 MVertex *v2 = edge.getVertex(1);
3706
3707 coordEdge[0] = 0.5 * (v1->x() + v2->x());
3708 coordEdge[1] = 0.5 * (v1->y() + v2->y());
3709 coordEdge[2] = 0.5 * (v1->z() + v2->z());
3710 }
3711 std::size_t edgeGlobalIndice = GModel::current()->addMEdge(edge);
3712 for(int k = 1; k < const1; k++) {
3713 typeKeys.push_back(k);
3714 entityKeys.push_back(edgeGlobalIndice);
3715 if(returnCoord) {
3716 coord.push_back(coordEdge[0]);
3717 coord.push_back(coordEdge[1]);
3718 coord.push_back(coordEdge[2]);
3719 }
3720 }
3721 }
3722 }
3723 // faces
3724 if(fSize > 0) {
3725 for(int jj = 0; jj < numberQuadFaces + numberTriFaces; jj++) {
3726 // Number the faces
3727 MFace face = e->getFaceSolin(jj);
3728 double coordFace[3] = {0., 0., 0.};
3729 if(returnCoord) {
3730 for(std::size_t indexV = 0; indexV < face.getNumVertices();
3731 ++indexV) {
3732 coordFace[0] += face.getVertex(indexV)->x();
3733 coordFace[1] += face.getVertex(indexV)->y();
3734 coordFace[2] += face.getVertex(indexV)->z();
3735 }
3736 coordFace[0] /= face.getNumVertices();
3737 coordFace[1] /= face.getNumVertices();
3738 coordFace[2] /= face.getNumVertices();
3739 }
3740 std::size_t faceGlobalIndice = GModel::current()->addMFace(face);
3741 int it2 = const2;
3742 if(jj >= numberQuadFaces) { it2 = const3; }
3743 for(int k = const1; k < it2; k++) {
3744 typeKeys.push_back(k);
3745 entityKeys.push_back(faceGlobalIndice);
3746 if(returnCoord) {
3747 coord.push_back(coordFace[0]);
3748 coord.push_back(coordFace[1]);
3749 coord.push_back(coordFace[2]);
3750 }
3751 }
3752 }
3753 }
3754 // volumes
3755 if(bSize > 0) {
3756 double bubbleCenterCoord[3] = {0., 0., 0.};
3757 if(returnCoord) {
3758 for(unsigned int indexV = 0; indexV < e->getNumVertices(); ++indexV) {
3759 bubbleCenterCoord[0] += e->getVertex(indexV)->x();
3760 bubbleCenterCoord[1] += e->getVertex(indexV)->y();
3761 bubbleCenterCoord[2] += e->getVertex(indexV)->z();
3762 }
3763 bubbleCenterCoord[0] /= e->getNumVertices();
3764 bubbleCenterCoord[1] /= e->getNumVertices();
3765 bubbleCenterCoord[2] /= e->getNumVertices();
3766 }
3767 for(int k = std::max(const3, const2); k < const4; k++) {
3768 typeKeys.push_back(k);
3769 entityKeys.push_back(e->getNum());
3770 if(returnCoord) {
3771 coord.push_back(bubbleCenterCoord[0]);
3772 coord.push_back(bubbleCenterCoord[1]);
3773 coord.push_back(bubbleCenterCoord[2]);
3774 }
3775 }
3776 }
3777 }
3778 }
3779 }
3780
getKeysForElement(const std::size_t elementTag,const std::string & functionSpaceType,std::vector<int> & typeKeys,std::vector<std::size_t> & entityKeys,std::vector<double> & coord,const bool returnCoord)3781 GMSH_API void gmsh::model::mesh::getKeysForElement(
3782 const std::size_t elementTag, const std::string &functionSpaceType,
3783 std::vector<int> &typeKeys, std::vector<std::size_t> &entityKeys,
3784 std::vector<double> &coord, const bool returnCoord)
3785 {
3786 if(!_checkInit()) return;
3787 coord.clear();
3788 typeKeys.clear();
3789 entityKeys.clear();
3790 int order = 0;
3791 int numComponents = 0;
3792 std::string fsName = "";
3793 if(!_getFunctionSpaceInfo(functionSpaceType, fsName, order, numComponents)) {
3794 Msg::Error("Unknown function space type '%s'", functionSpaceType.c_str());
3795 return;
3796 }
3797 MElement *e = GModel::current()->getMeshElementByTag(elementTag);
3798 int elementType = e->getTypeForMSH();
3799 int familyType = ElementType::getParentType(elementType);
3800
3801 HierarchicalBasis *basis(nullptr);
3802 if(fsName == "H1Legendre" || fsName == "GradH1Legendre") {
3803 switch(familyType) {
3804 case TYPE_HEX: {
3805 basis = new HierarchicalBasisH1Brick(order);
3806 } break;
3807 case TYPE_PRI: {
3808 basis = new HierarchicalBasisH1Pri(order);
3809 } break;
3810 case TYPE_TET: {
3811 basis = new HierarchicalBasisH1Tetra(order);
3812 } break;
3813 case TYPE_QUA: {
3814 basis = new HierarchicalBasisH1Quad(order);
3815 } break;
3816 case TYPE_TRI: {
3817 basis = new HierarchicalBasisH1Tria(order);
3818 } break;
3819 case TYPE_LIN: {
3820 basis = new HierarchicalBasisH1Line(order);
3821 } break;
3822 case TYPE_PNT: {
3823 basis = new HierarchicalBasisH1Point();
3824 } break;
3825 default:
3826 Msg::Error("Unknown familyType %i for basis function type %s", familyType,
3827 fsName.c_str());
3828 return;
3829 }
3830 }
3831 else if(fsName == "HcurlLegendre" || fsName == "CurlHcurlLegendre") {
3832 switch(familyType) {
3833 case TYPE_QUA: {
3834 basis = new HierarchicalBasisHcurlQuad(order);
3835 } break;
3836 case TYPE_HEX: {
3837 basis = new HierarchicalBasisHcurlBrick(order);
3838 } break;
3839 case TYPE_TRI: {
3840 basis = new HierarchicalBasisHcurlTria(order);
3841 } break;
3842 case TYPE_TET: {
3843 basis = new HierarchicalBasisHcurlTetra(order);
3844 } break;
3845 case TYPE_PRI: {
3846 basis = new HierarchicalBasisHcurlPri(order);
3847 } break;
3848 case TYPE_LIN: {
3849 basis = new HierarchicalBasisHcurlLine(order);
3850 } break;
3851 default:
3852 Msg::Error("Unknown familyType %i for basis function type %s", familyType,
3853 fsName.c_str());
3854 return;
3855 }
3856 }
3857 else if(fsName == "IsoParametric" || fsName == "Lagrange" ||
3858 fsName == "GradIsoParametric" || fsName == "GradLagrange") {
3859 typeKeys.reserve(e->getNumVertices());
3860 entityKeys.reserve(e->getNumVertices());
3861 if(returnCoord) { coord.reserve(3 * e->getNumVertices()); }
3862 for(size_t k = 0; k < e->getNumVertices(); ++k) {
3863 typeKeys.push_back(0);
3864 entityKeys.push_back(e->getVertex(k)->getNum());
3865 if(returnCoord) {
3866 coord.push_back(e->getVertex(k)->x());
3867 coord.push_back(e->getVertex(k)->y());
3868 coord.push_back(e->getVertex(k)->z());
3869 }
3870 }
3871 return;
3872 }
3873 else {
3874 Msg::Error("Unknown function space named '%s'", fsName.c_str());
3875 return;
3876 }
3877
3878 int vSize = basis->getnVertexFunction();
3879 int bSize = basis->getnBubbleFunction();
3880 int eSize = basis->getnEdgeFunction();
3881 int quadFSize = basis->getnQuadFaceFunction();
3882 int triFSize = basis->getnTriFaceFunction();
3883 int fSize = quadFSize + triFSize;
3884 int numberQuadFaces = basis->getNumQuadFace();
3885 int numberTriFaces = basis->getNumTriFace();
3886 int numTriFaceFunction = 0;
3887 if(basis->getNumTriFace() != 0) {
3888 numTriFaceFunction =
3889 triFSize /
3890 basis->getNumTriFace(); // number of Tri face functions for one face
3891 }
3892 int numQuadFaceFunction = 0;
3893 if(basis->getNumQuadFace() != 0) {
3894 numQuadFaceFunction =
3895 quadFSize /
3896 basis->getNumQuadFace(); // number of Tri face functions for one face
3897 }
3898 int numEdgeFunction = 0;
3899 if(basis->getNumEdge() != 0) {
3900 numEdgeFunction =
3901 eSize / basis->getNumEdge(); // number of edge functions for one edge
3902 }
3903 int const1 = numEdgeFunction + 1;
3904 int const2 = const1 + numQuadFaceFunction;
3905 int const3 = const1 + numTriFaceFunction;
3906 int const4 = bSize + std::max(const3, const2);
3907 int numDofsPerElement = vSize + bSize + eSize + fSize;
3908 delete basis;
3909
3910 typeKeys.reserve(numDofsPerElement);
3911 entityKeys.reserve(numDofsPerElement);
3912 if(returnCoord) { coord.reserve(3 * numDofsPerElement); }
3913
3914 // vertices
3915 for(int k = 0; k < vSize; k++) {
3916 typeKeys.push_back(0);
3917 entityKeys.push_back(e->getVertex(k)->getNum());
3918 if(returnCoord) {
3919 coord.push_back(e->getVertex(k)->x());
3920 coord.push_back(e->getVertex(k)->y());
3921 coord.push_back(e->getVertex(k)->z());
3922 }
3923 }
3924 // edges
3925 if(eSize > 0) {
3926 for(int jj = 0; jj < e->getNumEdges(); jj++) {
3927 MEdge edge = e->getEdge(jj);
3928 double coordEdge[3];
3929 if(returnCoord) {
3930 MVertex *v1 = edge.getVertex(0);
3931 MVertex *v2 = edge.getVertex(1);
3932
3933 coordEdge[0] = 0.5 * (v1->x() + v2->x());
3934 coordEdge[1] = 0.5 * (v1->y() + v2->y());
3935 coordEdge[2] = 0.5 * (v1->z() + v2->z());
3936 }
3937 std::size_t edgeGlobalIndice = GModel::current()->addMEdge(edge);
3938 for(int k = 1; k < const1; k++) {
3939 typeKeys.push_back(k);
3940 entityKeys.push_back(edgeGlobalIndice);
3941 if(returnCoord) {
3942 coord.push_back(coordEdge[0]);
3943 coord.push_back(coordEdge[1]);
3944 coord.push_back(coordEdge[2]);
3945 }
3946 }
3947 }
3948 }
3949 // faces
3950 if(fSize > 0) {
3951 for(int jj = 0; jj < numberQuadFaces + numberTriFaces; jj++) {
3952 // Number the faces
3953 MFace face = e->getFaceSolin(jj);
3954 double coordFace[3] = {0., 0., 0.};
3955 if(returnCoord) {
3956 for(std::size_t indexV = 0; indexV < face.getNumVertices(); ++indexV) {
3957 coordFace[0] += face.getVertex(indexV)->x();
3958 coordFace[1] += face.getVertex(indexV)->y();
3959 coordFace[2] += face.getVertex(indexV)->z();
3960 }
3961 coordFace[0] /= face.getNumVertices();
3962 coordFace[1] /= face.getNumVertices();
3963 coordFace[2] /= face.getNumVertices();
3964 }
3965 std::size_t faceGlobalIndice = GModel::current()->addMFace(face);
3966 int it2 = const2;
3967 if(jj >= numberQuadFaces) { it2 = const3; }
3968 for(int k = const1; k < it2; k++) {
3969 typeKeys.push_back(k);
3970 entityKeys.push_back(faceGlobalIndice);
3971 if(returnCoord) {
3972 coord.push_back(coordFace[0]);
3973 coord.push_back(coordFace[1]);
3974 coord.push_back(coordFace[2]);
3975 }
3976 }
3977 }
3978 }
3979 // volumes
3980 if(bSize > 0) {
3981 double bubbleCenterCoord[3] = {0., 0., 0.};
3982 if(returnCoord) {
3983 for(unsigned int indexV = 0; indexV < e->getNumVertices(); ++indexV) {
3984 bubbleCenterCoord[0] += e->getVertex(indexV)->x();
3985 bubbleCenterCoord[1] += e->getVertex(indexV)->y();
3986 bubbleCenterCoord[2] += e->getVertex(indexV)->z();
3987 }
3988 bubbleCenterCoord[0] /= e->getNumVertices();
3989 bubbleCenterCoord[1] /= e->getNumVertices();
3990 bubbleCenterCoord[2] /= e->getNumVertices();
3991 }
3992 for(int k = std::max(const3, const2); k < const4; k++) {
3993 typeKeys.push_back(k);
3994 entityKeys.push_back(e->getNum());
3995 if(returnCoord) {
3996 coord.push_back(bubbleCenterCoord[0]);
3997 coord.push_back(bubbleCenterCoord[1]);
3998 coord.push_back(bubbleCenterCoord[2]);
3999 }
4000 }
4001 }
4002 }
4003
getNumberOfKeys(const int elementType,const std::string & functionSpaceType)4004 GMSH_API int gmsh::model::mesh::getNumberOfKeys(
4005 const int elementType, const std::string &functionSpaceType)
4006 {
4007 int numberOfKeys = 0;
4008 int basisOrder = 0;
4009 std::string fsName = "";
4010 int numComponents = 0;
4011 if(!_getFunctionSpaceInfo(functionSpaceType, fsName, basisOrder,
4012 numComponents)) {
4013 Msg::Error("Unknown function space type '%s'", functionSpaceType.c_str());
4014 return 0;
4015 }
4016 int familyType = ElementType::getParentType(elementType);
4017 if(fsName == "H1Legendre" || fsName == "GradH1Legendre") {
4018 HierarchicalBasis *basis(nullptr);
4019 switch(familyType) {
4020 case TYPE_HEX: {
4021 basis = new HierarchicalBasisH1Brick(basisOrder);
4022 } break;
4023 case TYPE_PRI: {
4024 basis = new HierarchicalBasisH1Pri(basisOrder);
4025 } break;
4026 case TYPE_TET: {
4027 basis = new HierarchicalBasisH1Tetra(basisOrder);
4028 } break;
4029 case TYPE_QUA: {
4030 basis = new HierarchicalBasisH1Quad(basisOrder);
4031 } break;
4032 case TYPE_TRI: {
4033 basis = new HierarchicalBasisH1Tria(basisOrder);
4034 } break;
4035 case TYPE_LIN: {
4036 basis = new HierarchicalBasisH1Line(basisOrder);
4037 } break;
4038 case TYPE_PNT: {
4039 basis = new HierarchicalBasisH1Point();
4040 } break;
4041 default:
4042 Msg::Error("Unknown familyType %i for basis function type %s", familyType,
4043 fsName.c_str());
4044 return 0;
4045 }
4046 int vSize = basis->getnVertexFunction();
4047 int bSize = basis->getnBubbleFunction();
4048 int eSize = basis->getnEdgeFunction();
4049 int quadFSize = basis->getnQuadFaceFunction();
4050 int triFSize = basis->getnTriFaceFunction();
4051 numberOfKeys = vSize + bSize + eSize + quadFSize + triFSize;
4052 delete basis;
4053 }
4054 else if(fsName == "HcurlLegendre" || fsName == "CurlHcurlLegendre") {
4055 HierarchicalBasis *basis(nullptr);
4056 switch(familyType) {
4057 case TYPE_QUA: {
4058 basis = new HierarchicalBasisHcurlQuad(basisOrder);
4059 } break;
4060 case TYPE_HEX: {
4061 basis = new HierarchicalBasisHcurlBrick(basisOrder);
4062 } break;
4063 case TYPE_TRI: {
4064 basis = new HierarchicalBasisHcurlTria(basisOrder);
4065 } break;
4066 case TYPE_TET: {
4067 basis = new HierarchicalBasisHcurlTetra(basisOrder);
4068 } break;
4069 case TYPE_PRI: {
4070 basis = new HierarchicalBasisHcurlPri(basisOrder);
4071 } break;
4072 case TYPE_LIN: {
4073 basis = new HierarchicalBasisHcurlLine(basisOrder);
4074 } break;
4075 default:
4076 Msg::Error("Unknown familyType %i for basis function type %s", familyType,
4077 fsName.c_str());
4078 return 0;
4079 }
4080 int vSize = basis->getnVertexFunction();
4081 int bSize = basis->getnBubbleFunction();
4082 int eSize = basis->getnEdgeFunction();
4083 int quadFSize = basis->getnQuadFaceFunction();
4084 int triFSize = basis->getnTriFaceFunction();
4085 numberOfKeys = vSize + bSize + eSize + quadFSize + triFSize;
4086 delete basis;
4087 }
4088 else if(fsName == "IsoParametric" || fsName == "Lagrange" ||
4089 fsName == "GradIsoParametric" || fsName == "GradLagrange") {
4090 const nodalBasis *basis(nullptr);
4091 if(basisOrder == -1) { // isoparametric
4092 basis = BasisFactory::getNodalBasis(elementType);
4093 }
4094 else {
4095 int familyType = ElementType::getParentType(elementType);
4096 int newType = ElementType::getType(familyType, basisOrder, false);
4097 basis = BasisFactory::getNodalBasis(newType);
4098 }
4099 numberOfKeys = basis->getNumShapeFunctions();
4100 }
4101 else {
4102 Msg::Error("Unknown function space named '%s'", fsName.c_str());
4103 return 0;
4104 }
4105
4106 return numberOfKeys;
4107 }
4108
getKeysInformation(const std::vector<int> & typeKeys,const std::vector<std::size_t> & entityKeys,const int elementType,const std::string & functionSpaceType,gmsh::vectorpair & infoKeys)4109 GMSH_API void gmsh::model::mesh::getKeysInformation(
4110 const std::vector<int> &typeKeys, const std::vector<std::size_t> &entityKeys,
4111 const int elementType, const std::string &functionSpaceType,
4112 gmsh::vectorpair &infoKeys)
4113 {
4114 infoKeys.clear();
4115 int basisOrder = 0;
4116 std::string fsName = "";
4117 int numComponents = 0;
4118 if(!_getFunctionSpaceInfo(functionSpaceType, fsName, basisOrder,
4119 numComponents)) {
4120 Msg::Error("Unknown function space type '%s'", functionSpaceType.c_str());
4121 return;
4122 }
4123
4124 if(typeKeys.size() != entityKeys.size()) {
4125 Msg::Error("The size of 'typeKeys' is different of the size of "
4126 "'entityKeys' ('%i', '%i')",
4127 typeKeys.size(), entityKeys.size());
4128 return;
4129 }
4130
4131 HierarchicalBasis *basis(nullptr);
4132 int familyType = ElementType::getParentType(elementType);
4133 if(fsName == "H1Legendre" || fsName == "GradH1Legendre") {
4134 switch(familyType) {
4135 case TYPE_HEX: {
4136 basis = new HierarchicalBasisH1Brick(basisOrder);
4137 } break;
4138 case TYPE_PRI: {
4139 basis = new HierarchicalBasisH1Pri(basisOrder);
4140 } break;
4141 case TYPE_TET: {
4142 basis = new HierarchicalBasisH1Tetra(basisOrder);
4143 } break;
4144 case TYPE_QUA: {
4145 basis = new HierarchicalBasisH1Quad(basisOrder);
4146 } break;
4147 case TYPE_TRI: {
4148 basis = new HierarchicalBasisH1Tria(basisOrder);
4149 } break;
4150 case TYPE_LIN: {
4151 basis = new HierarchicalBasisH1Line(basisOrder);
4152 } break;
4153 case TYPE_PNT: {
4154 basis = new HierarchicalBasisH1Point();
4155 } break;
4156 default:
4157 Msg::Error("Unknown familyType %i for basis function type %s", familyType,
4158 fsName.c_str());
4159 return;
4160 }
4161 }
4162 else if(fsName == "HcurlLegendre" || fsName == "CurlHcurlLegendre") {
4163 switch(familyType) {
4164 case TYPE_QUA: {
4165 basis = new HierarchicalBasisHcurlQuad(basisOrder);
4166 } break;
4167 case TYPE_HEX: {
4168 basis = new HierarchicalBasisHcurlBrick(basisOrder);
4169 } break;
4170 case TYPE_TRI: {
4171 basis = new HierarchicalBasisHcurlTria(basisOrder);
4172 } break;
4173 case TYPE_TET: {
4174 basis = new HierarchicalBasisHcurlTetra(basisOrder);
4175 } break;
4176 case TYPE_PRI: {
4177 basis = new HierarchicalBasisHcurlPri(basisOrder);
4178 } break;
4179 case TYPE_LIN: {
4180 basis = new HierarchicalBasisHcurlLine(basisOrder);
4181 } break;
4182 default:
4183 Msg::Error("Unknown familyType %i for basis function type %s", familyType,
4184 fsName.c_str());
4185 return;
4186 }
4187 }
4188 else if(fsName == "IsoParametric" || fsName == "Lagrange" ||
4189 fsName == "GradIsoParametric" || fsName == "GradLagrange") {
4190 const nodalBasis *basis(nullptr);
4191 if(basisOrder == -1) { // isoparametric
4192 basis = BasisFactory::getNodalBasis(elementType);
4193 }
4194 else {
4195 int familyType = ElementType::getParentType(elementType);
4196 int newType = ElementType::getType(familyType, basisOrder, false);
4197 basis = BasisFactory::getNodalBasis(newType);
4198 }
4199 std::size_t numberOfKeys = basis->getNumShapeFunctions();
4200 std::size_t numberOfBubble = basis->getNumBubbleShapeFunctions();
4201 int dim = ElementType::getDimension(elementType);
4202
4203 if(numberOfBubble > numberOfKeys) {
4204 Msg::Error("Number of bubble functions greater than number of keys");
4205 return;
4206 }
4207
4208 infoKeys.reserve(typeKeys.size());
4209 for(size_t i = 0; i < typeKeys.size() / numberOfKeys; ++i) {
4210 for(size_t j = 0; j < numberOfKeys - numberOfBubble; ++j) {
4211 infoKeys.push_back(std::make_pair(0, basisOrder));
4212 }
4213 for(size_t j = 0; j < numberOfBubble; ++j) {
4214 infoKeys.push_back(std::make_pair(dim, basisOrder));
4215 }
4216 }
4217 return;
4218 }
4219 else {
4220 Msg::Error("Unknown function space named '%s'", fsName.c_str());
4221 return;
4222 }
4223
4224 int vSize = basis->getnVertexFunction();
4225 int bSize = basis->getnBubbleFunction();
4226 int eSize = basis->getnEdgeFunction();
4227 int quadFSize = basis->getnQuadFaceFunction();
4228 int triFSize = basis->getnTriFaceFunction();
4229 int numDofsPerElement = vSize + bSize + eSize + quadFSize + triFSize;
4230 std::vector<int> functionTypeInfo(numDofsPerElement);
4231 std::vector<int> orderInfo(numDofsPerElement);
4232 basis->getKeysInfo(functionTypeInfo, orderInfo);
4233 delete basis;
4234 std::size_t keySize = typeKeys.size();
4235 infoKeys.resize(keySize);
4236 std::size_t it = keySize / numDofsPerElement;
4237 for(std::size_t i = 0; i < it; i++) {
4238 size_t const1 = i * numDofsPerElement;
4239 for(int j = 0; j < numDofsPerElement; j++) {
4240 infoKeys[const1 + j] =
4241 std::make_pair(functionTypeInfo[j], orderInfo[j]);
4242 }
4243 }
4244 }
4245
getBarycenters(const int elementType,const int tag,const bool fast,const bool primary,std::vector<double> & barycenters,const std::size_t task,const std::size_t numTasks)4246 GMSH_API void gmsh::model::mesh::getBarycenters(
4247 const int elementType, const int tag, const bool fast, const bool primary,
4248 std::vector<double> &barycenters, const std::size_t task,
4249 const std::size_t numTasks)
4250 {
4251 if(!_checkInit()) return;
4252 int dim = ElementType::getDimension(elementType);
4253 std::map<int, std::vector<GEntity *> > typeEnt;
4254 _getEntitiesForElementTypes(dim, tag, typeEnt);
4255 const std::vector<GEntity *> &entities(typeEnt[elementType]);
4256 int familyType = ElementType::getParentType(elementType);
4257 std::size_t numElements = 0;
4258 for(std::size_t i = 0; i < entities.size(); i++) {
4259 GEntity *ge = entities[i];
4260 numElements += ge->getNumMeshElementsByType(familyType);
4261 }
4262 if(!numTasks) {
4263 Msg::Error("Number of tasks should be > 0");
4264 return;
4265 }
4266 const size_t begin = (task * numElements) / numTasks;
4267 const size_t end = ((task + 1) * numElements) / numTasks;
4268 if(3 * end > barycenters.size()) {
4269 if(numTasks > 1)
4270 Msg::Warning("Barycenters should be preallocated if numTasks > 1");
4271 barycenters.resize(3 * numElements);
4272 }
4273 size_t o = 0;
4274 size_t idx = 3 * begin;
4275 if(fast) {
4276 for(std::size_t i = 0; i < entities.size(); i++) {
4277 GEntity *ge = entities[i];
4278 for(std::size_t j = 0; j < ge->getNumMeshElementsByType(familyType);
4279 j++) {
4280 if(o >= begin && o < end) {
4281 MElement *e = ge->getMeshElementByType(familyType, j);
4282 SPoint3 p = e->fastBarycenter(primary);
4283 barycenters[idx++] = p[0];
4284 barycenters[idx++] = p[1];
4285 barycenters[idx++] = p[2];
4286 }
4287 o++;
4288 }
4289 }
4290 }
4291 else {
4292 for(std::size_t i = 0; i < entities.size(); i++) {
4293 GEntity *ge = entities[i];
4294 for(std::size_t j = 0; j < ge->getNumMeshElementsByType(familyType);
4295 j++) {
4296 if(o >= begin && o < end) {
4297 MElement *e = ge->getMeshElementByType(familyType, j);
4298 SPoint3 p = e->barycenter(primary);
4299 barycenters[idx++] = p[0];
4300 barycenters[idx++] = p[1];
4301 barycenters[idx++] = p[2];
4302 }
4303 o++;
4304 }
4305 }
4306 }
4307 }
4308
_getIntegrationInfo(const std::string & intType,std::string & intName,int & intOrder)4309 static bool _getIntegrationInfo(const std::string &intType,
4310 std::string &intName, int &intOrder)
4311 {
4312 if(intType.substr(0, 14) == "CompositeGauss") {
4313 intName = "CompositeGauss";
4314 intOrder = atoi(intType.substr(14).c_str());
4315 return true;
4316 }
4317 else if(intType.substr(0, 5) == "Gauss") {
4318 intName = "Gauss";
4319 intOrder = atoi(intType.substr(5).c_str());
4320 return true;
4321 }
4322 return false;
4323 }
4324
getIntegrationPoints(const int elementType,const std::string & integrationType,std::vector<double> & localCoord,std::vector<double> & weights)4325 GMSH_API void gmsh::model::mesh::getIntegrationPoints(
4326 const int elementType, const std::string &integrationType,
4327 std::vector<double> &localCoord, std::vector<double> &weights)
4328 {
4329 if(!_checkInit()) return;
4330 localCoord.clear();
4331 weights.clear();
4332 std::string intName = "";
4333 int intOrder = 0;
4334 if(!_getIntegrationInfo(integrationType, intName, intOrder)) {
4335 Msg::Error("Unknown quadrature type '%s'", integrationType.c_str());
4336 return;
4337 }
4338 // get quadrature info
4339 int familyType = ElementType::getParentType(elementType);
4340 fullMatrix<double> pts;
4341 fullVector<double> wgs;
4342 gaussIntegration::get(familyType, intOrder, pts, wgs,
4343 intName == "Gauss" ? false : true);
4344 if(pts.size1() != wgs.size() || pts.size2() != 3) {
4345 Msg::Error("Wrong integration point format");
4346 return;
4347 }
4348 localCoord.resize(3 * pts.size1());
4349 weights.resize(pts.size1());
4350 for(int i = 0; i < pts.size1(); i++) {
4351 localCoord[3 * i] = pts(i, 0);
4352 localCoord[3 * i + 1] = pts(i, 1);
4353 localCoord[3 * i + 2] = pts(i, 2);
4354 weights[i] = wgs(i);
4355 }
4356 }
4357
preallocateBarycenters(const int elementType,std::vector<double> & barycenters,const int tag)4358 GMSH_API void gmsh::model::mesh::preallocateBarycenters(
4359 const int elementType, std::vector<double> &barycenters, const int tag)
4360 {
4361 if(!_checkInit()) return;
4362 int dim = ElementType::getDimension(elementType);
4363 std::map<int, std::vector<GEntity *> > typeEnt;
4364 _getEntitiesForElementTypes(dim, tag, typeEnt);
4365 const std::vector<GEntity *> &entities(typeEnt[elementType]);
4366 int familyType = ElementType::getParentType(elementType);
4367 std::size_t numElements = 0;
4368 for(std::size_t i = 0; i < entities.size(); i++)
4369 numElements += entities[i]->getNumMeshElementsByType(familyType);
4370 barycenters.clear();
4371 barycenters.resize(3 * numElements, 0);
4372 }
4373
getElementEdgeNodes(const int elementType,std::vector<std::size_t> & nodeTags,const int tag,const bool primary,const std::size_t task,const std::size_t numTasks)4374 GMSH_API void gmsh::model::mesh::getElementEdgeNodes(
4375 const int elementType, std::vector<std::size_t> &nodeTags, const int tag,
4376 const bool primary, const std::size_t task, const std::size_t numTasks)
4377 {
4378 if(!_checkInit()) return;
4379 int dim = ElementType::getDimension(elementType);
4380 std::map<int, std::vector<GEntity *> > typeEnt;
4381 _getEntitiesForElementTypes(dim, tag, typeEnt);
4382 const std::vector<GEntity *> &entities(typeEnt[elementType]);
4383 int familyType = ElementType::getParentType(elementType);
4384 std::size_t numElements = 0;
4385 int numEdgesPerEle = 0, numNodesPerEdge = 0;
4386 for(std::size_t i = 0; i < entities.size(); i++) {
4387 GEntity *ge = entities[i];
4388 int n = ge->getNumMeshElementsByType(familyType);
4389 if(n && !numNodesPerEdge) {
4390 MElement *e = ge->getMeshElementByType(familyType, 0);
4391 numEdgesPerEle = e->getNumEdges();
4392 if(primary) { numNodesPerEdge = 2; }
4393 else {
4394 std::vector<MVertex *> v;
4395 // we could use e->getHighOrderEdge() here if we decide to remove
4396 // getEdgeVertices
4397 e->getEdgeVertices(0, v);
4398 numNodesPerEdge = v.size();
4399 }
4400 }
4401 numElements += n;
4402 }
4403 if(!numTasks) {
4404 Msg::Error("Number of tasks should be > 0");
4405 return;
4406 }
4407 const size_t begin = (task * numElements) / numTasks;
4408 const size_t end = ((task + 1) * numElements) / numTasks;
4409 if(numEdgesPerEle * numNodesPerEdge * end > nodeTags.size()) {
4410 if(numTasks > 1)
4411 Msg::Warning("Nodes should be preallocated if numTasks > 1");
4412 nodeTags.resize(numEdgesPerEle * numNodesPerEdge * numElements);
4413 }
4414 size_t o = 0;
4415 size_t idx = numEdgesPerEle * numNodesPerEdge * begin;
4416 for(std::size_t i = 0; i < entities.size(); i++) {
4417 GEntity *ge = entities[i];
4418 for(std::size_t j = 0; j < ge->getNumMeshElementsByType(familyType); j++) {
4419 if(o >= begin && o < end) {
4420 MElement *e = ge->getMeshElementByType(familyType, j);
4421 for(int k = 0; k < numEdgesPerEle; k++) {
4422 std::vector<MVertex *> v;
4423 // we could use e->getHighOrderEdge() here if we decide to remove
4424 // getEdgeVertices
4425 e->getEdgeVertices(k, v);
4426 std::size_t N = primary ? 2 : v.size();
4427 for(std::size_t l = 0; l < N; l++) {
4428 nodeTags[idx++] = v[l]->getNum();
4429 }
4430 }
4431 }
4432 o++;
4433 }
4434 }
4435 }
4436
getElementFaceNodes(const int elementType,const int faceType,std::vector<std::size_t> & nodeTags,const int tag,const bool primary,const std::size_t task,const std::size_t numTasks)4437 GMSH_API void gmsh::model::mesh::getElementFaceNodes(
4438 const int elementType, const int faceType, std::vector<std::size_t> &nodeTags,
4439 const int tag, const bool primary, const std::size_t task,
4440 const std::size_t numTasks)
4441 {
4442 if(!_checkInit()) return;
4443 int dim = ElementType::getDimension(elementType);
4444 std::map<int, std::vector<GEntity *> > typeEnt;
4445 _getEntitiesForElementTypes(dim, tag, typeEnt);
4446 const std::vector<GEntity *> &entities(typeEnt[elementType]);
4447 int familyType = ElementType::getParentType(elementType);
4448 std::size_t numElements = 0;
4449 int numFacesPerEle = 0, numNodesPerFace = 0;
4450 for(std::size_t i = 0; i < entities.size(); i++) {
4451 GEntity *ge = entities[i];
4452 int n = ge->getNumMeshElementsByType(familyType);
4453 if(n && !numNodesPerFace) {
4454 MElement *e = ge->getMeshElementByType(familyType, 0);
4455 int nf = e->getNumFaces();
4456 numFacesPerEle = 0;
4457 for(int j = 0; j < nf; j++) {
4458 MFace f = e->getFace(j);
4459 if(faceType == (int)f.getNumVertices()) numFacesPerEle++;
4460 }
4461 if(primary) { numNodesPerFace = faceType; }
4462 else {
4463 std::vector<MVertex *> v;
4464 // we could use e->getHighOrderFace() here if we decide to remove
4465 // getFaceVertices
4466 e->getFaceVertices(0, v);
4467 numNodesPerFace = v.size();
4468 }
4469 }
4470 numElements += n;
4471 }
4472 if(!numTasks) {
4473 Msg::Error("Number of tasks should be > 0");
4474 return;
4475 }
4476 const size_t begin = (task * numElements) / numTasks;
4477 const size_t end = ((task + 1) * numElements) / numTasks;
4478 if(numFacesPerEle * numNodesPerFace * end > nodeTags.size()) {
4479 if(numTasks > 1)
4480 Msg::Warning("Nodes should be preallocated if numTasks > 1");
4481 nodeTags.resize(numFacesPerEle * numNodesPerFace * numElements);
4482 }
4483 size_t o = 0;
4484 size_t idx = numFacesPerEle * numNodesPerFace * begin;
4485 for(std::size_t i = 0; i < entities.size(); i++) {
4486 GEntity *ge = entities[i];
4487 for(std::size_t j = 0; j < ge->getNumMeshElementsByType(familyType); j++) {
4488 if(o >= begin && o < end) {
4489 MElement *e = ge->getMeshElementByType(familyType, j);
4490 int nf = e->getNumFaces();
4491 for(int k = 0; k < nf; k++) {
4492 MFace f = e->getFace(k);
4493 if(faceType != (int)f.getNumVertices()) continue;
4494 std::vector<MVertex *> v;
4495 // we could use e->getHighOrderFace() here if we decide to remove
4496 // getFaceVertices
4497 e->getFaceVertices(k, v);
4498 std::size_t N = primary ? faceType : v.size();
4499 for(std::size_t l = 0; l < N; l++) {
4500 nodeTags[idx++] = v[l]->getNum();
4501 }
4502 }
4503 }
4504 o++;
4505 }
4506 }
4507 }
4508
4509 GMSH_API void
getGhostElements(const int dim,const int tag,std::vector<std::size_t> & elementTags,std::vector<int> & partitions)4510 gmsh::model::mesh::getGhostElements(const int dim, const int tag,
4511 std::vector<std::size_t> &elementTags,
4512 std::vector<int> &partitions)
4513 {
4514 if(!_checkInit()) return;
4515 elementTags.clear();
4516 partitions.clear();
4517 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
4518 if(!ge) {
4519 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
4520 return;
4521 }
4522 std::map<MElement *, int> ghostCells;
4523 if(ge->geomType() == GEntity::GhostCurve)
4524 ghostCells = static_cast<ghostEdge *>(ge)->getGhostCells();
4525 else if(ge->geomType() == GEntity::GhostSurface)
4526 ghostCells = static_cast<ghostFace *>(ge)->getGhostCells();
4527 else if(ge->geomType() == GEntity::GhostVolume)
4528 ghostCells = static_cast<ghostRegion *>(ge)->getGhostCells();
4529
4530 for(auto it = ghostCells.begin(); it != ghostCells.end(); it++) {
4531 elementTags.push_back(it->first->getNum());
4532 partitions.push_back(it->second);
4533 }
4534 }
4535
setSize(const vectorpair & dimTags,const double size)4536 GMSH_API void gmsh::model::mesh::setSize(const vectorpair &dimTags,
4537 const double size)
4538 {
4539 if(!_checkInit()) return;
4540 for(std::size_t i = 0; i < dimTags.size(); i++) {
4541 int dim = dimTags[i].first, tag = dimTags[i].second;
4542 if(dim == 0) {
4543 GVertex *gv = GModel::current()->getVertexByTag(tag);
4544 if(gv) gv->setPrescribedMeshSizeAtVertex(size);
4545 }
4546 }
4547 }
4548
getSizes(const vectorpair & dimTags,std::vector<double> & sizes)4549 GMSH_API void gmsh::model::mesh::getSizes(const vectorpair &dimTags,
4550 std::vector<double> &sizes)
4551 {
4552 if(!_checkInit()) return;
4553 sizes.clear();
4554 if(dimTags.empty()) return;
4555 sizes.resize(dimTags.size(), 0.);
4556 for(std::size_t i = 0; i < dimTags.size(); i++) {
4557 int dim = dimTags[i].first, tag = dimTags[i].second;
4558 if(dim == 0) {
4559 GVertex *gv = GModel::current()->getVertexByTag(tag);
4560 if(gv) {
4561 double s = gv->prescribedMeshSizeAtVertex();
4562 if(s != MAX_LC) sizes[i] = s;
4563 }
4564 }
4565 }
4566 }
4567
setSizeAtParametricPoints(const int dim,const int tag,const std::vector<double> & parametricCoord,const std::vector<double> & sizes)4568 GMSH_API void gmsh::model::mesh::setSizeAtParametricPoints(
4569 const int dim, const int tag, const std::vector<double> ¶metricCoord,
4570 const std::vector<double> &sizes)
4571 {
4572 if(!_checkInit()) return;
4573 if(dim == 1) {
4574 GEdge *ge = GModel::current()->getEdgeByTag(tag);
4575 if(ge) ge->setMeshSizeParametric(parametricCoord, sizes);
4576 }
4577 }
4578
setSizeCallback(std::function<double (int,int,double,double,double,double)> callback)4579 GMSH_API void gmsh::model::mesh::setSizeCallback(
4580 std::function<double(int, int, double, double, double, double)> callback)
4581 {
4582 if(!_checkInit()) return;
4583 GModel::current()->lcCallback = callback;
4584 }
4585
removeSizeCallback()4586 GMSH_API void gmsh::model::mesh::removeSizeCallback()
4587 {
4588 if(!_checkInit()) return;
4589 GModel::current()->lcCallback = nullptr;
4590 }
4591
4592 GMSH_API void
setTransfiniteCurve(const int tag,const int numNodes,const std::string & meshType,const double coef)4593 gmsh::model::mesh::setTransfiniteCurve(const int tag, const int numNodes,
4594 const std::string &meshType,
4595 const double coef)
4596 {
4597 if(!_checkInit()) return;
4598 // for compatibility with geo files, try both tag and -tag
4599 for(int sig = -1; sig <= 1; sig += 2) {
4600 int t = sig * tag;
4601 GEdge *ge = GModel::current()->getEdgeByTag(t);
4602 if(ge) {
4603 ge->meshAttributes.method = MESH_TRANSFINITE;
4604 ge->meshAttributes.nbPointsTransfinite = numNodes;
4605 ge->meshAttributes.typeTransfinite =
4606 (meshType == "Progression" || meshType == "Power") ? 1 :
4607 (meshType == "Bump") ? 2 :
4608 (meshType == "Beta") ? 3 :
4609 1;
4610 ge->meshAttributes.coeffTransfinite = std::abs(coef);
4611 // in .geo file we use a negative tag to do this trick; it's a bad idea
4612 if(coef < 0) ge->meshAttributes.typeTransfinite *= -1;
4613 }
4614 else {
4615 if(t > 0) {
4616 Msg::Error("%s does not exist", _getEntityName(1, t).c_str());
4617 return;
4618 }
4619 }
4620 }
4621 }
4622
4623 GMSH_API void
setTransfiniteSurface(const int tag,const std::string & arrangement,const std::vector<int> & cornerTags)4624 gmsh::model::mesh::setTransfiniteSurface(const int tag,
4625 const std::string &arrangement,
4626 const std::vector<int> &cornerTags)
4627 {
4628 if(!_checkInit()) return;
4629 GFace *gf = GModel::current()->getFaceByTag(tag);
4630 if(!gf) {
4631 Msg::Error("%s does not exist", _getEntityName(2, tag).c_str());
4632 return;
4633 }
4634 gf->meshAttributes.method = MESH_TRANSFINITE;
4635 gf->meshAttributes.transfiniteArrangement =
4636 (arrangement == "Right") ? 1 :
4637 (arrangement == "Left") ? -1 :
4638 (arrangement == "AlternateRight") ? 2 :
4639 (arrangement == "AlternateLeft") ? -2 :
4640 (arrangement == "Alternate") ? 2 :
4641 -1;
4642 if(cornerTags.empty() || cornerTags.size() == 3 || cornerTags.size() == 4) {
4643 for(std::size_t j = 0; j < cornerTags.size(); j++) {
4644 GVertex *gv = GModel::current()->getVertexByTag(cornerTags[j]);
4645 if(gv) gf->meshAttributes.corners.push_back(gv);
4646 }
4647 }
4648 }
4649
4650 GMSH_API void
setTransfiniteVolume(const int tag,const std::vector<int> & cornerTags)4651 gmsh::model::mesh::setTransfiniteVolume(const int tag,
4652 const std::vector<int> &cornerTags)
4653 {
4654 if(!_checkInit()) return;
4655 GRegion *gr = GModel::current()->getRegionByTag(tag);
4656 if(!gr) {
4657 Msg::Error("%s does not exist", _getEntityName(3, tag).c_str());
4658 return;
4659 }
4660 gr->meshAttributes.method = MESH_TRANSFINITE;
4661 if(cornerTags.empty() || cornerTags.size() == 6 || cornerTags.size() == 8) {
4662 for(std::size_t i = 0; i < cornerTags.size(); i++) {
4663 GVertex *gv = GModel::current()->getVertexByTag(cornerTags[i]);
4664 if(gv) gr->meshAttributes.corners.push_back(gv);
4665 }
4666 }
4667 }
4668
_eulerCharacteristic(GRegion * gr)4669 int _eulerCharacteristic(GRegion *gr)
4670 {
4671 std::set<GVertex *> vertices;
4672 std::set<GEdge *> edges;
4673 for(std::size_t _i = 0; _i < gr->faces().size(); ++_i) {
4674 GFace *gf = gr->faces()[_i];
4675 for(std::size_t j = 0; j < gf->edges().size(); ++j) {
4676 GEdge *ge = gf->edges()[j];
4677 edges.insert(ge);
4678 vertices.insert(ge->getBeginVertex());
4679 vertices.insert(ge->getEndVertex());
4680 }
4681 }
4682 int X = int(vertices.size()) - int(edges.size()) + int(gr->faces().size());
4683 return X;
4684 }
4685
setTransfiniteAutomatic(const vectorpair & dimTags,const double cornerAngle,const bool recombine)4686 GMSH_API void gmsh::model::mesh::setTransfiniteAutomatic(
4687 const vectorpair &dimTags, const double cornerAngle, const bool recombine)
4688 {
4689 #if defined(HAVE_MESH)
4690 if(!_checkInit()) return;
4691 Msg::Debug("setTransfiniteAutomatic() with cornerAngle=%.3f, recombine=%i",
4692 cornerAngle, int(recombine));
4693
4694 // Collect all quad 4-sided faces (from given faces and volumes)
4695 std::set<GFace *> faces;
4696 if(dimTags.size() == 0) { // Empty dimTag => all faces
4697 std::vector<GEntity *> entities;
4698 GModel::current()->getEntities(entities, 2);
4699 for(std::size_t i = 0; i < entities.size(); i++) {
4700 GFace *gf = static_cast<GFace *>(entities[i]);
4701 if(gf->edges().size() == 4) { faces.insert(gf); }
4702 }
4703 }
4704 else {
4705 for(std::size_t i = 0; i < dimTags.size(); ++i) {
4706 if(dimTags[i].first == 2) {
4707 int tag = dimTags[i].second;
4708 GFace *gf = GModel::current()->getFaceByTag(tag);
4709 if(!gf) {
4710 Msg::Error("%s does not exist", _getEntityName(2, tag).c_str());
4711 return;
4712 }
4713 if(gf->edges().size() == 4) { faces.insert(gf); }
4714 }
4715 else if(dimTags[i].first == 3) {
4716 int tag = dimTags[i].second;
4717 GRegion *gr = GModel::current()->getRegionByTag(tag);
4718 if(!gr) {
4719 Msg::Error("%s does not exist", _getEntityName(3, tag).c_str());
4720 return;
4721 }
4722 for(GFace *gf : gr->faces()) {
4723 if(gf->edges().size() == 4) { faces.insert(gf); }
4724 }
4725 }
4726 }
4727 }
4728
4729 // Build the chords, compute the averaged number of points on each chord,
4730 // assign the transfinite attributes
4731 bool okf = MeshSetTransfiniteFacesAutomatic(faces, cornerAngle, recombine);
4732 if(!okf) {
4733 Msg::Error("failed to automatically set transfinite faces");
4734 return;
4735 }
4736
4737 // Collect the 6-sided volumes with Euler characteristic equal to 2 (ie ball)
4738 std::set<GRegion *> regions;
4739 if(dimTags.size() == 0) { // Empty dimTag => all faces
4740 std::vector<GEntity *> entities;
4741 GModel::current()->getEntities(entities, 3);
4742 for(std::size_t i = 0; i < entities.size(); i++) {
4743 GRegion *gr = static_cast<GRegion *>(entities[i]);
4744 if(gr->faces().size() == 6 && _eulerCharacteristic(gr) == 2) {
4745 regions.insert(gr);
4746 }
4747 }
4748 }
4749 else {
4750 for(std::size_t i = 0; i < dimTags.size(); ++i) {
4751 if(dimTags[i].first == 3) {
4752 int tag = dimTags[i].second;
4753 GRegion *gr = GModel::current()->getRegionByTag(tag);
4754 if(!gr) {
4755 Msg::Error("%s does not exist", _getEntityName(3, tag).c_str());
4756 return;
4757 }
4758 if(gr->faces().size() == 6 && _eulerCharacteristic(gr) == 2) {
4759 regions.insert(gr);
4760 }
4761 }
4762 }
4763 }
4764
4765 std::size_t nr = 0;
4766 for(GRegion *gr : regions) {
4767 bool transfinite = true;
4768 for(GFace *gf : gr->faces()) {
4769 if(gf->meshAttributes.method != MESH_TRANSFINITE) {
4770 transfinite = false;
4771 break;
4772 }
4773 if(transfinite) {
4774 gr->meshAttributes.method = MESH_TRANSFINITE;
4775 nr += 1;
4776 }
4777 }
4778 }
4779 if(nr > 0)
4780 Msg::Debug("transfinite automatic: transfinite set on %li volumes", nr);
4781 #else
4782 Msg::Error("setTransfiniteAutomatic requires the mesh module");
4783 #endif
4784 }
4785
setRecombine(const int dim,const int tag)4786 GMSH_API void gmsh::model::mesh::setRecombine(const int dim, const int tag)
4787 {
4788 if(!_checkInit()) return;
4789 if(dim == 2) {
4790 GFace *gf = GModel::current()->getFaceByTag(tag);
4791 if(!gf) {
4792 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
4793 return;
4794 }
4795 gf->meshAttributes.recombine = 1;
4796 gf->meshAttributes.recombineAngle = 45.;
4797 }
4798 }
4799
setSmoothing(const int dim,const int tag,const int val)4800 GMSH_API void gmsh::model::mesh::setSmoothing(const int dim, const int tag,
4801 const int val)
4802 {
4803 if(!_checkInit()) return;
4804 if(dim == 2) {
4805 GFace *gf = GModel::current()->getFaceByTag(tag);
4806 if(!gf) {
4807 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
4808 return;
4809 }
4810 gf->meshAttributes.transfiniteSmoothing = val;
4811 }
4812 }
4813
setReverse(const int dim,const int tag,const bool val)4814 GMSH_API void gmsh::model::mesh::setReverse(const int dim, const int tag,
4815 const bool val)
4816 {
4817 if(!_checkInit()) return;
4818 if(dim == 1) {
4819 GEdge *ge = GModel::current()->getEdgeByTag(tag);
4820 if(!ge) {
4821 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
4822 return;
4823 }
4824 ge->meshAttributes.reverseMesh = val;
4825 }
4826 else if(dim == 2) {
4827 GFace *gf = GModel::current()->getFaceByTag(tag);
4828 if(!gf) {
4829 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
4830 return;
4831 }
4832 gf->meshAttributes.reverseMesh = val;
4833 }
4834 }
4835
setAlgorithm(const int dim,const int tag,const int val)4836 GMSH_API void gmsh::model::mesh::setAlgorithm(const int dim, const int tag,
4837 const int val)
4838 {
4839 if(!_checkInit()) return;
4840 if(dim == 2) {
4841 GFace *gf = GModel::current()->getFaceByTag(tag);
4842 if(!gf) {
4843 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
4844 return;
4845 }
4846 gf->meshAttributes.algorithm = val;
4847 }
4848 }
4849
setSizeFromBoundary(const int dim,const int tag,const int val)4850 GMSH_API void gmsh::model::mesh::setSizeFromBoundary(const int dim,
4851 const int tag,
4852 const int val)
4853 {
4854 if(!_checkInit()) return;
4855 if(dim == 2) {
4856 GFace *gf = GModel::current()->getFaceByTag(tag);
4857 if(!gf) {
4858 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
4859 return;
4860 }
4861 gf->meshAttributes.meshSizeFromBoundary = val;
4862 }
4863 }
4864
setCompound(const int dim,const std::vector<int> & tags)4865 GMSH_API void gmsh::model::mesh::setCompound(const int dim,
4866 const std::vector<int> &tags)
4867 {
4868 if(!_checkInit()) return;
4869 std::vector<GEntity *> ents;
4870 for(std::size_t i = 0; i < tags.size(); i++) {
4871 GEntity *ent = GModel::current()->getEntityByTag(dim, tags[i]);
4872 if(ent) { ents.push_back(ent); }
4873 else {
4874 Msg::Error("%s does not exist", _getEntityName(dim, tags[i]).c_str());
4875 }
4876 }
4877 for(std::size_t i = 0; i < ents.size(); i++) { ents[i]->compound = ents; }
4878 }
4879
setOutwardOrientation(const int tag)4880 GMSH_API void gmsh::model::mesh::setOutwardOrientation(const int tag)
4881 {
4882 if(!_checkInit()) return;
4883 GRegion *gr = GModel::current()->getRegionByTag(tag);
4884 if(!gr) {
4885 Msg::Error("%s does not exist", _getEntityName(3, tag).c_str());
4886 return;
4887 }
4888 gr->setOutwardOrientationMeshConstraint();
4889 }
4890
removeConstraints(const vectorpair & dimTags)4891 GMSH_API void gmsh::model::mesh::removeConstraints(const vectorpair &dimTags)
4892 {
4893 if(!_checkInit()) return;
4894 std::vector<GEntity *> entities;
4895 _getEntities(dimTags, entities);
4896 for(std::size_t i = 0; i < entities.size(); i++)
4897 entities[i]->resetMeshAttributes();
4898 }
4899
embed(const int dim,const std::vector<int> & tags,const int inDim,const int inTag)4900 GMSH_API void gmsh::model::mesh::embed(const int dim,
4901 const std::vector<int> &tags,
4902 const int inDim, const int inTag)
4903 {
4904 if(!_checkInit()) return;
4905 if(inDim == 2) {
4906 GFace *gf = GModel::current()->getFaceByTag(inTag);
4907 if(!gf) {
4908 Msg::Error("%s does not exist", _getEntityName(2, inTag).c_str());
4909 return;
4910 }
4911 for(std::size_t i = 0; i < tags.size(); i++) {
4912 if(dim == 0) {
4913 GVertex *gv = GModel::current()->getVertexByTag(tags[i]);
4914 if(!gv) {
4915 Msg::Error("%s does not exist", _getEntityName(0, tags[i]).c_str());
4916 return;
4917 }
4918 gf->addEmbeddedVertex(gv);
4919 }
4920 else if(dim == 1) {
4921 GEdge *ge = GModel::current()->getEdgeByTag(tags[i]);
4922 if(!ge) {
4923 Msg::Error("%s does not exist", _getEntityName(1, tags[i]).c_str());
4924 return;
4925 }
4926 gf->addEmbeddedEdge(ge);
4927 }
4928 }
4929 }
4930 else if(inDim == 3) {
4931 GRegion *gr = GModel::current()->getRegionByTag(inTag);
4932 if(!gr) {
4933 Msg::Error("%s does not exist", _getEntityName(3, inTag).c_str());
4934 return;
4935 }
4936 for(std::size_t i = 0; i < tags.size(); i++) {
4937 if(dim == 0) {
4938 GVertex *gv = GModel::current()->getVertexByTag(tags[i]);
4939 if(!gv) {
4940 Msg::Error("%s does not exist", _getEntityName(0, tags[i]).c_str());
4941 return;
4942 }
4943 gr->addEmbeddedVertex(gv);
4944 }
4945 else if(dim == 1) {
4946 GEdge *ge = GModel::current()->getEdgeByTag(tags[i]);
4947 if(!ge) {
4948 Msg::Error("%s does not exist", _getEntityName(1, tags[i]).c_str());
4949 return;
4950 }
4951 gr->addEmbeddedEdge(ge);
4952 }
4953 else if(dim == 2) {
4954 GFace *gf = GModel::current()->getFaceByTag(tags[i]);
4955 if(!gf) {
4956 Msg::Error("%s does not exist", _getEntityName(2, tags[i]).c_str());
4957 return;
4958 }
4959 gr->addEmbeddedFace(gf);
4960 }
4961 }
4962 }
4963 }
4964
removeEmbedded(const vectorpair & dimTags,const int rdim)4965 GMSH_API void gmsh::model::mesh::removeEmbedded(const vectorpair &dimTags,
4966 const int rdim)
4967 {
4968 if(!_checkInit()) return;
4969 for(std::size_t i = 0; i < dimTags.size(); i++) {
4970 int dim = dimTags[i].first, tag = dimTags[i].second;
4971 if(dim == 2) {
4972 GFace *gf = GModel::current()->getFaceByTag(tag);
4973 if(!gf) {
4974 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
4975 return;
4976 }
4977 if(rdim < 0 || rdim == 1) gf->embeddedEdges().clear();
4978 if(rdim < 0 || rdim == 0) gf->embeddedVertices().clear();
4979 }
4980 else if(dimTags[i].first == 3) {
4981 GRegion *gr = GModel::current()->getRegionByTag(tag);
4982 if(!gr) {
4983 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
4984 return;
4985 }
4986 if(rdim < 0 || rdim == 2) gr->embeddedFaces().clear();
4987 if(rdim < 0 || rdim == 1) gr->embeddedEdges().clear();
4988 if(rdim < 0 || rdim == 0) gr->embeddedVertices().clear();
4989 }
4990 }
4991 }
4992
getEmbedded(const int dim,const int tag,vectorpair & dimTags)4993 GMSH_API void gmsh::model::mesh::getEmbedded(const int dim, const int tag,
4994 vectorpair &dimTags)
4995 {
4996 if(!_checkInit()) return;
4997 dimTags.clear();
4998 if(dim == 2) {
4999 GFace *gf = GModel::current()->getFaceByTag(tag);
5000 if(!gf) {
5001 Msg::Error("%s does not exist", _getEntityName(2, tag).c_str());
5002 return;
5003 }
5004 for(auto v : gf->embeddedVertices())
5005 dimTags.push_back(std::make_pair(v->dim(), v->tag()));
5006 for(auto e : gf->embeddedEdges())
5007 dimTags.push_back(std::make_pair(e->dim(), e->tag()));
5008 }
5009 else if(dim == 3) {
5010 GRegion *gr = GModel::current()->getRegionByTag(tag);
5011 if(!gr) {
5012 Msg::Error("%s does not exist", _getEntityName(3, tag).c_str());
5013 return;
5014 }
5015 for(auto v : gr->embeddedVertices())
5016 dimTags.push_back(std::make_pair(v->dim(), v->tag()));
5017 for(auto e : gr->embeddedEdges())
5018 dimTags.push_back(std::make_pair(e->dim(), e->tag()));
5019 for(auto f : gr->embeddedFaces())
5020 dimTags.push_back(std::make_pair(f->dim(), f->tag()));
5021 }
5022 }
5023
5024 GMSH_API void
reorderElements(const int elementType,const int tag,const std::vector<std::size_t> & ordering)5025 gmsh::model::mesh::reorderElements(const int elementType, const int tag,
5026 const std::vector<std::size_t> &ordering)
5027 {
5028 if(!_checkInit()) return;
5029 int dim = ElementType::getDimension(elementType);
5030 std::map<int, std::vector<GEntity *> > typeEnt;
5031 _getEntitiesForElementTypes(dim, tag, typeEnt);
5032 const std::vector<GEntity *> &entities(typeEnt[elementType]);
5033 if(entities.empty()) {
5034 Msg::Error("No elements to reorder");
5035 return;
5036 }
5037 for(std::size_t i = 0; i < entities.size(); i++) {
5038 if(!entities[i]->reorder(elementType, ordering)) {
5039 Msg::Error("Could not reorder elements");
5040 return;
5041 }
5042 }
5043 }
5044
renumberNodes()5045 GMSH_API void gmsh::model::mesh::renumberNodes()
5046 {
5047 if(!_checkInit()) return;
5048 GModel::current()->renumberMeshVertices();
5049 }
5050
renumberElements()5051 GMSH_API void gmsh::model::mesh::renumberElements()
5052 {
5053 if(!_checkInit()) return;
5054 GModel::current()->renumberMeshElements();
5055 }
5056
5057 GMSH_API void
setPeriodic(const int dim,const std::vector<int> & tags,const std::vector<int> & tagsMaster,const std::vector<double> & affineTransform)5058 gmsh::model::mesh::setPeriodic(const int dim, const std::vector<int> &tags,
5059 const std::vector<int> &tagsMaster,
5060 const std::vector<double> &affineTransform)
5061 {
5062 if(!_checkInit()) return;
5063 if(tags.size() != tagsMaster.size()) {
5064 Msg::Error("Incompatible number of tags and master tags for periodic mesh");
5065 return;
5066 }
5067 if(affineTransform.size() != 16) {
5068 Msg::Error("Wrong number of elements in affine transformation (%d != 16)",
5069 (int)affineTransform.size());
5070 return;
5071 }
5072 for(std::size_t i = 0; i < tags.size(); i++) {
5073 if(dim == 1) {
5074 GEdge *target = GModel::current()->getEdgeByTag(tags[i]);
5075 if(!target) {
5076 Msg::Error("%s does not exist", _getEntityName(dim, tags[i]).c_str());
5077 return;
5078 }
5079 GEdge *source = GModel::current()->getEdgeByTag(tagsMaster[i]);
5080 if(!source) {
5081 Msg::Error("%s does not exist",
5082 _getEntityName(dim, tagsMaster[i]).c_str());
5083 return;
5084 }
5085 target->setMeshMaster(source, affineTransform);
5086 }
5087 else if(dim == 2) {
5088 GFace *target = GModel::current()->getFaceByTag(tags[i]);
5089 if(!target) {
5090 Msg::Error("%s does not exist", _getEntityName(dim, tags[i]).c_str());
5091 return;
5092 }
5093 GFace *source = GModel::current()->getFaceByTag(tagsMaster[i]);
5094 if(!source) {
5095 Msg::Error("%s does not exist",
5096 _getEntityName(dim, tagsMaster[i]).c_str());
5097 return;
5098 }
5099 target->setMeshMaster(source, affineTransform);
5100 }
5101 }
5102 }
5103
5104 GMSH_API void
getPeriodic(const int dim,const std::vector<int> & tags,std::vector<int> & tagsMaster)5105 gmsh::model::mesh::getPeriodic(const int dim, const std::vector<int> &tags,
5106 std::vector<int> &tagsMaster)
5107 {
5108 if(!_checkInit()) return;
5109 tagsMaster.clear();
5110 tagsMaster.reserve(tags.size());
5111 for(auto i : tags) {
5112 GEntity *ge = GModel::current()->getEntityByTag(dim, i);
5113 if(!ge) {
5114 Msg::Error("%s does not exist", _getEntityName(dim, i).c_str());
5115 return;
5116 }
5117 tagsMaster.push_back(ge->getMeshMaster()->tag());
5118 }
5119 }
5120
getPeriodicNodes(const int dim,const int tag,int & tagMaster,std::vector<std::size_t> & nodeTags,std::vector<std::size_t> & nodeTagsMaster,std::vector<double> & affineTransform,const bool includeHighOrderNodes)5121 GMSH_API void gmsh::model::mesh::getPeriodicNodes(
5122 const int dim, const int tag, int &tagMaster,
5123 std::vector<std::size_t> &nodeTags, std::vector<std::size_t> &nodeTagsMaster,
5124 std::vector<double> &affineTransform, const bool includeHighOrderNodes)
5125 {
5126 if(!_checkInit()) return;
5127 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
5128 if(!ge) {
5129 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
5130 return;
5131 }
5132 if(ge->getMeshMaster() != ge) {
5133 tagMaster = ge->getMeshMaster()->tag();
5134 for(auto it = ge->correspondingVertices.begin();
5135 it != ge->correspondingVertices.end(); ++it) {
5136 nodeTags.push_back(it->first->getNum());
5137 nodeTagsMaster.push_back(it->second->getNum());
5138 }
5139 if(includeHighOrderNodes) {
5140 for(auto it = ge->correspondingHighOrderVertices.begin();
5141 it != ge->correspondingHighOrderVertices.end(); ++it) {
5142 nodeTags.push_back(it->first->getNum());
5143 nodeTagsMaster.push_back(it->second->getNum());
5144 }
5145 }
5146 affineTransform = ge->affineTransform;
5147 }
5148 else {
5149 tagMaster = tag;
5150 nodeTags.clear();
5151 nodeTagsMaster.clear();
5152 affineTransform.clear();
5153 }
5154 }
5155
getPeriodicKeys(const int elementType,const std::string & functionSpaceType,const int tag,int & tagMaster,std::vector<int> & typeKeys,std::vector<int> & typeKeysMaster,std::vector<std::size_t> & entityKeys,std::vector<std::size_t> & entityKeysMaster,std::vector<double> & coord,std::vector<double> & coordMaster,const bool returnCoord)5156 GMSH_API void gmsh::model::mesh::getPeriodicKeys(
5157 const int elementType, const std::string &functionSpaceType,
5158 const int tag, int &tagMaster,
5159 std::vector<int> &typeKeys, std::vector<int> &typeKeysMaster,
5160 std::vector<std::size_t> &entityKeys, std::vector<std::size_t> &entityKeysMaster,
5161 std::vector<double> &coord, std::vector<double> &coordMaster,
5162 const bool returnCoord)
5163 {
5164 if(!_checkInit()) return;
5165 int dim = ElementType::getDimension(elementType);
5166 GEntity *ge = GModel::current()->getEntityByTag(dim, tag);
5167 if(!ge) {
5168 Msg::Error("%s does not exist", _getEntityName(dim, tag).c_str());
5169 return;
5170 }
5171 if(ge->getMeshMaster() == ge) { // not periodic
5172 tagMaster = tag;
5173 typeKeys.clear();
5174 typeKeysMaster.clear();
5175 entityKeys.clear();
5176 entityKeysMaster.clear();
5177 return;
5178 }
5179
5180 tagMaster = ge->getMeshMaster()->tag();
5181 getKeys(elementType, functionSpaceType,
5182 typeKeys, entityKeys, coord, tag, returnCoord);
5183 typeKeysMaster = typeKeys;
5184 entityKeysMaster = entityKeys;
5185 coordMaster = coord;
5186
5187 if(functionSpaceType == "IsoParametric" ||
5188 functionSpaceType == "Lagrange") {
5189 #pragma omp parallel for
5190 for(std::size_t i = 0; i < entityKeys.size(); i++) {
5191 MVertex v(0., 0., 0., nullptr, entityKeys[i]);
5192 auto mv = ge->correspondingVertices.find(&v);
5193 if(mv != ge->correspondingVertices.end()) {
5194 entityKeysMaster[i] = mv->second->getNum();
5195 if(returnCoord) {
5196 coord[3 * i] = mv->second->x();
5197 coord[3 * i + 1] = mv->second->y();
5198 coord[3 * i + 2] = mv->second->z();
5199 }
5200 }
5201 else {
5202 auto mv2 = ge->correspondingHighOrderVertices.find(&v);
5203 if(mv2 != ge->correspondingHighOrderVertices.end()) {
5204 entityKeysMaster[i] = mv2->second->getNum();
5205 if(returnCoord) {
5206 coord[3 * i] = mv2->second->x();
5207 coord[3 * i + 1] = mv2->second->y();
5208 coord[3 * i + 2] = mv2->second->z();
5209 }
5210 }
5211 else{
5212 Msg::Warning("Unknown master node corresponding to node %d",
5213 entityKeys[i]);
5214 }
5215 }
5216 }
5217 }
5218 else{
5219 Msg::Error("Periodic key generation currently only available for "
5220 "\"IsoParametric\" and \"Lagrange\" function spaces");
5221 }
5222 }
5223
removeDuplicateNodes()5224 GMSH_API void gmsh::model::mesh::removeDuplicateNodes()
5225 {
5226 if(!_checkInit()) return;
5227 GModel::current()->removeDuplicateMeshVertices(
5228 CTX::instance()->geom.tolerance);
5229 CTX::instance()->mesh.changed = ENT_ALL;
5230 }
5231
classifySurfaces(const double angle,const bool boundary,const bool forReparametrization,const double curveAngle,const bool exportDiscrete)5232 GMSH_API void gmsh::model::mesh::classifySurfaces(
5233 const double angle, const bool boundary, const bool forReparametrization,
5234 const double curveAngle, const bool exportDiscrete)
5235 {
5236 if(!_checkInit()) return;
5237 GModel::current()->classifySurfaces(angle, boundary, forReparametrization,
5238 curveAngle);
5239 if(exportDiscrete) {
5240 // Warning: this clears GEO_Internals!
5241 GModel::current()->exportDiscreteGEOInternals();
5242 }
5243 }
5244
createGeometry(const vectorpair & dimTags)5245 GMSH_API void gmsh::model::mesh::createGeometry(const vectorpair &dimTags)
5246 {
5247 if(!_checkInit()) return;
5248 GModel::current()->createGeometryOfDiscreteEntities(dimTags);
5249 }
5250
createTopology(const bool makeSimplyConnected,const bool exportDiscrete)5251 GMSH_API void gmsh::model::mesh::createTopology(const bool makeSimplyConnected,
5252 const bool exportDiscrete)
5253 {
5254 if(!_checkInit()) return;
5255
5256 if(makeSimplyConnected) {
5257 GModel::current()->makeDiscreteRegionsSimplyConnected();
5258 GModel::current()->makeDiscreteFacesSimplyConnected();
5259 }
5260 GModel::current()->createTopologyFromMesh();
5261 if(exportDiscrete) {
5262 // Warning: this clears GEO_Internals!
5263 GModel::current()->exportDiscreteGEOInternals();
5264 }
5265 }
5266
5267 GMSH_API void
computeHomology(const std::vector<int> & domainTags,const std::vector<int> & subdomainTags,const std::vector<int> & dims)5268 gmsh::model::mesh::computeHomology(const std::vector<int> &domainTags,
5269 const std::vector<int> &subdomainTags,
5270 const std::vector<int> &dims)
5271 {
5272 if(!_checkInit()) return;
5273 GModel::current()->addHomologyRequest("Homology", domainTags, subdomainTags,
5274 dims);
5275 }
5276
5277 GMSH_API void
computeCohomology(const std::vector<int> & domainTags,const std::vector<int> & subdomainTags,const std::vector<int> & dims)5278 gmsh::model::mesh::computeCohomology(const std::vector<int> &domainTags,
5279 const std::vector<int> &subdomainTags,
5280 const std::vector<int> &dims)
5281 {
5282 if(!_checkInit()) return;
5283 GModel::current()->addHomologyRequest("Cohomology", domainTags, subdomainTags,
5284 dims);
5285 }
5286
triangulate(const std::vector<double> & coord,std::vector<std::size_t> & tri)5287 GMSH_API void gmsh::model::mesh::triangulate(const std::vector<double> &coord,
5288 std::vector<std::size_t> &tri)
5289 {
5290 if(!_checkInit()) return;
5291 if(coord.size() % 2) {
5292 Msg::Error("Number of 2D coordinates should be even");
5293 return;
5294 }
5295 #if defined(HAVE_MESH)
5296 SBoundingBox3d bbox;
5297 for(std::size_t i = 0; i < coord.size(); i += 2)
5298 bbox += SPoint3(coord[i], coord[i + 1], 0.);
5299 double lc = 10. * norm(SVector3(bbox.max(), bbox.min()));
5300 std::vector<MVertex *> verts(coord.size() / 2);
5301 std::size_t j = 0;
5302 for(std::size_t i = 0; i < coord.size(); i += 2) {
5303 double XX = 1.e-12 * lc * (double)rand() / (double)RAND_MAX;
5304 double YY = 1.e-12 * lc * (double)rand() / (double)RAND_MAX;
5305 MVertex *v = new MVertex(coord[i] + XX, coord[i + 1] + YY, 0.);
5306 v->setIndex(j);
5307 verts[j++] = v;
5308 }
5309 std::vector<MTriangle *> tris;
5310 delaunayMeshIn2D(verts, tris);
5311 tri.resize(3 * tris.size());
5312 for(std::size_t i = 0; i < tris.size(); i++) {
5313 MTriangle *t = tris[i];
5314 for(std::size_t j = 0; j < 3; j++)
5315 tri[3 * i + j] = t->getVertex(j)->getIndex() + 1; // start at 1
5316 }
5317 for(std::size_t i = 0; i < verts.size(); i++) delete verts[i];
5318 for(std::size_t i = 0; i < tris.size(); i++) delete tris[i];
5319 #else
5320 Msg::Error("triangulate requires the mesh module");
5321 #endif
5322 }
5323
5324 GMSH_API void
tetrahedralize(const std::vector<double> & coord,std::vector<std::size_t> & tetra)5325 gmsh::model::mesh::tetrahedralize(const std::vector<double> &coord,
5326 std::vector<std::size_t> &tetra)
5327 {
5328 if(!_checkInit()) return;
5329 if(coord.size() % 3) {
5330 Msg::Error("Number of coordinates should be a multiple of 3");
5331 return;
5332 }
5333 #if defined(HAVE_MESH)
5334 std::vector<MVertex *> verts(coord.size() / 3);
5335 std::size_t j = 0;
5336 for(std::size_t i = 0; i < coord.size(); i += 3) {
5337 MVertex *v = new MVertex(coord[i], coord[i + 1], coord[i + 2]);
5338 v->setIndex(j);
5339 verts[j++] = v;
5340 }
5341 std::vector<MTetrahedron *> tets;
5342 if(CTX::instance()->mesh.algo3d == ALGO_3D_HXT)
5343 delaunayMeshIn3DHxt(verts, tets);
5344 else
5345 delaunayMeshIn3D(verts, tets, true);
5346 tetra.resize(4 * tets.size());
5347 for(std::size_t i = 0; i < tets.size(); i++) {
5348 MTetrahedron *t = tets[i];
5349 for(std::size_t j = 0; j < 4; j++)
5350 tetra[4 * i + j] = t->getVertex(j)->getIndex() + 1; // start at 1
5351 }
5352 for(std::size_t i = 0; i < verts.size(); i++) delete verts[i];
5353 for(std::size_t i = 0; i < tets.size(); i++) delete tets[i];
5354 #else
5355 Msg::Error("tetrahedralize requires the mesh module");
5356 #endif
5357 }
5358
5359 // gmsh::model::mesh::field
5360
add(const std::string & fieldType,const int tag)5361 GMSH_API int gmsh::model::mesh::field::add(const std::string &fieldType,
5362 const int tag)
5363 {
5364 if(!_checkInit()) return -1;
5365 int outTag = tag;
5366 #if defined(HAVE_MESH)
5367 if(outTag < 0) { outTag = GModel::current()->getFields()->newId(); }
5368 if(!GModel::current()->getFields()->newField(outTag, fieldType)) {
5369 Msg::Error("Cannot add Field %i of type '%s'", outTag, fieldType.c_str());
5370 return -1;
5371 }
5372 #if defined(HAVE_FLTK)
5373 if(FlGui::available()) FlGui::instance()->updateFields();
5374 #endif
5375 #else
5376 Msg::Error("Fields require the mesh module");
5377 #endif
5378 return outTag;
5379 }
5380
remove(const int tag)5381 GMSH_API void gmsh::model::mesh::field::remove(const int tag)
5382 {
5383 if(!_checkInit()) return;
5384 #if defined(HAVE_MESH)
5385 GModel::current()->getFields()->deleteField(tag);
5386 #if defined(HAVE_FLTK)
5387 if(FlGui::available()) FlGui::instance()->updateFields();
5388 #endif
5389 #else
5390 Msg::Error("Fields require the mesh module");
5391 #endif
5392 }
5393
list(std::vector<int> & tags)5394 GMSH_API void gmsh::model::mesh::field::list(std::vector<int> &tags)
5395 {
5396 if(!_checkInit()) return;
5397 tags.clear();
5398 #if defined(HAVE_MESH)
5399 FieldManager &fields = *GModel::current()->getFields();
5400 for(auto it = fields.begin(); it != fields.end(); it++) {
5401 tags.push_back(it->first);
5402 }
5403 #else
5404 Msg::Error("Fields require the mesh module");
5405 #endif
5406 }
5407
getType(const int tag,std::string & fieldType)5408 GMSH_API void gmsh::model::mesh::field::getType(const int tag,
5409 std::string &fieldType)
5410 {
5411 if(!_checkInit()) return;
5412 #if defined(HAVE_MESH)
5413 Field *field = GModel::current()->getFields()->get(tag);
5414 if(!field) {
5415 Msg::Error("Unknown field %i", tag);
5416 return;
5417 }
5418 fieldType = field->getName();
5419 #else
5420 Msg::Error("Fields require the mesh module");
5421 #endif
5422 }
5423
5424 #if defined(HAVE_MESH)
_getFieldOption(const int tag,const std::string & option)5425 static FieldOption *_getFieldOption(const int tag, const std::string &option)
5426 {
5427 Field *field = GModel::current()->getFields()->get(tag);
5428 if(!field) {
5429 Msg::Error("Unknown field %i", tag);
5430 return nullptr;
5431 }
5432 FieldOption *o = field->options[option];
5433 if(!o) {
5434 Msg::Error("Unknown option '%s' in field %i of type '%s'", option.c_str(),
5435 tag, field->getName());
5436 return nullptr;
5437 }
5438 return o;
5439 }
5440 #endif
5441
setNumber(const int tag,const std::string & option,const double value)5442 GMSH_API void gmsh::model::mesh::field::setNumber(const int tag,
5443 const std::string &option,
5444 const double value)
5445 {
5446 if(!_checkInit()) return;
5447 #if defined(HAVE_MESH)
5448 FieldOption *o = _getFieldOption(tag, option);
5449 if(!o) return;
5450 o->numericalValue(value);
5451 #else
5452 Msg::Error("Fields require the mesh module");
5453 #endif
5454 }
5455
getNumber(const int tag,const std::string & option,double & value)5456 GMSH_API void gmsh::model::mesh::field::getNumber(const int tag,
5457 const std::string &option,
5458 double &value)
5459 {
5460 if(!_checkInit()) return;
5461 #if defined(HAVE_MESH)
5462 FieldOption *o = _getFieldOption(tag, option);
5463 if(!o) { return; }
5464 value = o->numericalValue();
5465 #else
5466 Msg::Error("Fields require the mesh module");
5467 #endif
5468 }
5469
setString(const int tag,const std::string & option,const std::string & value)5470 GMSH_API void gmsh::model::mesh::field::setString(const int tag,
5471 const std::string &option,
5472 const std::string &value)
5473 {
5474 if(!_checkInit()) return;
5475 #if defined(HAVE_MESH)
5476 FieldOption *o = _getFieldOption(tag, option);
5477 if(!o) return;
5478 o->string(value);
5479 #else
5480 Msg::Error("Fields require the mesh module");
5481 #endif
5482 }
5483
getString(const int tag,const std::string & option,std::string & value)5484 GMSH_API void gmsh::model::mesh::field::getString(const int tag,
5485 const std::string &option,
5486 std::string &value)
5487 {
5488 if(!_checkInit()) return;
5489 #if defined(HAVE_MESH)
5490 FieldOption *o = _getFieldOption(tag, option);
5491 if(!o) { return; }
5492 value = o->string();
5493 #else
5494 Msg::Error("Fields require the mesh module");
5495 #endif
5496 }
5497
5498 GMSH_API void
setNumbers(const int tag,const std::string & option,const std::vector<double> & value)5499 gmsh::model::mesh::field::setNumbers(const int tag, const std::string &option,
5500 const std::vector<double> &value)
5501 {
5502 if(!_checkInit()) return;
5503 #if defined(HAVE_MESH)
5504 FieldOption *o = _getFieldOption(tag, option);
5505 if(!o) return;
5506 if(o->getType() == FIELD_OPTION_LIST) {
5507 std::list<int> vl;
5508 for(std::size_t i = 0; i < value.size(); i++) vl.push_back((int)value[i]);
5509 o->list(vl);
5510 }
5511 else {
5512 std::list<double> vl;
5513 for(std::size_t i = 0; i < value.size(); i++) vl.push_back(value[i]);
5514 o->listdouble(vl);
5515 }
5516 #else
5517 Msg::Error("Fields require the mesh module");
5518 #endif
5519 }
5520
5521 GMSH_API void
getNumbers(const int tag,const std::string & option,std::vector<double> & value)5522 gmsh::model::mesh::field::getNumbers(const int tag, const std::string &option,
5523 std::vector<double> &value)
5524 {
5525 if(!_checkInit()) return;
5526 #if defined(HAVE_MESH)
5527 FieldOption *o = _getFieldOption(tag, option);
5528 if(!o) { return; }
5529 if(o->getType() == FIELD_OPTION_LIST) {
5530 std::list<int> vl = o->list();
5531 for(auto i : vl) value.push_back(i);
5532 }
5533 else {
5534 std::list<double> vl = o->listdouble();
5535 for(auto d : vl) value.push_back(d);
5536 }
5537 #else
5538 Msg::Error("Fields require the mesh module");
5539 #endif
5540 }
5541
setAsBackgroundMesh(const int tag)5542 GMSH_API void gmsh::model::mesh::field::setAsBackgroundMesh(const int tag)
5543 {
5544 if(!_checkInit()) return;
5545 #if defined(HAVE_MESH)
5546 GModel::current()->getFields()->setBackgroundFieldId(tag);
5547 #else
5548 Msg::Error("Fields require the mesh module");
5549 #endif
5550 }
5551
setAsBoundaryLayer(const int tag)5552 GMSH_API void gmsh::model::mesh::field::setAsBoundaryLayer(const int tag)
5553 {
5554 if(!_checkInit()) return;
5555 #if defined(HAVE_MESH)
5556 GModel::current()->getFields()->addBoundaryLayerFieldId(tag);
5557 #else
5558 Msg::Error("Fields require the mesh module");
5559 #endif
5560 }
5561
5562 // gmsh::model::geo
5563
addPoint(const double x,const double y,const double z,const double meshSize,const int tag)5564 GMSH_API int gmsh::model::geo::addPoint(const double x, const double y,
5565 const double z, const double meshSize,
5566 const int tag)
5567 {
5568 if(!_checkInit()) return -1;
5569 int outTag = tag;
5570 double xx = CTX::instance()->geom.scalingFactor * x;
5571 double yy = CTX::instance()->geom.scalingFactor * y;
5572 double zz = CTX::instance()->geom.scalingFactor * z;
5573 double lc = CTX::instance()->geom.scalingFactor * meshSize;
5574 GModel::current()->getGEOInternals()->addVertex(outTag, xx, yy, zz, lc);
5575 return outTag;
5576 }
5577
addLine(const int startTag,const int endTag,const int tag)5578 GMSH_API int gmsh::model::geo::addLine(const int startTag, const int endTag,
5579 const int tag)
5580 {
5581 if(!_checkInit()) return -1;
5582 int outTag = tag;
5583 GModel::current()->getGEOInternals()->addLine(outTag, startTag, endTag);
5584 return outTag;
5585 }
5586
addCircleArc(const int startTag,const int centerTag,const int endTag,const int tag,const double nx,const double ny,const double nz)5587 GMSH_API int gmsh::model::geo::addCircleArc(const int startTag,
5588 const int centerTag,
5589 const int endTag, const int tag,
5590 const double nx, const double ny,
5591 const double nz)
5592 {
5593 if(!_checkInit()) return -1;
5594 int outTag = tag;
5595 GModel::current()->getGEOInternals()->addCircleArc(
5596 outTag, startTag, centerTag, endTag, nx, ny, nz);
5597 return outTag;
5598 }
5599
addEllipseArc(const int startTag,const int centerTag,const int majorTag,const int endTag,const int tag,const double nx,const double ny,const double nz)5600 GMSH_API int gmsh::model::geo::addEllipseArc(
5601 const int startTag, const int centerTag, const int majorTag, const int endTag,
5602 const int tag, const double nx, const double ny, const double nz)
5603 {
5604 if(!_checkInit()) return -1;
5605 int outTag = tag;
5606 GModel::current()->getGEOInternals()->addEllipseArc(
5607 outTag, startTag, centerTag, majorTag, endTag, nx, ny, nz);
5608 return outTag;
5609 }
5610
addSpline(const std::vector<int> & pointTags,const int tag)5611 GMSH_API int gmsh::model::geo::addSpline(const std::vector<int> &pointTags,
5612 const int tag)
5613 {
5614 if(!_checkInit()) return -1;
5615 int outTag = tag;
5616 GModel::current()->getGEOInternals()->addSpline(outTag, pointTags);
5617 return outTag;
5618 }
5619
addBSpline(const std::vector<int> & pointTags,const int tag)5620 GMSH_API int gmsh::model::geo::addBSpline(const std::vector<int> &pointTags,
5621 const int tag)
5622 {
5623 if(!_checkInit()) return -1;
5624 int outTag = tag;
5625 GModel::current()->getGEOInternals()->addBSpline(outTag, pointTags);
5626 return outTag;
5627 }
5628
addBezier(const std::vector<int> & pointTags,const int tag)5629 GMSH_API int gmsh::model::geo::addBezier(const std::vector<int> &pointTags,
5630 const int tag)
5631 {
5632 if(!_checkInit()) return -1;
5633 int outTag = tag;
5634 GModel::current()->getGEOInternals()->addBezier(outTag, pointTags);
5635 return outTag;
5636 }
5637
addPolyline(const std::vector<int> & pointTags,const int tag)5638 GMSH_API int gmsh::model::geo::addPolyline(const std::vector<int> &pointTags,
5639 const int tag)
5640 {
5641 if(!_checkInit()) return -1;
5642 int outTag = tag;
5643 GModel::current()->getGEOInternals()->addLine(outTag, pointTags);
5644 return outTag;
5645 }
5646
5647 GMSH_API int
addCompoundSpline(const std::vector<int> & curveTags,const int numIntervals,const int tag)5648 gmsh::model::geo::addCompoundSpline(const std::vector<int> &curveTags,
5649 const int numIntervals, const int tag)
5650 {
5651 if(!_checkInit()) return -1;
5652 int outTag = tag;
5653 GModel::current()->getGEOInternals()->addCompoundSpline(outTag, curveTags,
5654 numIntervals);
5655 return outTag;
5656 }
5657
5658 GMSH_API int
addCompoundBSpline(const std::vector<int> & curveTags,const int numIntervals,const int tag)5659 gmsh::model::geo::addCompoundBSpline(const std::vector<int> &curveTags,
5660 const int numIntervals, const int tag)
5661 {
5662 if(!_checkInit()) return -1;
5663 int outTag = tag;
5664 GModel::current()->getGEOInternals()->addCompoundBSpline(outTag, curveTags,
5665 numIntervals);
5666 return outTag;
5667 }
5668
addCurveLoop(const std::vector<int> & curveTags,const int tag,const bool reorient)5669 GMSH_API int gmsh::model::geo::addCurveLoop(const std::vector<int> &curveTags,
5670 const int tag, const bool reorient)
5671 {
5672 if(!_checkInit()) return -1;
5673 int outTag = tag;
5674 GModel::current()->getGEOInternals()->addCurveLoop(outTag, curveTags,
5675 reorient);
5676 return outTag;
5677 }
5678
addCurveLoops(const std::vector<int> & curveTags,std::vector<int> & tags)5679 GMSH_API void gmsh::model::geo::addCurveLoops(const std::vector<int> &curveTags,
5680 std::vector<int> &tags)
5681 {
5682 if(!_checkInit()) return;
5683 GModel::current()->getGEOInternals()->addCurveLoops(curveTags, tags);
5684 }
5685
addPlaneSurface(const std::vector<int> & wireTags,const int tag)5686 GMSH_API int gmsh::model::geo::addPlaneSurface(const std::vector<int> &wireTags,
5687 const int tag)
5688 {
5689 if(!_checkInit()) return -1;
5690 int outTag = tag;
5691 GModel::current()->getGEOInternals()->addPlaneSurface(outTag, wireTags);
5692 return outTag;
5693 }
5694
5695 GMSH_API int
addSurfaceFilling(const std::vector<int> & wireTags,const int tag,const int sphereCenterTag)5696 gmsh::model::geo::addSurfaceFilling(const std::vector<int> &wireTags,
5697 const int tag, const int sphereCenterTag)
5698 {
5699 if(!_checkInit()) return -1;
5700 int outTag = tag;
5701 GModel::current()->getGEOInternals()->addSurfaceFilling(outTag, wireTags,
5702 sphereCenterTag);
5703 return outTag;
5704 }
5705
5706 GMSH_API int
addSurfaceLoop(const std::vector<int> & surfaceTags,const int tag)5707 gmsh::model::geo::addSurfaceLoop(const std::vector<int> &surfaceTags,
5708 const int tag)
5709 {
5710 if(!_checkInit()) return -1;
5711 int outTag = tag;
5712 GModel::current()->getGEOInternals()->addSurfaceLoop(outTag, surfaceTags);
5713 return outTag;
5714 }
5715
addVolume(const std::vector<int> & shellTags,const int tag)5716 GMSH_API int gmsh::model::geo::addVolume(const std::vector<int> &shellTags,
5717 const int tag)
5718 {
5719 if(!_checkInit()) return -1;
5720 int outTag = tag;
5721 GModel::current()->getGEOInternals()->addVolume(outTag, shellTags);
5722 return outTag;
5723 }
5724
_getExtrudeParams(const std::vector<int> & numElements,const std::vector<double> & heights,const bool recombine)5725 static ExtrudeParams *_getExtrudeParams(const std::vector<int> &numElements,
5726 const std::vector<double> &heights,
5727 const bool recombine)
5728 {
5729 ExtrudeParams *e = nullptr;
5730 if(numElements.size()) {
5731 e = new ExtrudeParams();
5732 e->mesh.ExtrudeMesh = true;
5733 e->mesh.NbElmLayer = numElements;
5734 e->mesh.hLayer = heights;
5735 if(e->mesh.hLayer.empty()) {
5736 e->mesh.NbLayer = numElements.size();
5737 for(int i = 0; i < e->mesh.NbLayer; i++) {
5738 e->mesh.hLayer.push_back((i + 1.) / e->mesh.NbLayer);
5739 }
5740 }
5741 else {
5742 e->mesh.NbLayer = heights.size();
5743 }
5744 e->mesh.Recombine = recombine;
5745 }
5746 return e;
5747 }
5748
extrude(const vectorpair & dimTags,const double dx,const double dy,const double dz,vectorpair & outDimTags,const std::vector<int> & numElements,const std::vector<double> & heights,const bool recombine)5749 GMSH_API void gmsh::model::geo::extrude(const vectorpair &dimTags,
5750 const double dx, const double dy,
5751 const double dz, vectorpair &outDimTags,
5752 const std::vector<int> &numElements,
5753 const std::vector<double> &heights,
5754 const bool recombine)
5755 {
5756 if(!_checkInit()) return;
5757 outDimTags.clear();
5758 ExtrudeParams *e = _getExtrudeParams(numElements, heights, recombine);
5759 GModel::current()->getGEOInternals()->extrude(
5760 dimTags, dx, dy, dz, outDimTags, e);
5761 if(e) delete e;
5762 }
5763
revolve(const vectorpair & dimTags,const double x,const double y,const double z,const double ax,const double ay,const double az,const double angle,vectorpair & outDimTags,const std::vector<int> & numElements,const std::vector<double> & heights,const bool recombine)5764 GMSH_API void gmsh::model::geo::revolve(
5765 const vectorpair &dimTags, const double x, const double y, const double z,
5766 const double ax, const double ay, const double az, const double angle,
5767 vectorpair &outDimTags, const std::vector<int> &numElements,
5768 const std::vector<double> &heights, const bool recombine)
5769 {
5770 if(!_checkInit()) return;
5771 outDimTags.clear();
5772 ExtrudeParams *e = _getExtrudeParams(numElements, heights, recombine);
5773 GModel::current()->getGEOInternals()->revolve(
5774 dimTags, x, y, z, ax, ay, az, angle, outDimTags, e);
5775 if(e) delete e;
5776 }
5777
twist(const vectorpair & dimTags,const double x,const double y,const double z,const double dx,const double dy,const double dz,const double ax,const double ay,const double az,const double angle,vectorpair & outDimTags,const std::vector<int> & numElements,const std::vector<double> & heights,const bool recombine)5778 GMSH_API void gmsh::model::geo::twist(
5779 const vectorpair &dimTags, const double x, const double y, const double z,
5780 const double dx, const double dy, const double dz, const double ax,
5781 const double ay, const double az, const double angle, vectorpair &outDimTags,
5782 const std::vector<int> &numElements, const std::vector<double> &heights,
5783 const bool recombine)
5784 {
5785 _checkInit();
5786 outDimTags.clear();
5787 ExtrudeParams *e = _getExtrudeParams(numElements, heights, recombine);
5788 GModel::current()->getGEOInternals()->twist(
5789 dimTags, x, y, z, dx, dy, dz, ax, ay, az, angle, outDimTags, e);
5790 if(e) delete e;
5791 }
5792
extrudeBoundaryLayer(const vectorpair & dimTags,vectorpair & outDimTags,const std::vector<int> & numElements,const std::vector<double> & heights,const bool recombine,const bool second,const int viewIndex)5793 GMSH_API void gmsh::model::geo::extrudeBoundaryLayer(
5794 const vectorpair &dimTags, vectorpair &outDimTags,
5795 const std::vector<int> &numElements, const std::vector<double> &heights,
5796 const bool recombine, const bool second, const int viewIndex)
5797 {
5798 if(!_checkInit()) return;
5799 outDimTags.clear();
5800 ExtrudeParams *e = _getExtrudeParams(numElements, heights, recombine);
5801 if(!e) {
5802 Msg::Error("Element layers are required for boundary layer extrusion");
5803 return;
5804 }
5805 e->mesh.BoundaryLayerIndex = second ? 1 : 0;
5806 e->mesh.ViewIndex = viewIndex;
5807 GModel::current()->getGEOInternals()->boundaryLayer(dimTags, outDimTags, e);
5808 delete e;
5809 }
5810
translate(const vectorpair & dimTags,const double dx,const double dy,const double dz)5811 GMSH_API void gmsh::model::geo::translate(const vectorpair &dimTags,
5812 const double dx, const double dy,
5813 const double dz)
5814 {
5815 if(!_checkInit()) return;
5816 GModel::current()->getGEOInternals()->translate(dimTags, dx, dy, dz);
5817 }
5818
rotate(const vectorpair & dimTags,const double x,const double y,const double z,const double ax,const double ay,const double az,const double angle)5819 GMSH_API void gmsh::model::geo::rotate(const vectorpair &dimTags,
5820 const double x, const double y,
5821 const double z, const double ax,
5822 const double ay, const double az,
5823 const double angle)
5824 {
5825 if(!_checkInit()) return;
5826 GModel::current()->getGEOInternals()->rotate(dimTags, x, y, z, ax, ay, az,
5827 angle);
5828 }
5829
dilate(const vectorpair & dimTags,const double x,const double y,const double z,const double a,const double b,const double c)5830 GMSH_API void gmsh::model::geo::dilate(const vectorpair &dimTags,
5831 const double x, const double y,
5832 const double z, const double a,
5833 const double b, const double c)
5834 {
5835 if(!_checkInit()) return;
5836 GModel::current()->getGEOInternals()->dilate(dimTags, x, y, z, a, b, c);
5837 }
5838
mirror(const vectorpair & dimTags,const double a,const double b,const double c,const double d)5839 GMSH_API void gmsh::model::geo::mirror(const vectorpair &dimTags,
5840 const double a, const double b,
5841 const double c, const double d)
5842 {
5843 if(!_checkInit()) return;
5844 GModel::current()->getGEOInternals()->symmetry(dimTags, a, b, c, d);
5845 }
5846
5847 // will be deprecated
symmetrize(const vectorpair & dimTags,const double a,const double b,const double c,const double d)5848 GMSH_API void gmsh::model::geo::symmetrize(const vectorpair &dimTags,
5849 const double a, const double b,
5850 const double c, const double d)
5851 {
5852 gmsh::model::geo::mirror(dimTags, a, b, c, d);
5853 }
5854
copy(const vectorpair & dimTags,vectorpair & outDimTags)5855 GMSH_API void gmsh::model::geo::copy(const vectorpair &dimTags,
5856 vectorpair &outDimTags)
5857 {
5858 if(!_checkInit()) return;
5859 outDimTags.clear();
5860 GModel::current()->getGEOInternals()->copy(dimTags, outDimTags);
5861 }
5862
remove(const vectorpair & dimTags,const bool recursive)5863 GMSH_API void gmsh::model::geo::remove(const vectorpair &dimTags,
5864 const bool recursive)
5865 {
5866 if(!_checkInit()) return;
5867 GModel::current()->getGEOInternals()->remove(dimTags, recursive);
5868 }
5869
removeAllDuplicates()5870 GMSH_API void gmsh::model::geo::removeAllDuplicates()
5871 {
5872 if(!_checkInit()) return;
5873 GModel::current()->getGEOInternals()->removeAllDuplicates();
5874 }
5875
splitCurve(const int tag,const std::vector<int> & pointTags,std::vector<int> & curveTags)5876 GMSH_API void gmsh::model::geo::splitCurve(const int tag,
5877 const std::vector<int> &pointTags,
5878 std::vector<int> &curveTags)
5879 {
5880 if(!_checkInit()) return;
5881 GModel::current()->getGEOInternals()->splitCurve(tag, pointTags, curveTags);
5882 }
5883
getMaxTag(const int dim)5884 GMSH_API int gmsh::model::geo::getMaxTag(const int dim)
5885 {
5886 if(!_checkInit()) return -1;
5887 return GModel::current()->getGEOInternals()->getMaxTag(dim);
5888 }
5889
setMaxTag(const int dim,const int maxTag)5890 GMSH_API void gmsh::model::geo::setMaxTag(const int dim, const int maxTag)
5891 {
5892 if(!_checkInit()) return;
5893 GModel::current()->getGEOInternals()->setMaxTag(dim, maxTag);
5894 }
5895
addPhysicalGroup(const int dim,const std::vector<int> & tags,const int tag)5896 GMSH_API int gmsh::model::geo::addPhysicalGroup(const int dim,
5897 const std::vector<int> &tags,
5898 const int tag)
5899 {
5900 if(!_checkInit()) return -1;
5901 int outTag = tag;
5902 if(outTag < 0)
5903 outTag = GModel::current()->getGEOInternals()->getMaxPhysicalTag() + 1;
5904 GModel::current()->getGEOInternals()->modifyPhysicalGroup(dim, outTag, 0,
5905 tags);
5906 return outTag;
5907 }
5908
removePhysicalGroups(const vectorpair & dimTags)5909 GMSH_API void gmsh::model::geo::removePhysicalGroups(const vectorpair &dimTags)
5910 {
5911 if(!_checkInit()) return;
5912 if(dimTags.empty()) {
5913 GModel::current()->getGEOInternals()->resetPhysicalGroups();
5914 }
5915 else {
5916 for(std::size_t i = 0; i < dimTags.size(); i++) {
5917 std::vector<int> tags; // empty to delete the group
5918 GModel::current()->getGEOInternals()->modifyPhysicalGroup(
5919 dimTags[i].first, dimTags[i].second, 2, tags);
5920 }
5921 }
5922 }
5923
synchronize()5924 GMSH_API void gmsh::model::geo::synchronize()
5925 {
5926 if(!_checkInit()) return;
5927 GModel::current()->getGEOInternals()->synchronize(GModel::current());
5928 }
5929
5930 // gmsh::model::geo::mesh
5931
5932 GMSH_API void
setTransfiniteCurve(const int tag,const int nPoints,const std::string & meshType,const double coef)5933 gmsh::model::geo::mesh::setTransfiniteCurve(const int tag, const int nPoints,
5934 const std::string &meshType,
5935 const double coef)
5936 {
5937 if(!_checkInit()) return;
5938 int type = (meshType == "Progression" || meshType == "Power") ? 1 :
5939 (meshType == "Bump") ? 2 :
5940 (meshType == "Beta") ? 3 :
5941 1;
5942 double c = std::abs(coef);
5943 // in .geo file we use a negative tag to do this trick; it's a bad idea
5944 if(coef < 0) type = -type;
5945
5946 // for compatibility with geo files, try both tag and -tag
5947 for(int sig = -1; sig <= 1; sig += 2)
5948 GModel::current()->getGEOInternals()->setTransfiniteLine(sig * tag, nPoints,
5949 type, c);
5950 }
5951
setTransfiniteSurface(const int tag,const std::string & arrangement,const std::vector<int> & cornerTags)5952 GMSH_API void gmsh::model::geo::mesh::setTransfiniteSurface(
5953 const int tag, const std::string &arrangement,
5954 const std::vector<int> &cornerTags)
5955 {
5956 if(!_checkInit()) return;
5957 int t = (arrangement == "Right") ? 1 :
5958 (arrangement == "Left") ? -1 :
5959 (arrangement == "AlternateRight") ? 2 :
5960 (arrangement == "AlternateLeft") ? -2 :
5961 (arrangement == "Alternate") ? 2 :
5962 -1;
5963 GModel::current()->getGEOInternals()->setTransfiniteSurface(tag, t,
5964 cornerTags);
5965 }
5966
5967 GMSH_API void
setTransfiniteVolume(const int tag,const std::vector<int> & cornerTags)5968 gmsh::model::geo::mesh::setTransfiniteVolume(const int tag,
5969 const std::vector<int> &cornerTags)
5970 {
5971 if(!_checkInit()) return;
5972 GModel::current()->getGEOInternals()->setTransfiniteVolume(tag, cornerTags);
5973 }
5974
setRecombine(const int dim,const int tag,const double angle)5975 GMSH_API void gmsh::model::geo::mesh::setRecombine(const int dim, const int tag,
5976 const double angle)
5977 {
5978 if(!_checkInit()) return;
5979 GModel::current()->getGEOInternals()->setRecombine(dim, tag, angle);
5980 }
5981
setSmoothing(const int dim,const int tag,const int val)5982 GMSH_API void gmsh::model::geo::mesh::setSmoothing(const int dim, const int tag,
5983 const int val)
5984 {
5985 if(!_checkInit()) return;
5986 if(dim == 2) { GModel::current()->getGEOInternals()->setSmoothing(tag, val); }
5987 }
5988
setReverse(const int dim,const int tag,const bool val)5989 GMSH_API void gmsh::model::geo::mesh::setReverse(const int dim, const int tag,
5990 const bool val)
5991 {
5992 if(!_checkInit()) return;
5993 GModel::current()->getGEOInternals()->setReverseMesh(dim, tag, val);
5994 }
5995
setAlgorithm(const int dim,const int tag,const int val)5996 GMSH_API void gmsh::model::geo::mesh::setAlgorithm(const int dim, const int tag,
5997 const int val)
5998 {
5999 if(!_checkInit()) return;
6000 GModel::current()->getGEOInternals()->setMeshAlgorithm(dim, tag, val);
6001 }
6002
setSizeFromBoundary(const int dim,const int tag,const int val)6003 GMSH_API void gmsh::model::geo::mesh::setSizeFromBoundary(const int dim,
6004 const int tag,
6005 const int val)
6006 {
6007 if(!_checkInit()) return;
6008 GModel::current()->getGEOInternals()->setMeshSizeFromBoundary(dim, tag, val);
6009 }
6010
setSize(const vectorpair & dimTags,const double size)6011 GMSH_API void gmsh::model::geo::mesh::setSize(const vectorpair &dimTags,
6012 const double size)
6013 {
6014 if(!_checkInit()) return;
6015 for(std::size_t i = 0; i < dimTags.size(); i++) {
6016 int dim = dimTags[i].first, tag = dimTags[i].second;
6017 GModel::current()->getGEOInternals()->setMeshSize(dim, tag, size);
6018 }
6019 }
6020
6021 // gmsh::model::occ
6022
_createOcc()6023 static void _createOcc()
6024 {
6025 if(!GModel::current()->getOCCInternals())
6026 GModel::current()->createOCCInternals();
6027 }
6028
addPoint(const double x,const double y,const double z,const double meshSize,const int tag)6029 GMSH_API int gmsh::model::occ::addPoint(const double x, const double y,
6030 const double z, const double meshSize,
6031 const int tag)
6032 {
6033 if(!_checkInit()) return -1;
6034 _createOcc();
6035 int outTag = tag;
6036 GModel::current()->getOCCInternals()->addVertex(outTag, x, y, z, meshSize);
6037 return outTag;
6038 }
6039
addLine(const int startTag,const int endTag,const int tag)6040 GMSH_API int gmsh::model::occ::addLine(const int startTag, const int endTag,
6041 const int tag)
6042 {
6043 if(!_checkInit()) return -1;
6044 _createOcc();
6045 int outTag = tag;
6046 GModel::current()->getOCCInternals()->addLine(outTag, startTag, endTag);
6047 return outTag;
6048 }
6049
addCircleArc(const int startTag,const int centerTag,const int endTag,const int tag)6050 GMSH_API int gmsh::model::occ::addCircleArc(const int startTag,
6051 const int centerTag,
6052 const int endTag, const int tag)
6053 {
6054 if(!_checkInit()) return -1;
6055 _createOcc();
6056 int outTag = tag;
6057 GModel::current()->getOCCInternals()->addCircleArc(outTag, startTag,
6058 centerTag, endTag);
6059 return outTag;
6060 }
6061
addCircle(const double x,const double y,const double z,const double r,const int tag,const double angle1,const double angle2)6062 GMSH_API int gmsh::model::occ::addCircle(const double x, const double y,
6063 const double z, const double r,
6064 const int tag, const double angle1,
6065 const double angle2)
6066 {
6067 if(!_checkInit()) return -1;
6068 _createOcc();
6069 int outTag = tag;
6070 GModel::current()->getOCCInternals()->addCircle(outTag, x, y, z, r, angle1,
6071 angle2);
6072 return outTag;
6073 }
6074
addEllipseArc(const int startTag,const int centerTag,const int majorTag,const int endTag,const int tag)6075 GMSH_API int gmsh::model::occ::addEllipseArc(const int startTag,
6076 const int centerTag,
6077 const int majorTag,
6078 const int endTag, const int tag)
6079 {
6080 if(!_checkInit()) return -1;
6081 _createOcc();
6082 int outTag = tag;
6083 GModel::current()->getOCCInternals()->addEllipseArc(
6084 outTag, startTag, centerTag, majorTag, endTag);
6085 return outTag;
6086 }
6087
addEllipse(const double x,const double y,const double z,const double r1,const double r2,const int tag,const double angle1,const double angle2)6088 GMSH_API int gmsh::model::occ::addEllipse(const double x, const double y,
6089 const double z, const double r1,
6090 const double r2, const int tag,
6091 const double angle1,
6092 const double angle2)
6093 {
6094 if(!_checkInit()) return -1;
6095 _createOcc();
6096 int outTag = tag;
6097 GModel::current()->getOCCInternals()->addEllipse(outTag, x, y, z, r1, r2,
6098 angle1, angle2);
6099 return outTag;
6100 }
6101
addSpline(const std::vector<int> & pointTags,const int tag)6102 GMSH_API int gmsh::model::occ::addSpline(const std::vector<int> &pointTags,
6103 const int tag)
6104 {
6105 if(!_checkInit()) return -1;
6106 _createOcc();
6107 int outTag = tag;
6108 GModel::current()->getOCCInternals()->addSpline(outTag, pointTags);
6109 return outTag;
6110 }
6111
addBSpline(const std::vector<int> & pointTags,const int tag,const int degree,const std::vector<double> & weights,const std::vector<double> & knots,const std::vector<int> & multiplicities)6112 GMSH_API int gmsh::model::occ::addBSpline(
6113 const std::vector<int> &pointTags, const int tag, const int degree,
6114 const std::vector<double> &weights, const std::vector<double> &knots,
6115 const std::vector<int> &multiplicities)
6116 {
6117 if(!_checkInit()) return -1;
6118 _createOcc();
6119 int outTag = tag;
6120 GModel::current()->getOCCInternals()->addBSpline(
6121 outTag, pointTags, degree, weights, knots, multiplicities);
6122 return outTag;
6123 }
6124
addBezier(const std::vector<int> & pointTags,const int tag)6125 GMSH_API int gmsh::model::occ::addBezier(const std::vector<int> &pointTags,
6126 const int tag)
6127 {
6128 if(!_checkInit()) return -1;
6129 _createOcc();
6130 int outTag = tag;
6131 GModel::current()->getOCCInternals()->addBezier(outTag, pointTags);
6132 return outTag;
6133 }
6134
addWire(const std::vector<int> & curveTags,const int tag,const bool checkClosed)6135 GMSH_API int gmsh::model::occ::addWire(const std::vector<int> &curveTags,
6136 const int tag, const bool checkClosed)
6137 {
6138 if(!_checkInit()) return -1;
6139 _createOcc();
6140 int outTag = tag;
6141 GModel::current()->getOCCInternals()->addWire(outTag, curveTags, checkClosed);
6142 return outTag;
6143 }
6144
addCurveLoop(const std::vector<int> & curveTags,const int tag)6145 GMSH_API int gmsh::model::occ::addCurveLoop(const std::vector<int> &curveTags,
6146 const int tag)
6147 {
6148 if(!_checkInit()) return -1;
6149 _createOcc();
6150 int outTag = tag;
6151 GModel::current()->getOCCInternals()->addCurveLoop(outTag, curveTags);
6152 return outTag;
6153 }
6154
addRectangle(const double x,const double y,const double z,const double dx,const double dy,const int tag,const double roundedRadius)6155 GMSH_API int gmsh::model::occ::addRectangle(const double x, const double y,
6156 const double z, const double dx,
6157 const double dy, const int tag,
6158 const double roundedRadius)
6159 {
6160 if(!_checkInit()) return -1;
6161 _createOcc();
6162 int outTag = tag;
6163 GModel::current()->getOCCInternals()->addRectangle(outTag, x, y, z, dx, dy,
6164 roundedRadius);
6165 return outTag;
6166 }
6167
addDisk(const double xc,const double yc,const double zc,const double rx,const double ry,const int tag)6168 GMSH_API int gmsh::model::occ::addDisk(const double xc, const double yc,
6169 const double zc, const double rx,
6170 const double ry, const int tag)
6171 {
6172 if(!_checkInit()) return -1;
6173 _createOcc();
6174 int outTag = tag;
6175 GModel::current()->getOCCInternals()->addDisk(outTag, xc, yc, zc, rx, ry);
6176 return outTag;
6177 }
6178
addPlaneSurface(const std::vector<int> & wireTags,const int tag)6179 GMSH_API int gmsh::model::occ::addPlaneSurface(const std::vector<int> &wireTags,
6180 const int tag)
6181 {
6182 if(!_checkInit()) return -1;
6183 _createOcc();
6184 int outTag = tag;
6185 GModel::current()->getOCCInternals()->addPlaneSurface(outTag, wireTags);
6186 return outTag;
6187 }
6188
addSurfaceFilling(const int wireTag,const int tag,const std::vector<int> & pointTags,const int degree,const int numPointsOnCurves,const int numIter,const bool anisotropic,const double tol2d,const double tol3d,const double tolAng,const double tolCurv,const int maxDegree,const int maxSegments)6189 GMSH_API int gmsh::model::occ::addSurfaceFilling(
6190 const int wireTag, const int tag, const std::vector<int> &pointTags,
6191 const int degree, const int numPointsOnCurves, const int numIter,
6192 const bool anisotropic, const double tol2d, const double tol3d,
6193 const double tolAng, const double tolCurv, const int maxDegree,
6194 const int maxSegments)
6195 {
6196 if(!_checkInit()) return -1;
6197 _createOcc();
6198 int outTag = tag;
6199 std::vector<int> surf, surfCont;
6200 GModel::current()->getOCCInternals()->addSurfaceFilling(
6201 outTag, wireTag, pointTags, surf, surfCont, degree, numPointsOnCurves,
6202 numIter, anisotropic, tol2d, tol3d, tolAng, tolCurv, maxDegree,
6203 maxSegments);
6204 return outTag;
6205 }
6206
addBSplineFilling(const int wireTag,const int tag,const std::string & type)6207 GMSH_API int gmsh::model::occ::addBSplineFilling(const int wireTag,
6208 const int tag,
6209 const std::string &type)
6210 {
6211 if(!_checkInit()) return -1;
6212 _createOcc();
6213 int outTag = tag;
6214 GModel::current()->getOCCInternals()->addBSplineFilling(outTag, wireTag,
6215 type);
6216 return outTag;
6217 }
6218
addBezierFilling(const int wireTag,const int tag,const std::string & type)6219 GMSH_API int gmsh::model::occ::addBezierFilling(const int wireTag,
6220 const int tag,
6221 const std::string &type)
6222 {
6223 if(!_checkInit()) return -1;
6224 _createOcc();
6225 int outTag = tag;
6226 GModel::current()->getOCCInternals()->addBezierFilling(outTag, wireTag, type);
6227 return outTag;
6228 }
6229
addBSplineSurface(const std::vector<int> & pointTags,const int numPointsU,const int tag,const int degreeU,const int degreeV,const std::vector<double> & weights,const std::vector<double> & knotsU,const std::vector<double> & knotsV,const std::vector<int> & multiplicitiesU,const std::vector<int> & multiplicitiesV,const std::vector<int> & wireTags,const bool wire3D)6230 GMSH_API int gmsh::model::occ::addBSplineSurface(
6231 const std::vector<int> &pointTags, const int numPointsU, const int tag,
6232 const int degreeU, const int degreeV, const std::vector<double> &weights,
6233 const std::vector<double> &knotsU, const std::vector<double> &knotsV,
6234 const std::vector<int> &multiplicitiesU,
6235 const std::vector<int> &multiplicitiesV, const std::vector<int> &wireTags,
6236 const bool wire3D)
6237 {
6238 if(!_checkInit()) return -1;
6239 _createOcc();
6240 int outTag = tag;
6241 GModel::current()->getOCCInternals()->addBSplineSurface(
6242 outTag, pointTags, numPointsU, degreeU, degreeV, weights, knotsU, knotsV,
6243 multiplicitiesU, multiplicitiesV, wireTags, wire3D);
6244 return outTag;
6245 }
6246
addBezierSurface(const std::vector<int> & pointTags,const int numPointsU,const int tag,const std::vector<int> & wireTags,const bool wire3D)6247 GMSH_API int gmsh::model::occ::addBezierSurface(
6248 const std::vector<int> &pointTags, const int numPointsU, const int tag,
6249 const std::vector<int> &wireTags, const bool wire3D)
6250 {
6251 if(!_checkInit()) return -1;
6252 _createOcc();
6253 int outTag = tag;
6254 GModel::current()->getOCCInternals()->addBezierSurface(
6255 outTag, pointTags, numPointsU, wireTags, wire3D);
6256 return outTag;
6257 }
6258
6259 GMSH_API int
addTrimmedSurface(const int surfaceTag,const std::vector<int> & wireTags,const bool wire3D,const int tag)6260 gmsh::model::occ::addTrimmedSurface(const int surfaceTag,
6261 const std::vector<int> &wireTags,
6262 const bool wire3D, const int tag)
6263 {
6264 if(!_checkInit()) return -1;
6265 _createOcc();
6266 int outTag = tag;
6267 GModel::current()->getOCCInternals()->addTrimmedSurface(outTag, surfaceTag,
6268 wireTags, wire3D);
6269 return outTag;
6270 }
6271
6272 GMSH_API int
addSurfaceLoop(const std::vector<int> & surfaceTags,const int tag,const bool sewing)6273 gmsh::model::occ::addSurfaceLoop(const std::vector<int> &surfaceTags,
6274 const int tag, const bool sewing)
6275 {
6276 if(!_checkInit()) return -1;
6277 _createOcc();
6278 int outTag = tag;
6279 GModel::current()->getOCCInternals()->addSurfaceLoop(outTag, surfaceTags,
6280 sewing);
6281 return outTag;
6282 }
6283
addVolume(const std::vector<int> & shellTags,const int tag)6284 GMSH_API int gmsh::model::occ::addVolume(const std::vector<int> &shellTags,
6285 const int tag)
6286 {
6287 if(!_checkInit()) return -1;
6288 _createOcc();
6289 int outTag = tag;
6290 GModel::current()->getOCCInternals()->addVolume(outTag, shellTags);
6291 return outTag;
6292 }
6293
addSphere(const double xc,const double yc,const double zc,const double radius,const int tag,const double angle1,const double angle2,const double angle3)6294 GMSH_API int gmsh::model::occ::addSphere(const double xc, const double yc,
6295 const double zc, const double radius,
6296 const int tag, const double angle1,
6297 const double angle2,
6298 const double angle3)
6299 {
6300 if(!_checkInit()) return -1;
6301 _createOcc();
6302 int outTag = tag;
6303 GModel::current()->getOCCInternals()->addSphere(outTag, xc, yc, zc, radius,
6304 angle1, angle2, angle3);
6305 return outTag;
6306 }
6307
addBox(const double x,const double y,const double z,const double dx,const double dy,const double dz,const int tag)6308 GMSH_API int gmsh::model::occ::addBox(const double x, const double y,
6309 const double z, const double dx,
6310 const double dy, const double dz,
6311 const int tag)
6312 {
6313 if(!_checkInit()) return -1;
6314 _createOcc();
6315 int outTag = tag;
6316 GModel::current()->getOCCInternals()->addBox(outTag, x, y, z, dx, dy, dz);
6317 return outTag;
6318 }
6319
addCylinder(const double x,const double y,const double z,const double dx,const double dy,const double dz,const double r,const int tag,const double angle)6320 GMSH_API int gmsh::model::occ::addCylinder(const double x, const double y,
6321 const double z, const double dx,
6322 const double dy, const double dz,
6323 const double r, const int tag,
6324 const double angle)
6325 {
6326 if(!_checkInit()) return -1;
6327 _createOcc();
6328 int outTag = tag;
6329 GModel::current()->getOCCInternals()->addCylinder(outTag, x, y, z, dx, dy, dz,
6330 r, angle);
6331 return outTag;
6332 }
6333
addCone(const double x,const double y,const double z,const double dx,const double dy,const double dz,const double r1,const double r2,const int tag,const double angle)6334 GMSH_API int gmsh::model::occ::addCone(const double x, const double y,
6335 const double z, const double dx,
6336 const double dy, const double dz,
6337 const double r1, const double r2,
6338 const int tag, const double angle)
6339 {
6340 if(!_checkInit()) return -1;
6341 _createOcc();
6342 int outTag = tag;
6343 GModel::current()->getOCCInternals()->addCone(outTag, x, y, z, dx, dy, dz, r1,
6344 r2, angle);
6345 return outTag;
6346 }
6347
addWedge(const double x,const double y,const double z,const double dx,const double dy,const double dz,const int tag,const double ltx)6348 GMSH_API int gmsh::model::occ::addWedge(const double x, const double y,
6349 const double z, const double dx,
6350 const double dy, const double dz,
6351 const int tag, const double ltx)
6352 {
6353 if(!_checkInit()) return -1;
6354 _createOcc();
6355 int outTag = tag;
6356 GModel::current()->getOCCInternals()->addWedge(outTag, x, y, z, dx, dy, dz,
6357 ltx);
6358 return outTag;
6359 }
6360
addTorus(const double x,const double y,const double z,const double r1,const double r2,const int tag,const double angle)6361 GMSH_API int gmsh::model::occ::addTorus(const double x, const double y,
6362 const double z, const double r1,
6363 const double r2, const int tag,
6364 const double angle)
6365 {
6366 if(!_checkInit()) return -1;
6367 _createOcc();
6368 int outTag = tag;
6369 GModel::current()->getOCCInternals()->addTorus(outTag, x, y, z, r1, r2,
6370 angle);
6371 return outTag;
6372 }
6373
addThruSections(const std::vector<int> & wireTags,vectorpair & outDimTags,const int tag,const bool makeSolid,const bool makeRuled,const int maxDegree)6374 GMSH_API void gmsh::model::occ::addThruSections(
6375 const std::vector<int> &wireTags, vectorpair &outDimTags, const int tag,
6376 const bool makeSolid, const bool makeRuled, const int maxDegree)
6377 {
6378 if(!_checkInit()) return;
6379 _createOcc();
6380 outDimTags.clear();
6381 GModel::current()->getOCCInternals()->addThruSections(
6382 tag, wireTags, makeSolid, makeRuled, outDimTags, maxDegree);
6383 }
6384
addThickSolid(const int volumeTag,const std::vector<int> & excludeSurfaceTags,const double offset,vectorpair & outDimTags,const int tag)6385 GMSH_API void gmsh::model::occ::addThickSolid(
6386 const int volumeTag, const std::vector<int> &excludeSurfaceTags,
6387 const double offset, vectorpair &outDimTags, const int tag)
6388 {
6389 if(!_checkInit()) return;
6390 _createOcc();
6391 outDimTags.clear();
6392 GModel::current()->getOCCInternals()->addThickSolid(
6393 tag, volumeTag, excludeSurfaceTags, offset, outDimTags);
6394 }
6395
extrude(const vectorpair & dimTags,const double dx,const double dy,const double dz,vectorpair & outDimTags,const std::vector<int> & numElements,const std::vector<double> & heights,const bool recombine)6396 GMSH_API void gmsh::model::occ::extrude(const vectorpair &dimTags,
6397 const double dx, const double dy,
6398 const double dz, vectorpair &outDimTags,
6399 const std::vector<int> &numElements,
6400 const std::vector<double> &heights,
6401 const bool recombine)
6402 {
6403 if(!_checkInit()) return;
6404 _createOcc();
6405 outDimTags.clear();
6406 ExtrudeParams *e = _getExtrudeParams(numElements, heights, recombine);
6407 GModel::current()->getOCCInternals()->extrude(
6408 dimTags, dx, dy, dz, outDimTags, e);
6409 if(e) delete e;
6410 }
6411
revolve(const vectorpair & dimTags,const double x,const double y,const double z,const double ax,const double ay,const double az,const double angle,vectorpair & outDimTags,const std::vector<int> & numElements,const std::vector<double> & heights,const bool recombine)6412 GMSH_API void gmsh::model::occ::revolve(
6413 const vectorpair &dimTags, const double x, const double y, const double z,
6414 const double ax, const double ay, const double az, const double angle,
6415 vectorpair &outDimTags, const std::vector<int> &numElements,
6416 const std::vector<double> &heights, const bool recombine)
6417 {
6418 if(!_checkInit()) return;
6419 _createOcc();
6420 outDimTags.clear();
6421 ExtrudeParams *e = _getExtrudeParams(numElements, heights, recombine);
6422 GModel::current()->getOCCInternals()->revolve(
6423 dimTags, x, y, z, ax, ay, az, angle, outDimTags, e);
6424 if(e) delete e;
6425 }
6426
addPipe(const vectorpair & dimTags,const int wireTag,vectorpair & outDimTags,const std::string & trihedron)6427 GMSH_API void gmsh::model::occ::addPipe(const vectorpair &dimTags,
6428 const int wireTag,
6429 vectorpair &outDimTags,
6430 const std::string &trihedron)
6431 {
6432 if(!_checkInit()) return;
6433 _createOcc();
6434 outDimTags.clear();
6435 GModel::current()->getOCCInternals()->addPipe(dimTags, wireTag, outDimTags,
6436 trihedron);
6437 }
6438
fillet(const std::vector<int> & volumeTags,const std::vector<int> & curveTags,const std::vector<double> & radii,vectorpair & outDimTags,const bool removeVolume)6439 GMSH_API void gmsh::model::occ::fillet(const std::vector<int> &volumeTags,
6440 const std::vector<int> &curveTags,
6441 const std::vector<double> &radii,
6442 vectorpair &outDimTags,
6443 const bool removeVolume)
6444 {
6445 if(!_checkInit()) return;
6446 _createOcc();
6447 outDimTags.clear();
6448 GModel::current()->getOCCInternals()->fillet(volumeTags, curveTags, radii,
6449 outDimTags, removeVolume);
6450 }
6451
chamfer(const std::vector<int> & volumeTags,const std::vector<int> & curveTags,const std::vector<int> & surfaceTags,const std::vector<double> & distances,vectorpair & outDimTags,const bool removeVolume)6452 GMSH_API void gmsh::model::occ::chamfer(const std::vector<int> &volumeTags,
6453 const std::vector<int> &curveTags,
6454 const std::vector<int> &surfaceTags,
6455 const std::vector<double> &distances,
6456 vectorpair &outDimTags,
6457 const bool removeVolume)
6458 {
6459 if(!_checkInit()) return;
6460 _createOcc();
6461 outDimTags.clear();
6462 GModel::current()->getOCCInternals()->chamfer(
6463 volumeTags, curveTags, surfaceTags, distances, outDimTags, removeVolume);
6464 }
6465
fuse(const vectorpair & objectDimTags,const vectorpair & toolDimTags,vectorpair & outDimTags,std::vector<vectorpair> & outDimTagsMap,const int tag,const bool removeObject,const bool removeTool)6466 GMSH_API void gmsh::model::occ::fuse(const vectorpair &objectDimTags,
6467 const vectorpair &toolDimTags,
6468 vectorpair &outDimTags,
6469 std::vector<vectorpair> &outDimTagsMap,
6470 const int tag, const bool removeObject,
6471 const bool removeTool)
6472 {
6473 if(!_checkInit()) return;
6474 _createOcc();
6475 outDimTags.clear();
6476 outDimTagsMap.clear();
6477 GModel::current()->getOCCInternals()->booleanUnion(
6478 tag, objectDimTags, toolDimTags, outDimTags, outDimTagsMap, removeObject,
6479 removeTool);
6480 }
6481
intersect(const vectorpair & objectDimTags,const vectorpair & toolDimTags,vectorpair & outDimTags,std::vector<vectorpair> & outDimTagsMap,const int tag,const bool removeObject,const bool removeTool)6482 GMSH_API void gmsh::model::occ::intersect(
6483 const vectorpair &objectDimTags, const vectorpair &toolDimTags,
6484 vectorpair &outDimTags, std::vector<vectorpair> &outDimTagsMap, const int tag,
6485 const bool removeObject, const bool removeTool)
6486 {
6487 if(!_checkInit()) return;
6488 _createOcc();
6489 outDimTags.clear();
6490 outDimTagsMap.clear();
6491 GModel::current()->getOCCInternals()->booleanIntersection(
6492 tag, objectDimTags, toolDimTags, outDimTags, outDimTagsMap, removeObject,
6493 removeTool);
6494 }
6495
cut(const vectorpair & objectDimTags,const vectorpair & toolDimTags,vectorpair & outDimTags,std::vector<vectorpair> & outDimTagsMap,const int tag,const bool removeObject,const bool removeTool)6496 GMSH_API void gmsh::model::occ::cut(const vectorpair &objectDimTags,
6497 const vectorpair &toolDimTags,
6498 vectorpair &outDimTags,
6499 std::vector<vectorpair> &outDimTagsMap,
6500 const int tag, const bool removeObject,
6501 const bool removeTool)
6502 {
6503 if(!_checkInit()) return;
6504 _createOcc();
6505 outDimTags.clear();
6506 outDimTagsMap.clear();
6507 GModel::current()->getOCCInternals()->booleanDifference(
6508 tag, objectDimTags, toolDimTags, outDimTags, outDimTagsMap, removeObject,
6509 removeTool);
6510 }
6511
fragment(const vectorpair & objectDimTags,const vectorpair & toolDimTags,vectorpair & outDimTags,std::vector<vectorpair> & outDimTagsMap,const int tag,const bool removeObject,const bool removeTool)6512 GMSH_API void gmsh::model::occ::fragment(const vectorpair &objectDimTags,
6513 const vectorpair &toolDimTags,
6514 vectorpair &outDimTags,
6515 std::vector<vectorpair> &outDimTagsMap,
6516 const int tag, const bool removeObject,
6517 const bool removeTool)
6518 {
6519 if(!_checkInit()) return;
6520 _createOcc();
6521 outDimTags.clear();
6522 outDimTagsMap.clear();
6523 GModel::current()->getOCCInternals()->booleanFragments(
6524 tag, objectDimTags, toolDimTags, outDimTags, outDimTagsMap, removeObject,
6525 removeTool);
6526 }
6527
translate(const vectorpair & dimTags,const double dx,const double dy,const double dz)6528 GMSH_API void gmsh::model::occ::translate(const vectorpair &dimTags,
6529 const double dx, const double dy,
6530 const double dz)
6531 {
6532 if(!_checkInit()) return;
6533 _createOcc();
6534 GModel::current()->getOCCInternals()->translate(dimTags, dx, dy, dz);
6535 }
6536
rotate(const vectorpair & dimTags,const double x,const double y,const double z,const double ax,const double ay,const double az,const double angle)6537 GMSH_API void gmsh::model::occ::rotate(const vectorpair &dimTags,
6538 const double x, const double y,
6539 const double z, const double ax,
6540 const double ay, const double az,
6541 const double angle)
6542 {
6543 if(!_checkInit()) return;
6544 _createOcc();
6545 GModel::current()->getOCCInternals()->rotate(dimTags, x, y, z, ax, ay, az,
6546 angle);
6547 }
6548
dilate(const vectorpair & dimTags,const double x,const double y,const double z,const double a,const double b,const double c)6549 GMSH_API void gmsh::model::occ::dilate(const vectorpair &dimTags,
6550 const double x, const double y,
6551 const double z, const double a,
6552 const double b, const double c)
6553 {
6554 if(!_checkInit()) return;
6555 _createOcc();
6556 GModel::current()->getOCCInternals()->dilate(dimTags, x, y, z, a, b, c);
6557 }
6558
mirror(const vectorpair & dimTags,const double a,const double b,const double c,const double d)6559 GMSH_API void gmsh::model::occ::mirror(const vectorpair &dimTags,
6560 const double a, const double b,
6561 const double c, const double d)
6562 {
6563 if(!_checkInit()) return;
6564 _createOcc();
6565 GModel::current()->getOCCInternals()->symmetry(dimTags, a, b, c, d);
6566 }
6567
symmetrize(const vectorpair & dimTags,const double a,const double b,const double c,const double d)6568 GMSH_API void gmsh::model::occ::symmetrize(const vectorpair &dimTags,
6569 const double a, const double b,
6570 const double c, const double d)
6571 {
6572 gmsh::model::occ::mirror(dimTags, a, b, c, d);
6573 }
6574
6575 GMSH_API void
affineTransform(const vectorpair & dimTags,const std::vector<double> & affineTransform)6576 gmsh::model::occ::affineTransform(const vectorpair &dimTags,
6577 const std::vector<double> &affineTransform)
6578 {
6579 if(!_checkInit()) return;
6580 _createOcc();
6581 GModel::current()->getOCCInternals()->affine(dimTags, affineTransform);
6582 }
6583
copy(const vectorpair & dimTags,vectorpair & outDimTags)6584 GMSH_API void gmsh::model::occ::copy(const vectorpair &dimTags,
6585 vectorpair &outDimTags)
6586 {
6587 if(!_checkInit()) return;
6588 _createOcc();
6589 outDimTags.clear();
6590 GModel::current()->getOCCInternals()->copy(dimTags, outDimTags);
6591 }
6592
remove(const vectorpair & dimTags,const bool recursive)6593 GMSH_API void gmsh::model::occ::remove(const vectorpair &dimTags,
6594 const bool recursive)
6595 {
6596 if(!_checkInit()) return;
6597 _createOcc();
6598 GModel::current()->getOCCInternals()->remove(dimTags, recursive);
6599 }
6600
removeAllDuplicates()6601 GMSH_API void gmsh::model::occ::removeAllDuplicates()
6602 {
6603 if(!_checkInit()) return;
6604 _createOcc();
6605 GModel::current()->getOCCInternals()->removeAllDuplicates();
6606 }
6607
healShapes(vectorpair & outDimTags,const vectorpair & inDimTags,const double tolerance,const bool fixDegenerated,const bool fixSmallEdges,const bool fixSmallFaces,const bool sewFaces,const bool makeSolids)6608 GMSH_API void gmsh::model::occ::healShapes(
6609 vectorpair &outDimTags, const vectorpair &inDimTags, const double tolerance,
6610 const bool fixDegenerated, const bool fixSmallEdges, const bool fixSmallFaces,
6611 const bool sewFaces, const bool makeSolids)
6612 {
6613 if(!_checkInit()) return;
6614 _createOcc();
6615 outDimTags.clear();
6616 GModel::current()->getOCCInternals()->healShapes(
6617 inDimTags, outDimTags, tolerance, fixDegenerated, fixSmallEdges,
6618 fixSmallFaces, sewFaces, makeSolids);
6619 }
6620
importShapes(const std::string & fileName,vectorpair & outDimTags,const bool highestDimOnly,const std::string & format)6621 GMSH_API void gmsh::model::occ::importShapes(const std::string &fileName,
6622 vectorpair &outDimTags,
6623 const bool highestDimOnly,
6624 const std::string &format)
6625 {
6626 if(!_checkInit()) return;
6627 _createOcc();
6628 outDimTags.clear();
6629 GModel::current()->getOCCInternals()->importShapes(fileName, highestDimOnly,
6630 outDimTags, format);
6631 }
6632
importShapesNativePointer(const void * shape,vectorpair & outDimTags,const bool highestDimOnly)6633 GMSH_API void gmsh::model::occ::importShapesNativePointer(
6634 const void *shape, vectorpair &outDimTags, const bool highestDimOnly)
6635 {
6636 if(!_checkInit()) return;
6637 _createOcc();
6638 outDimTags.clear();
6639 #if defined(HAVE_OCC)
6640 GModel::current()->getOCCInternals()->importShapes(
6641 static_cast<const TopoDS_Shape *>(shape), highestDimOnly, outDimTags);
6642 #else
6643 Msg::Error("Gmsh requires OpenCASCADE to import native shape");
6644 #endif
6645 }
6646
getEntities(vectorpair & dimTags,const int dim)6647 GMSH_API void gmsh::model::occ::getEntities(vectorpair &dimTags, const int dim)
6648 {
6649 if(!_checkInit()) return;
6650 _createOcc();
6651 GModel::current()->getOCCInternals()->getEntities(dimTags, dim);
6652 }
6653
getEntitiesInBoundingBox(const double xmin,const double ymin,const double zmin,const double xmax,const double ymax,const double zmax,vectorpair & dimTags,const int dim)6654 GMSH_API void gmsh::model::occ::getEntitiesInBoundingBox(
6655 const double xmin, const double ymin, const double zmin, const double xmax,
6656 const double ymax, const double zmax, vectorpair &dimTags, const int dim)
6657 {
6658 if(!_checkInit()) return;
6659 _createOcc();
6660 dimTags.clear();
6661 GModel::current()->getOCCInternals()->getEntitiesInBoundingBox(
6662 xmin, ymin, zmin, xmax, ymax, zmax, dimTags, dim);
6663 }
6664
getBoundingBox(const int dim,const int tag,double & xmin,double & ymin,double & zmin,double & xmax,double & ymax,double & zmax)6665 GMSH_API void gmsh::model::occ::getBoundingBox(const int dim, const int tag,
6666 double &xmin, double &ymin,
6667 double &zmin, double &xmax,
6668 double &ymax, double &zmax)
6669 {
6670 if(!_checkInit()) return;
6671 _createOcc();
6672 GModel::current()->getOCCInternals()->getBoundingBox(dim, tag, xmin, ymin,
6673 zmin, xmax, ymax, zmax);
6674 }
6675
getMass(const int dim,const int tag,double & mass)6676 GMSH_API void gmsh::model::occ::getMass(const int dim, const int tag,
6677 double &mass)
6678 {
6679 if(!_checkInit()) return;
6680 _createOcc();
6681 GModel::current()->getOCCInternals()->getMass(dim, tag, mass);
6682 }
6683
getCenterOfMass(const int dim,const int tag,double & x,double & y,double & z)6684 GMSH_API void gmsh::model::occ::getCenterOfMass(const int dim, const int tag,
6685 double &x, double &y, double &z)
6686 {
6687 if(!_checkInit()) return;
6688 _createOcc();
6689 GModel::current()->getOCCInternals()->getCenterOfMass(dim, tag, x, y, z);
6690 }
6691
getMatrixOfInertia(const int dim,const int tag,std::vector<double> & m)6692 GMSH_API void gmsh::model::occ::getMatrixOfInertia(const int dim, const int tag,
6693 std::vector<double> &m)
6694 {
6695 if(!_checkInit()) return;
6696 _createOcc();
6697 GModel::current()->getOCCInternals()->getMatrixOfInertia(dim, tag, m);
6698 }
6699
getMaxTag(const int dim)6700 GMSH_API int gmsh::model::occ::getMaxTag(const int dim)
6701 {
6702 if(!_checkInit()) return -1;
6703 _createOcc();
6704 return GModel::current()->getOCCInternals()->getMaxTag(dim);
6705 }
6706
setMaxTag(const int dim,const int maxTag)6707 GMSH_API void gmsh::model::occ::setMaxTag(const int dim, const int maxTag)
6708 {
6709 if(!_checkInit()) return;
6710 _createOcc();
6711 GModel::current()->getOCCInternals()->setMaxTag(dim, maxTag);
6712 }
6713
synchronize()6714 GMSH_API void gmsh::model::occ::synchronize()
6715 {
6716 if(!_checkInit()) return;
6717 _createOcc();
6718 GModel::current()->getOCCInternals()->synchronize(GModel::current());
6719 }
6720
6721 // gmsh::model::occ::mesh
6722
setSize(const vectorpair & dimTags,const double size)6723 GMSH_API void gmsh::model::occ::mesh::setSize(const vectorpair &dimTags,
6724 const double size)
6725 {
6726 if(!_checkInit()) return;
6727 _createOcc();
6728 for(std::size_t i = 0; i < dimTags.size(); i++) {
6729 int dim = dimTags[i].first, tag = dimTags[i].second;
6730 GModel::current()->getOCCInternals()->setMeshSize(dim, tag, size);
6731 }
6732 }
6733
6734 // gmsh::view
6735
add(const std::string & name,const int tag)6736 GMSH_API int gmsh::view::add(const std::string &name, const int tag)
6737 {
6738 if(!_checkInit()) return -1;
6739 #if defined(HAVE_POST)
6740 PView *view = new PView(tag);
6741 view->getData()->setName(name);
6742 #if defined(HAVE_FLTK)
6743 if(FlGui::available()) FlGui::instance()->updateViews(true, true);
6744 #endif
6745 return view->getTag();
6746 #else
6747 Msg::Error("Views require the post-processing module");
6748 return -1;
6749 #endif
6750 }
6751
remove(const int tag)6752 GMSH_API void gmsh::view::remove(const int tag)
6753 {
6754 if(!_checkInit()) return;
6755 #if defined(HAVE_POST)
6756 PView *view = PView::getViewByTag(tag);
6757 if(!view) {
6758 Msg::Error("Unknown view with tag %d", tag);
6759 return;
6760 }
6761 delete view;
6762 #if defined(HAVE_FLTK)
6763 if(FlGui::available()) FlGui::instance()->updateViews(true, true);
6764 #endif
6765 #else
6766 Msg::Error("Views require the post-processing module");
6767 #endif
6768 }
6769
getIndex(const int tag)6770 GMSH_API int gmsh::view::getIndex(const int tag)
6771 {
6772 if(!_checkInit()) return -1;
6773 #if defined(HAVE_POST)
6774 PView *view = PView::getViewByTag(tag);
6775 if(!view) {
6776 Msg::Error("Unknown view with tag %d", tag);
6777 return -1;
6778 }
6779 return view->getIndex();
6780 #else
6781 Msg::Error("Views require the post-processing module");
6782 return -1;
6783 #endif
6784 }
6785
getTags(std::vector<int> & tags)6786 GMSH_API void gmsh::view::getTags(std::vector<int> &tags)
6787 {
6788 if(!_checkInit()) return;
6789 #if defined(HAVE_POST)
6790 tags.clear();
6791 for(std::size_t i = 0; i < PView::list.size(); i++)
6792 tags.push_back(PView::list[i]->getTag());
6793 #else
6794 Msg::Error("Views require the post-processing module");
6795 #endif
6796 }
6797
6798 template <class T>
6799 static void
_addModelData(const int tag,const int step,const std::string & modelName,const std::string & dataType,const std::vector<std::size_t> & tags,const T & data,const double time,const int numComponents,const int partition)6800 _addModelData(const int tag, const int step, const std::string &modelName,
6801 const std::string &dataType, const std::vector<std::size_t> &tags,
6802 const T &data, const double time, const int numComponents,
6803 const int partition)
6804 {
6805 #if defined(HAVE_POST)
6806 PView *view = PView::getViewByTag(tag);
6807 if(!view) {
6808 Msg::Error("Unknown view with tag %d", tag);
6809 return;
6810 }
6811 GModel *model = GModel::current();
6812 if(modelName.size()) {
6813 model = GModel::findByName(modelName);
6814 if(!model) {
6815 Msg::Error("Unknown model '%s'", modelName.c_str());
6816 return;
6817 }
6818 }
6819 PViewDataGModel::DataType type;
6820 if(dataType == "NodeData")
6821 type = PViewDataGModel::NodeData;
6822 else if(dataType == "ElementData")
6823 type = PViewDataGModel::ElementData;
6824 else if(dataType == "ElementNodeData")
6825 type = PViewDataGModel::ElementNodeData;
6826 else if(dataType == "GaussPointData")
6827 type = PViewDataGModel::GaussPointData;
6828 else if(dataType == "Beam")
6829 type = PViewDataGModel::BeamData;
6830 else {
6831 Msg::Error("Unknown type of view to add '%s'", dataType.c_str());
6832 return;
6833 }
6834
6835 PViewDataGModel *d = dynamic_cast<PViewDataGModel *>(view->getData());
6836 bool changeType = false;
6837 if(d && d->getType() != type) {
6838 Msg::Warning("Changing type of view to '%s'", dataType.c_str());
6839 changeType = true;
6840 }
6841 if(!d || changeType) { // change view type
6842 std::string name = view->getData()->getName();
6843 delete view->getData();
6844 d = new PViewDataGModel(type);
6845 d->setName(name);
6846 d->setFileName(name + ".msh");
6847 view->setData(d);
6848 }
6849 if(!d->addData(model, tags, data, step, time, partition, numComponents)) {
6850 Msg::Error("Could not add model data");
6851 return;
6852 }
6853 if(view->getOptions()->adaptVisualizationGrid)
6854 d->initAdaptiveData(view->getOptions()->timeStep,
6855 view->getOptions()->maxRecursionLevel,
6856 view->getOptions()->targetError);
6857 view->setChanged(true);
6858 #else
6859 Msg::Error("Views require the post-processing module");
6860 #endif
6861 }
6862
addModelData(const int tag,const int step,const std::string & modelName,const std::string & dataType,const std::vector<std::size_t> & tags,const std::vector<std::vector<double>> & data,const double time,const int numComponents,const int partition)6863 GMSH_API void gmsh::view::addModelData(
6864 const int tag, const int step, const std::string &modelName,
6865 const std::string &dataType, const std::vector<std::size_t> &tags,
6866 const std::vector<std::vector<double> > &data, const double time,
6867 const int numComponents, const int partition)
6868 {
6869 if(!_checkInit()) return;
6870 if(tags.size() != data.size()) {
6871 Msg::Error("Incompatible number of tags and data");
6872 return;
6873 }
6874 _addModelData(tag, step, modelName, dataType, tags, data, time, numComponents,
6875 partition);
6876 }
6877
addHomogeneousModelData(const int tag,const int step,const std::string & modelName,const std::string & dataType,const std::vector<std::size_t> & tags,const std::vector<double> & data,const double time,const int numComponents,const int partition)6878 GMSH_API void gmsh::view::addHomogeneousModelData(
6879 const int tag, const int step, const std::string &modelName,
6880 const std::string &dataType, const std::vector<std::size_t> &tags,
6881 const std::vector<double> &data, const double time, const int numComponents,
6882 const int partition)
6883 {
6884 if(!_checkInit()) return;
6885 _addModelData(tag, step, modelName, dataType, tags, data, time, numComponents,
6886 partition);
6887 }
6888
6889 #if defined(HAVE_POST)
_getModelData(const int tag,const int step,std::string & dataType,double & time,int & numComponents,int & numEnt,int & maxMult)6890 static stepData<double> *_getModelData(const int tag, const int step,
6891 std::string &dataType, double &time,
6892 int &numComponents, int &numEnt,
6893 int &maxMult)
6894 {
6895 if(!_checkInit()) return nullptr;
6896 PView *view = PView::getViewByTag(tag);
6897 if(!view) {
6898 Msg::Error("Unknown view with tag %d", tag);
6899 return nullptr;
6900 }
6901 PViewDataGModel *d = dynamic_cast<PViewDataGModel *>(view->getData());
6902 if(!d) {
6903 Msg::Error("View with tag %d does not contain model data", tag);
6904 return nullptr;
6905 }
6906 if(d->getType() == PViewDataGModel::NodeData)
6907 dataType = "NodeData";
6908 else if(d->getType() == PViewDataGModel::ElementData)
6909 dataType = "ElementData";
6910 else if(d->getType() == PViewDataGModel::ElementNodeData)
6911 dataType = "ElementNodeData";
6912 else if(d->getType() == PViewDataGModel::GaussPointData)
6913 dataType = "GaussPointData";
6914 else if(d->getType() == PViewDataGModel::BeamData)
6915 dataType = "Beam";
6916 else
6917 dataType = "Unknown";
6918 stepData<double> *s = d->getStepData(step);
6919 if(!s) {
6920 Msg::Error("View with tag %d does not contain model data for step %d", tag,
6921 step);
6922 return nullptr;
6923 }
6924 time = s->getTime();
6925 numComponents = s->getNumComponents();
6926 numEnt = 0;
6927 maxMult = 0;
6928 for(std::size_t i = 0; i < s->getNumData(); i++) {
6929 if(s->getData(i)) {
6930 numEnt++;
6931 maxMult = std::max(maxMult, s->getMult(i));
6932 }
6933 }
6934 return s;
6935 }
6936 #endif
6937
getModelData(const int tag,const int step,std::string & dataType,std::vector<std::size_t> & tags,std::vector<std::vector<double>> & data,double & time,int & numComponents)6938 GMSH_API void gmsh::view::getModelData(const int tag, const int step,
6939 std::string &dataType,
6940 std::vector<std::size_t> &tags,
6941 std::vector<std::vector<double> > &data,
6942 double &time, int &numComponents)
6943 {
6944 if(!_checkInit()) return;
6945 tags.clear();
6946 data.clear();
6947 #if defined(HAVE_POST)
6948 int numEnt, maxMult;
6949 stepData<double> *s =
6950 _getModelData(tag, step, dataType, time, numComponents, numEnt, maxMult);
6951 if(!s || !numComponents || !numEnt || !maxMult) return;
6952 data.resize(numEnt);
6953 tags.resize(numEnt);
6954 std::size_t j = 0;
6955 for(std::size_t i = 0; i < s->getNumData(); i++) {
6956 double *dd = s->getData(i);
6957 if(dd) {
6958 tags[j] = i;
6959 int mult = s->getMult(i);
6960 data[j].resize(numComponents * mult);
6961 for(int k = 0; k < numComponents * mult; k++) data[j][k] = dd[k];
6962 j++;
6963 }
6964 }
6965 #else
6966 Msg::Error("Views require the post-processing module");
6967 #endif
6968 }
6969
getHomogeneousModelData(const int tag,const int step,std::string & dataType,std::vector<std::size_t> & tags,std::vector<double> & data,double & time,int & numComponents)6970 GMSH_API void gmsh::view::getHomogeneousModelData(
6971 const int tag, const int step, std::string &dataType,
6972 std::vector<std::size_t> &tags, std::vector<double> &data, double &time,
6973 int &numComponents)
6974 {
6975 if(!_checkInit()) return;
6976 tags.clear();
6977 data.clear();
6978 #if defined(HAVE_POST)
6979 int numEnt, maxMult;
6980 stepData<double> *s =
6981 _getModelData(tag, step, dataType, time, numComponents, numEnt, maxMult);
6982 if(!s || !numComponents || !numEnt || !maxMult) return;
6983 data.resize(numEnt * numComponents * maxMult, 0.);
6984 tags.resize(numEnt);
6985 std::size_t j = 0;
6986 for(std::size_t i = 0; i < s->getNumData(); i++) {
6987 double *dd = s->getData(i);
6988 if(dd) {
6989 tags[j] = i;
6990 int mult = s->getMult(i);
6991 for(int k = 0; k < numComponents * mult; k++) {
6992 data[j * numComponents * maxMult + k] = dd[k];
6993 }
6994 j++;
6995 }
6996 }
6997 #else
6998 Msg::Error("Views require the post-processing module");
6999 #endif
7000 }
7001
7002 // for better performance, manual C implementation of gmsh::view::getModelData
gmshViewGetModelData(const int tag,const int step,char ** dataType,size_t ** tags,size_t * tags_n,double *** data,size_t ** data_n,size_t * data_nn,double * time,int * numComponents,int * ierr)7003 GMSH_API void gmshViewGetModelData(const int tag, const int step,
7004 char **dataType, size_t **tags,
7005 size_t *tags_n, double ***data,
7006 size_t **data_n, size_t *data_nn,
7007 double *time, int *numComponents, int *ierr)
7008 {
7009 if(!_checkInit()) {
7010 if(ierr) *ierr = -1;
7011 return;
7012 }
7013 #if defined(HAVE_POST)
7014 PView *view = PView::getViewByTag(tag);
7015 if(!view) {
7016 Msg::Error("Unknown view with tag %d", tag);
7017 if(ierr) *ierr = 2;
7018 return;
7019 }
7020 PViewDataGModel *d = dynamic_cast<PViewDataGModel *>(view->getData());
7021 if(!d) {
7022 Msg::Error("View with tag %d does not contain model data", tag);
7023 return;
7024 }
7025 if(d->getType() == PViewDataGModel::NodeData)
7026 *dataType = strdup("NodeData");
7027 else if(d->getType() == PViewDataGModel::ElementData)
7028 *dataType = strdup("ElementData");
7029 else if(d->getType() == PViewDataGModel::ElementNodeData)
7030 *dataType = strdup("ElementNodeData");
7031 else if(d->getType() == PViewDataGModel::GaussPointData)
7032 *dataType = strdup("GaussPointData");
7033 else if(d->getType() == PViewDataGModel::BeamData)
7034 *dataType = strdup("Beam");
7035 else
7036 *dataType = strdup("Unknown");
7037 stepData<double> *s = d->getStepData(step);
7038 if(!s) {
7039 Msg::Error("View with tag %d does not contain model data for step %d", tag,
7040 step);
7041 if(ierr) *ierr = 2;
7042 return;
7043 }
7044 *tags_n = 0;
7045 *data_nn = 0;
7046 *time = s->getTime();
7047 *numComponents = s->getNumComponents();
7048 int numEnt = 0;
7049 for(size_t i = 0; i < s->getNumData(); i++) {
7050 if(s->getData(i)) numEnt++;
7051 }
7052 if(!numEnt) return;
7053 *tags_n = numEnt;
7054 *tags = (size_t *)Malloc(numEnt * sizeof(size_t));
7055 *data_nn = numEnt;
7056 *data_n = (size_t *)Malloc(numEnt * sizeof(size_t *));
7057 *data = (double **)Malloc(numEnt * sizeof(double *));
7058 size_t j = 0;
7059 for(size_t i = 0; i < s->getNumData(); i++) {
7060 double *dd = s->getData(i);
7061 if(dd) {
7062 (*tags)[j] = i;
7063 int mult = s->getMult(i);
7064 (*data_n)[j] = *numComponents * mult;
7065 (*data)[j] = (double *)Malloc(*numComponents * mult * sizeof(double));
7066 for(int k = 0; k < *numComponents * mult; k++) (*data)[j][k] = dd[k];
7067 j++;
7068 }
7069 }
7070 if(ierr) *ierr = 0;
7071 #else
7072 Msg::Error("Views require the post-processing module");
7073 if(ierr) *ierr = -1;
7074 #endif
7075 }
7076
addListData(const int tag,const std::string & dataType,const int numElements,const std::vector<double> & data)7077 GMSH_API void gmsh::view::addListData(const int tag,
7078 const std::string &dataType,
7079 const int numElements,
7080 const std::vector<double> &data)
7081 {
7082 if(!_checkInit()) return;
7083 #if defined(HAVE_POST)
7084 PView *view = PView::getViewByTag(tag);
7085 if(!view) {
7086 Msg::Error("Unknown view with tag %d", tag);
7087 return;
7088 }
7089 PViewDataList *d = dynamic_cast<PViewDataList *>(view->getData());
7090 if(!d) { // change the view type
7091 std::string name = view->getData()->getName();
7092 delete view->getData();
7093 d = new PViewDataList();
7094 d->setName(name);
7095 d->setFileName(name + ".pos");
7096 view->setData(d);
7097 }
7098 const char *types[] = {"SP", "VP", "TP", "SL", "VL", "TL", "ST", "VT",
7099 "TT", "SQ", "VQ", "TQ", "SS", "VS", "TS", "SH",
7100 "VH", "TH", "SI", "VI", "TI", "SY", "VY", "TY"};
7101 for(int idxtype = 0; idxtype < 24; idxtype++) {
7102 if(dataType == types[idxtype]) {
7103 d->importList(idxtype, numElements, data, true);
7104 view->setChanged(true);
7105 return;
7106 }
7107 }
7108 Msg::Error("Unknown data type for list import");
7109 #else
7110 Msg::Error("Views require the post-processing module");
7111 #endif
7112 }
7113
getListData(const int tag,std::vector<std::string> & dataTypes,std::vector<int> & numElements,std::vector<std::vector<double>> & data)7114 GMSH_API void gmsh::view::getListData(const int tag,
7115 std::vector<std::string> &dataTypes,
7116 std::vector<int> &numElements,
7117 std::vector<std::vector<double> > &data)
7118 {
7119 if(!_checkInit()) return;
7120 #if defined(HAVE_POST)
7121 PView *view = PView::getViewByTag(tag);
7122 if(!view) {
7123 Msg::Error("Unknown view with tag %d", tag);
7124 return;
7125 }
7126 PViewDataList *d = dynamic_cast<PViewDataList *>(view->getData());
7127 if(!d) {
7128 Msg::Error("View with tag %d does not contain list data", tag);
7129 return;
7130 }
7131 const char *types[] = {"SP", "VP", "TP", "SL", "VL", "TL", "ST", "VT",
7132 "TT", "SQ", "VQ", "TQ", "SS", "VS", "TS", "SH",
7133 "VH", "TH", "SI", "VI", "TI", "SY", "VY", "TY"};
7134 std::vector<int> N(24);
7135 std::vector<std::vector<double> *> V(24);
7136 d->getListPointers(&N[0], &V[0]);
7137 for(int idxtype = 0; idxtype < 24; idxtype++) {
7138 if(N[idxtype]) {
7139 dataTypes.push_back(types[idxtype]);
7140 numElements.push_back(N[idxtype]);
7141 data.push_back(*V[idxtype]);
7142 }
7143 }
7144 #else
7145 Msg::Error("Views require the post-processing module");
7146 #endif
7147 }
7148
7149 #if defined(HAVE_POST)
getStringStyle(const std::vector<std::string> & style)7150 static double getStringStyle(const std::vector<std::string> &style)
7151 {
7152 if(style.empty()) return 0.;
7153 int align = 0, font = 0, fontsize = CTX::instance()->glFontSize;
7154 if(style.size() % 2) {
7155 Msg::Error("Number of string style attributes should be even");
7156 }
7157 else {
7158 for(std::size_t i = 0; i < style.size(); i += 2) {
7159 std::string key = style[i], val = style[i + 1];
7160 #if defined(HAVE_OPENGL)
7161 if(key == "Font")
7162 font = drawContext::global()->getFontIndex(val.c_str());
7163 else if(key == "FontSize")
7164 fontsize = atoi(val.c_str());
7165 else if(key == "Align")
7166 align = drawContext::global()->getFontAlign(val.c_str());
7167 #endif
7168 }
7169 }
7170 return (double)((align << 16) | (font << 8) | (fontsize));
7171 }
7172 #endif
7173
7174 GMSH_API void
addListDataString(const int tag,const std::vector<double> & coord,const std::vector<std::string> & data,const std::vector<std::string> & style)7175 gmsh::view::addListDataString(const int tag, const std::vector<double> &coord,
7176 const std::vector<std::string> &data,
7177 const std::vector<std::string> &style)
7178 {
7179 if(!_checkInit()) return;
7180 #if defined(HAVE_POST)
7181 PView *view = PView::getViewByTag(tag);
7182 if(!view) {
7183 Msg::Error("Unknown view with tag %d", tag);
7184 return;
7185 }
7186 PViewDataList *d = dynamic_cast<PViewDataList *>(view->getData());
7187 if(!d) { // change the view type
7188 std::string name = view->getData()->getName();
7189 delete view->getData();
7190 d = new PViewDataList();
7191 d->setName(name);
7192 d->setFileName(name + ".pos");
7193 view->setData(d);
7194 }
7195 if(coord.size() == 3) {
7196 d->T3D.push_back(coord[0]);
7197 d->T3D.push_back(coord[1]);
7198 d->T3D.push_back(coord[2]);
7199 d->T3D.push_back(getStringStyle(style)), d->T3D.push_back(d->T3C.size());
7200 d->NbT3++;
7201 for(std::size_t i = 0; i < data.size(); i++) {
7202 for(std::size_t j = 0; j < data[i].size(); j++) {
7203 d->T3C.push_back(data[i][j]);
7204 }
7205 d->T3C.push_back('\0');
7206 }
7207 }
7208 else if(coord.size() == 2) {
7209 d->T2D.push_back(coord[0]);
7210 d->T2D.push_back(coord[1]);
7211 d->T2D.push_back(getStringStyle(style)), d->T2D.push_back(d->T2C.size());
7212 d->NbT2++;
7213 for(std::size_t i = 0; i < data.size(); i++) {
7214 for(std::size_t j = 0; j < data[i].size(); j++) {
7215 d->T2C.push_back(data[i][j]);
7216 }
7217 d->T2C.push_back('\0');
7218 }
7219 }
7220 d->finalize();
7221 view->setChanged(true);
7222 #else
7223 Msg::Error("Views require the post-processing module");
7224 #endif
7225 }
7226
getListDataStrings(const int tag,const int dim,std::vector<double> & coord,std::vector<std::string> & data,std::vector<std::string> & style)7227 GMSH_API void gmsh::view::getListDataStrings(const int tag, const int dim,
7228 std::vector<double> &coord,
7229 std::vector<std::string> &data,
7230 std::vector<std::string> &style)
7231 {
7232 if(!_checkInit()) return;
7233 #if defined(HAVE_POST)
7234 PView *view = PView::getViewByTag(tag);
7235 if(!view) {
7236 Msg::Error("Unknown view with tag %d", tag);
7237 return;
7238 }
7239 PViewDataList *d = dynamic_cast<PViewDataList *>(view->getData());
7240 if(!d) {
7241 Msg::Error("View with tag %d does not contain list data", tag);
7242 return;
7243 }
7244 int nstep = d->getNumTimeSteps();
7245 if(dim == 3) {
7246 int ns = d->getNumStrings3D();
7247 for(int i = 0; i < ns; i++) {
7248 for(int j = 0; j < nstep; j++) {
7249 double x, y, z, styl;
7250 std::string s;
7251 d->getString3D(i, j, s, x, y, z, styl);
7252 if(i == 0) {
7253 coord.push_back(x);
7254 coord.push_back(y);
7255 coord.push_back(z);
7256 }
7257 data.push_back(s);
7258 // TODO convert style to strings, pad with empty strings so that all
7259 // strings return the same number of styling pairs
7260 style.push_back("");
7261 }
7262 }
7263 }
7264 else if(dim == 2) {
7265 int ns = d->getNumStrings2D();
7266 for(int i = 0; i < ns; i++) {
7267 for(int j = 0; j < nstep; j++) {
7268 double x, y, styl;
7269 std::string s;
7270 d->getString2D(i, j, s, x, y, styl);
7271 if(i == 0) {
7272 coord.push_back(x);
7273 coord.push_back(y);
7274 }
7275 data.push_back(s);
7276 // TODO convert style to strings, pad with empty strings so that all
7277 // strings return the same number of styling pairs
7278 style.push_back("");
7279 }
7280 }
7281 }
7282 #else
7283 Msg::Error("Views require the post-processing module");
7284 #endif
7285 }
7286
setInterpolationMatrices(const int tag,const std::string & type,const int d,const std::vector<double> & coef,const std::vector<double> & exp,const int dGeo,const std::vector<double> & coefGeo,const std::vector<double> & expGeo)7287 GMSH_API void gmsh::view::setInterpolationMatrices(
7288 const int tag, const std::string &type, const int d,
7289 const std::vector<double> &coef, const std::vector<double> &exp,
7290 const int dGeo, const std::vector<double> &coefGeo,
7291 const std::vector<double> &expGeo)
7292 {
7293 if(!_checkInit()) return;
7294 #if defined(HAVE_POST)
7295 PView *view = PView::getViewByTag(tag);
7296 if(!view) {
7297 Msg::Error("Unknown view with tag %d", tag);
7298 return;
7299 }
7300 PViewData *data = view->getData();
7301 if(!data) {
7302 Msg::Error("View with tag %d does not contain any data", tag);
7303 return;
7304 }
7305
7306 int itype = 0;
7307 if(type == "Line" || type == "line")
7308 itype = TYPE_LIN;
7309 else if(type == "Triangle" || type == "triangle")
7310 itype = TYPE_TRI;
7311 else if(type == "Quadrangle" || type == "quadrangle")
7312 itype = TYPE_QUA;
7313 else if(type == "Tetrahedron" || type == "tetrahedron")
7314 itype = TYPE_TET;
7315 else if(type == "Pyramid" || type == "pyramid")
7316 itype = TYPE_PYR;
7317 else if(type == "Prism" || type == "prism")
7318 itype = TYPE_PRI;
7319 else if(type == "Hexahedron" || type == "hexahedron")
7320 itype = TYPE_HEX;
7321 else {
7322 Msg::Error("Unknown element family type '%s'", type.c_str());
7323 return;
7324 }
7325
7326 if(data->haveInterpolationMatrices(itype))
7327 data->deleteInterpolationMatrices(itype);
7328
7329 if(d <= 0) return;
7330
7331 // field interpolation coefficients and exponents
7332 if((int)coef.size() != d * d) {
7333 Msg::Error("Wrong number of coefficients (%d != %d x %d)", (int)coef.size(),
7334 d, d);
7335 return;
7336 }
7337 if((int)exp.size() != d * 3) {
7338 Msg::Error("Wrong number of exponents (%d != %d x 3)", (int)exp.size(), d);
7339 return;
7340 }
7341 fullMatrix<double> F(d, d), P(d, 3);
7342 for(int i = 0; i < d; i++) {
7343 for(int j = 0; j < d; j++) { F(i, j) = coef[d * i + j]; }
7344 for(int j = 0; j < 3; j++) { P(i, j) = exp[3 * i + j]; }
7345 }
7346
7347 if(dGeo <= 0) {
7348 data->setInterpolationMatrices(itype, F, P);
7349 view->setChanged(true);
7350 return;
7351 }
7352
7353 // geometry interpolation coefficients and exponents
7354 if((int)coefGeo.size() != dGeo * dGeo) {
7355 Msg::Error("Wrong number of coefficients (%d != %d x %d)",
7356 (int)coefGeo.size(), dGeo, dGeo);
7357 return;
7358 }
7359 if((int)expGeo.size() != dGeo * 3) {
7360 Msg::Error("Wrong number of exponents (%d != %d x 3)", (int)expGeo.size(),
7361 dGeo);
7362 return;
7363 }
7364 fullMatrix<double> Fg(dGeo, dGeo), Pg(dGeo, 3);
7365 for(int i = 0; i < dGeo; i++) {
7366 for(int j = 0; j < dGeo; j++) { Fg(i, j) = coefGeo[dGeo * i + j]; }
7367 for(int j = 0; j < 3; j++) { Pg(i, j) = expGeo[3 * i + j]; }
7368 }
7369 data->setInterpolationMatrices(itype, F, P, Fg, Pg);
7370 view->setChanged(true);
7371 #else
7372 Msg::Error("Views require the post-processing module");
7373 #endif
7374 }
7375
addAlias(const int refTag,const bool copyOptions,const int tag)7376 GMSH_API int gmsh::view::addAlias(const int refTag, const bool copyOptions,
7377 const int tag)
7378 {
7379 if(!_checkInit()) return -1;
7380 #if defined(HAVE_POST)
7381 PView *ref = PView::getViewByTag(refTag);
7382 if(!ref) {
7383 Msg::Error("Unknown view with tag %d", refTag);
7384 return -1;
7385 }
7386 PView *view = new PView(ref, copyOptions, tag);
7387 #if defined(HAVE_FLTK)
7388 if(FlGui::available()) FlGui::instance()->updateViews(true, true);
7389 #endif
7390 return view->getTag();
7391 #else
7392 Msg::Error("Views require the post-processing module");
7393 return -1;
7394 #endif
7395 }
7396
combine(const std::string & what,const std::string & how,const bool remove,const bool copyOptions)7397 GMSH_API void gmsh::view::combine(const std::string &what,
7398 const std::string &how, const bool remove,
7399 const bool copyOptions)
7400 {
7401 if(!_checkInit()) return;
7402 #if defined(HAVE_POST)
7403 bool time = (what == "steps") ? true : false; // "elements"
7404 int ihow = (how == "all") ? 1 : (how == "name") ? 2 : 0; // "visible"
7405 PView::combine(time, ihow, remove, copyOptions);
7406 #if defined(HAVE_FLTK)
7407 if(FlGui::available()) FlGui::instance()->updateViews(true, true);
7408 #endif
7409 #else
7410 Msg::Error("Views require the post-processing module");
7411 #endif
7412 }
7413
probe(const int tag,const double x,const double y,const double z,std::vector<double> & value,double & distance,const int step,const int numComp,const bool gradient,const double distanceMax,const std::vector<double> & xElemCoord,const std::vector<double> & yElemCoord,const std::vector<double> & zElemCoord,const int dim)7414 GMSH_API void gmsh::view::probe(const int tag, const double x, const double y,
7415 const double z, std::vector<double> &value,
7416 double &distance, const int step,
7417 const int numComp, const bool gradient,
7418 const double distanceMax,
7419 const std::vector<double> &xElemCoord,
7420 const std::vector<double> &yElemCoord,
7421 const std::vector<double> &zElemCoord,
7422 const int dim)
7423 {
7424 if(!_checkInit()) return;
7425 #if defined(HAVE_POST)
7426 PView *view = PView::getViewByTag(tag);
7427 if(!view) {
7428 Msg::Error("Unknown view with tag %d", tag);
7429 return;
7430 }
7431 PViewData *data = view->getData();
7432 if(!data) {
7433 Msg::Error("No data in view %d", tag);
7434 return;
7435 }
7436 value.clear();
7437 std::vector<double> val(9 * data->getNumTimeSteps() * 3);
7438 int qn = 0;
7439 double *qx = nullptr, *qy = nullptr, *qz = nullptr;
7440 if(xElemCoord.size() && yElemCoord.size() && zElemCoord.size() &&
7441 xElemCoord.size() == yElemCoord.size() &&
7442 xElemCoord.size() == zElemCoord.size()) {
7443 qn = xElemCoord.size();
7444 qx = (double *)&xElemCoord[0];
7445 qy = (double *)&yElemCoord[0];
7446 qz = (double *)&zElemCoord[0];
7447 }
7448 int numSteps = (step < 0) ? data->getNumTimeSteps() : 1;
7449 int mult = gradient ? 3 : 1;
7450 int numVal = 0;
7451 distance = distanceMax;
7452 switch(numComp) {
7453 case 1:
7454 if(data->searchScalarClosest(x, y, z, distance, &val[0], step, nullptr,
7455 qn, qx, qy, qz, gradient, dim)) {
7456 numVal = numSteps * mult * 1;
7457 }
7458 break;
7459 case 3:
7460 if(data->searchVectorClosest(x, y, z, distance, &val[0], step, nullptr,
7461 qn, qx, qy, qz, gradient, dim)) {
7462 numVal = numSteps * mult * 3;
7463 }
7464 break;
7465 case 9:
7466 if(data->searchTensorClosest(x, y, z, distance, &val[0], step, nullptr,
7467 qn, qx, qy, qz, gradient, dim)) {
7468 numVal = numSteps * mult * 9;
7469 }
7470 break;
7471 default:
7472 if(data->searchScalarClosest(x, y, z, distance, &val[0], step, nullptr,
7473 qn, qx, qy, qz, gradient, dim)) {
7474 numVal = numSteps * mult * 1;
7475 }
7476 else if(data->searchVectorClosest(x, y, z, distance, &val[0], step, nullptr,
7477 qn, qx, qy, qz, gradient,
7478 dim)) {
7479 numVal = numSteps * mult * 3;
7480 }
7481 else if(data->searchTensorClosest(x, y, z, distance, &val[0], step, nullptr,
7482 qn, qx, qy, qz, gradient,
7483 dim)) {
7484 numVal = numSteps * mult * 9;
7485 }
7486 break;
7487 }
7488 for(int i = 0; i < numVal; i++) value.push_back(val[i]);
7489 #else
7490 Msg::Error("Views require the post-processing module");
7491 #endif
7492 }
7493
write(const int tag,const std::string & fileName,const bool append)7494 GMSH_API void gmsh::view::write(const int tag, const std::string &fileName,
7495 const bool append)
7496 {
7497 if(!_checkInit()) return;
7498 #if defined(HAVE_POST)
7499 PView *view = PView::getViewByTag(tag);
7500 if(!view) {
7501 Msg::Error("Unknown view with tag %d", tag);
7502 return;
7503 }
7504 view->write(fileName, 10, append);
7505 #else
7506 Msg::Error("Views require the post-processing module");
7507 #endif
7508 }
7509
setVisibilityPerWindow(const int tag,const int value,const int windowIndex)7510 GMSH_API void gmsh::view::setVisibilityPerWindow(const int tag, const int value,
7511 const int windowIndex)
7512 {
7513 if(!_checkInit()) return;
7514 #if defined(HAVE_POST)
7515 PView *view = PView::getViewByTag(tag);
7516 if(!view) {
7517 Msg::Error("Unknown view with tag %d", tag);
7518 return;
7519 }
7520 #if defined(HAVE_FLTK)
7521 FlGui::instance()->setCurrentOpenglWindow(windowIndex);
7522 drawContext *ctx = FlGui::instance()->getCurrentDrawContext();
7523 if(value)
7524 ctx->show(view);
7525 else
7526 ctx->hide(view);
7527 #endif
7528 #else
7529 Msg::Error("Views require the post-processing module");
7530 #endif
7531 }
7532
7533 // gmsh::view::option
7534
setNumber(int tag,const std::string & name,const double value)7535 GMSH_API void gmsh::view::option::setNumber(int tag, const std::string &name,
7536 const double value)
7537 {
7538 if(!_checkInit()) return;
7539 #if defined(HAVE_POST)
7540 PView *view = PView::getViewByTag(tag);
7541 if(view) {
7542 if(!GmshSetOption("View", name, value, view->getIndex()))
7543 Msg::Error("Could not set option '%s' in view with tag %d",
7544 name.c_str(), tag);
7545 }
7546 else {
7547 Msg::Error("Unknown view with tag %d", tag);
7548 }
7549 #else
7550 Msg::Error("Views require the post-processing module");
7551 #endif
7552 }
7553
getNumber(int tag,const std::string & name,double & value)7554 GMSH_API void gmsh::view::option::getNumber(int tag, const std::string &name,
7555 double &value)
7556 {
7557 if(!_checkInit()) return;
7558 #if defined(HAVE_POST)
7559 PView *view = PView::getViewByTag(tag);
7560 if(view) {
7561 if(!GmshGetOption("View", name, value, view->getIndex()))
7562 Msg::Error("Could not get option '%s' in view with tag %d",
7563 name.c_str(), tag);
7564 }
7565 else {
7566 Msg::Error("Unknown view with tag %d", tag);
7567 }
7568 #else
7569 Msg::Error("Views require the post-processing module");
7570 #endif
7571 }
7572
setString(int tag,const std::string & name,const std::string & value)7573 GMSH_API void gmsh::view::option::setString(int tag, const std::string &name,
7574 const std::string &value)
7575 {
7576 if(!_checkInit()) return;
7577 #if defined(HAVE_POST)
7578 PView *view = PView::getViewByTag(tag);
7579 if(view) {
7580 if(!GmshSetOption("View", name, value, view->getIndex()))
7581 Msg::Error("Could not set option '%s' in view with tag %d",
7582 name.c_str(), tag);
7583 }
7584 else {
7585 Msg::Error("Unknown view with tag %d", tag);
7586 }
7587 #else
7588 Msg::Error("Views require the post-processing module");
7589 #endif
7590 }
7591
getString(int tag,const std::string & name,std::string & value)7592 GMSH_API void gmsh::view::option::getString(int tag, const std::string &name,
7593 std::string &value)
7594 {
7595 if(!_checkInit()) return;
7596 #if defined(HAVE_POST)
7597 PView *view = PView::getViewByTag(tag);
7598 if(view) {
7599 if(!GmshGetOption("View", name, value, view->getIndex()))
7600 Msg::Error("Could not get option '%s' in view with tag %d",
7601 name.c_str(), tag);
7602 }
7603 else {
7604 Msg::Error("Unknown view with tag %d", tag);
7605 }
7606 #else
7607 Msg::Error("Views require the post-processing module");
7608 #endif
7609 }
7610
setColor(int tag,const std::string & name,const int r,const int g,const int b,const int a)7611 GMSH_API void gmsh::view::option::setColor(int tag, const std::string &name,
7612 const int r, const int g,
7613 const int b, const int a)
7614 {
7615 if(!_checkInit()) return;
7616 #if defined(HAVE_POST)
7617 PView *view = PView::getViewByTag(tag);
7618 if(view) {
7619 unsigned int value = CTX::instance()->packColor(r, g, b, a);
7620 if(!GmshSetOption("View", name, value, view->getIndex()))
7621 Msg::Error("Could not set option '%s' in view with tag %d",
7622 name.c_str(), tag);
7623 }
7624 else {
7625 Msg::Error("Unknown view with tag %d", tag);
7626 }
7627 #else
7628 Msg::Error("Views require the post-processing module");
7629 #endif
7630 }
7631
getColor(int tag,const std::string & name,int & r,int & g,int & b,int & a)7632 GMSH_API void gmsh::view::option::getColor(int tag, const std::string &name,
7633 int &r, int &g, int &b, int &a)
7634 {
7635 if(!_checkInit()) return;
7636 #if defined(HAVE_POST)
7637 PView *view = PView::getViewByTag(tag);
7638 if(view) {
7639 unsigned int value;
7640 if(GmshGetOption("View", name, value, view->getIndex())) {
7641 r = CTX::instance()->unpackRed(value);
7642 g = CTX::instance()->unpackGreen(value);
7643 b = CTX::instance()->unpackBlue(value);
7644 a = CTX::instance()->unpackAlpha(value);
7645 }
7646 else {
7647 Msg::Error("Could not get option '%s' in view with tag %d",
7648 name.c_str(), tag);
7649 }
7650 }
7651 else {
7652 Msg::Error("Unknown view with tag %d", tag);
7653 }
7654 #else
7655 Msg::Error("Views require the post-processing module");
7656 #endif
7657 }
7658
copy(const int refTag,const int tag)7659 GMSH_API void gmsh::view::option::copy(const int refTag, const int tag)
7660 {
7661 if(!_checkInit()) return;
7662 #if defined(HAVE_POST)
7663 PView *ref = PView::getViewByTag(refTag);
7664 if(!ref) {
7665 Msg::Error("Unknown view with tag %d", refTag);
7666 return;
7667 }
7668 PView *view = PView::getViewByTag(tag);
7669 if(!view) {
7670 Msg::Error("Unknown view with tag %d", tag);
7671 return;
7672 }
7673 view->setOptions(ref->getOptions());
7674 view->setChanged(true);
7675 #if defined(HAVE_FLTK)
7676 if(FlGui::available()) FlGui::instance()->updateViews(true, true);
7677 #endif
7678 #else
7679 Msg::Error("Views require the post-processing module");
7680 #endif
7681 }
7682
7683 // gmsh::plugin
7684
setNumber(const std::string & name,const std::string & option,const double value)7685 GMSH_API void gmsh::plugin::setNumber(const std::string &name,
7686 const std::string &option,
7687 const double value)
7688 {
7689 if(!_checkInit()) return;
7690 #if defined(HAVE_PLUGINS)
7691 try {
7692 PluginManager::instance()->setPluginOption(name, option, value);
7693 } catch(...) {
7694 Msg::Error("Unknown plugin or plugin option");
7695 }
7696 #else
7697 Msg::Error("Views require the post-processing and plugin modules");
7698 #endif
7699 }
7700
setString(const std::string & name,const std::string & option,const std::string & value)7701 GMSH_API void gmsh::plugin::setString(const std::string &name,
7702 const std::string &option,
7703 const std::string &value)
7704 {
7705 if(!_checkInit()) return;
7706 #if defined(HAVE_PLUGINS)
7707 try {
7708 PluginManager::instance()->setPluginOption(name, option, value);
7709 } catch(...) {
7710 Msg::Error("Unknown plugin or plugin option");
7711 }
7712 #else
7713 Msg::Error("Views require the post-processing and plugin modules");
7714 #endif
7715 }
7716
run(const std::string & name)7717 GMSH_API int gmsh::plugin::run(const std::string &name)
7718 {
7719 if(!_checkInit()) return 0;
7720 #if defined(HAVE_PLUGINS)
7721 try {
7722 return PluginManager::instance()->action(name, "Run", nullptr);
7723 } catch(...) {
7724 Msg::Error("Unknown plugin or plugin action");
7725 return 0;
7726 }
7727 #else
7728 Msg::Error("Views require the post-processing and plugin modules");
7729 return 0;
7730 #endif
7731 }
7732
7733 // gmsh::graphics
7734
draw()7735 GMSH_API void gmsh::graphics::draw()
7736 {
7737 #if defined(HAVE_OPENGL)
7738 drawContext::global()->draw(false); // not rate-limited
7739 #endif
7740 }
7741
7742 // gmsh::fltk
7743
7744 #if defined(HAVE_FLTK)
_errorHandlerFltk(const char * fmt,...)7745 static void _errorHandlerFltk(const char *fmt, ...)
7746 {
7747 char str[5000];
7748 va_list args;
7749 va_start(args, fmt);
7750 vsnprintf(str, sizeof(str), fmt, args);
7751 va_end(args);
7752 Msg::Error("%s (FLTK internal error)", str);
7753 }
7754
_createFltk()7755 static void _createFltk()
7756 {
7757 if(!FlGui::available())
7758 FlGui::instance(_argc, _argv, false, _errorHandlerFltk);
7759 }
7760 #endif
7761
initialize()7762 GMSH_API void gmsh::fltk::initialize()
7763 {
7764 if(!_checkInit()) return;
7765 #if defined(HAVE_FLTK)
7766 _createFltk();
7767 FlGui::setFinishedProcessingCommandLine();
7768 FlGui::check();
7769 #else
7770 Msg::Error("Fltk not available");
7771 #endif
7772 }
7773
isAvailable()7774 GMSH_API int gmsh::fltk::isAvailable()
7775 {
7776 if(!_checkInit()) return -1;
7777 #if defined(HAVE_FLTK)
7778 return FlGui::available() ? 1 : 0;
7779 #else
7780 return 0;
7781 #endif
7782 }
7783
wait(const double time)7784 GMSH_API void gmsh::fltk::wait(const double time)
7785 {
7786 if(!_checkInit()) return;
7787 #if defined(HAVE_FLTK)
7788 _createFltk();
7789 if(time >= 0)
7790 FlGui::wait(time, true); // force
7791 else
7792 FlGui::wait(true); // force
7793 #else
7794 Msg::Error("Fltk not available");
7795 #endif
7796 }
7797
lock()7798 GMSH_API void gmsh::fltk::lock()
7799 {
7800 if(!_checkInit()) return;
7801 #if defined(HAVE_FLTK)
7802 FlGui::lock();
7803 #else
7804 Msg::Error("Fltk not available");
7805 #endif
7806 }
7807
unlock()7808 GMSH_API void gmsh::fltk::unlock()
7809 {
7810 if(!_checkInit()) return;
7811 #if defined(HAVE_FLTK)
7812 FlGui::unlock();
7813 #else
7814 Msg::Error("Fltk not available");
7815 #endif
7816 }
7817
update()7818 GMSH_API void gmsh::fltk::update()
7819 {
7820 if(!_checkInit()) return;
7821 #if defined(HAVE_FLTK)
7822 _createFltk();
7823 FlGui::instance()->updateViews(true, true);
7824 #else
7825 Msg::Error("Fltk not available");
7826 #endif
7827 }
7828
awake(const std::string & action)7829 GMSH_API void gmsh::fltk::awake(const std::string &action)
7830 {
7831 if(!_checkInit()) return;
7832 #if defined(HAVE_FLTK)
7833 FlGui::awake(action);
7834 #else
7835 Msg::Error("Fltk not available");
7836 #endif
7837 }
7838
run()7839 GMSH_API void gmsh::fltk::run()
7840 {
7841 if(!_checkInit()) return;
7842 #if defined(HAVE_FLTK)
7843 _createFltk();
7844 FlGui::instance()->run(); // this calls draw() once
7845 #else
7846 Msg::Error("Fltk not available");
7847 #endif
7848 }
7849
7850 #if defined(HAVE_FLTK)
selectionCode(char val)7851 static int selectionCode(char val)
7852 {
7853 switch(val) {
7854 case 'q': return 0; // abort
7855 case 'l': return 1; // selected
7856 case 'r': return 2; // deselected
7857 case 'u': return 3; // undone last selection
7858 case 'e': return 4; // ended selection
7859 default: return -1; // unknown code
7860 }
7861 }
7862 #endif
7863
selectEntities(vectorpair & dimTags,const int dim)7864 GMSH_API int gmsh::fltk::selectEntities(vectorpair &dimTags, const int dim)
7865 {
7866 if(!_checkInit()) return -1;
7867 dimTags.clear();
7868 #if defined(HAVE_FLTK)
7869 _createFltk();
7870 char ret = 0;
7871 switch(dim) {
7872 case 0: ret = FlGui::instance()->selectEntity(ENT_POINT); break;
7873 case 1: ret = FlGui::instance()->selectEntity(ENT_CURVE); break;
7874 case 2: ret = FlGui::instance()->selectEntity(ENT_SURFACE); break;
7875 case 3: ret = FlGui::instance()->selectEntity(ENT_VOLUME); break;
7876 default: ret = FlGui::instance()->selectEntity(ENT_ALL); break;
7877 }
7878 if(!FlGui::available()) return 0; // GUI closed during selection
7879 for(std::size_t i = 0; i < FlGui::instance()->selectedVertices.size(); i++)
7880 dimTags.push_back(
7881 std::make_pair(0, FlGui::instance()->selectedVertices[i]->tag()));
7882 for(std::size_t i = 0; i < FlGui::instance()->selectedEdges.size(); i++)
7883 dimTags.push_back(
7884 std::make_pair(1, FlGui::instance()->selectedEdges[i]->tag()));
7885 for(std::size_t i = 0; i < FlGui::instance()->selectedFaces.size(); i++)
7886 dimTags.push_back(
7887 std::make_pair(2, FlGui::instance()->selectedFaces[i]->tag()));
7888 for(std::size_t i = 0; i < FlGui::instance()->selectedRegions.size(); i++)
7889 dimTags.push_back(
7890 std::make_pair(3, FlGui::instance()->selectedRegions[i]->tag()));
7891 return selectionCode(ret);
7892 #else
7893 return 0;
7894 #endif
7895 }
7896
selectElements(std::vector<std::size_t> & elementTags)7897 GMSH_API int gmsh::fltk::selectElements(std::vector<std::size_t> &elementTags)
7898 {
7899 if(!_checkInit()) return -1;
7900 elementTags.clear();
7901 #if defined(HAVE_FLTK)
7902 _createFltk();
7903 int old = CTX::instance()->pickElements;
7904 CTX::instance()->pickElements = 1;
7905 CTX::instance()->mesh.changed = ENT_ALL;
7906 char ret = FlGui::instance()->selectEntity(ENT_ALL);
7907 CTX::instance()->pickElements = old;
7908 if(!FlGui::available()) return 0; // GUI closed during selection
7909 for(std::size_t i = 0; i < FlGui::instance()->selectedElements.size(); i++)
7910 elementTags.push_back(FlGui::instance()->selectedElements[i]->getNum());
7911 return selectionCode(ret);
7912 #else
7913 return 0;
7914 #endif
7915 }
7916
selectViews(std::vector<int> & viewTags)7917 GMSH_API int gmsh::fltk::selectViews(std::vector<int> &viewTags)
7918 {
7919 if(!_checkInit()) return -1;
7920 viewTags.clear();
7921 #if defined(HAVE_FLTK)
7922 _createFltk();
7923 char ret = FlGui::instance()->selectEntity(ENT_ALL);
7924 if(!FlGui::available()) return 0; // GUI closed during selection
7925 for(std::size_t i = 0; i < FlGui::instance()->selectedViews.size(); i++)
7926 viewTags.push_back(FlGui::instance()->selectedViews[i]->getTag());
7927 return selectionCode(ret);
7928 #else
7929 return 0;
7930 #endif
7931 }
7932
splitCurrentWindow(const std::string & how,const double ratio)7933 GMSH_API void gmsh::fltk::splitCurrentWindow(const std::string &how,
7934 const double ratio)
7935 {
7936 if(!_checkInit()) return;
7937 #if defined(HAVE_FLTK)
7938 _createFltk();
7939 if(how == "h")
7940 FlGui::instance()->splitCurrentOpenglWindow('h', ratio);
7941 else if(how == "v")
7942 FlGui::instance()->splitCurrentOpenglWindow('v', ratio);
7943 else if(how == "u")
7944 FlGui::instance()->splitCurrentOpenglWindow('u');
7945 else {
7946 Msg::Error("Unknown window splitting method '%s'", how.c_str());
7947 }
7948 #endif
7949 }
7950
setCurrentWindow(const int windowIndex)7951 GMSH_API void gmsh::fltk::setCurrentWindow(const int windowIndex)
7952 {
7953 if(!_checkInit()) return;
7954 #if defined(HAVE_FLTK)
7955 _createFltk();
7956 FlGui::instance()->setCurrentOpenglWindow(windowIndex);
7957 #endif
7958 }
7959
setStatusMessage(const std::string & message,const bool graphics)7960 GMSH_API void gmsh::fltk::setStatusMessage(const std::string &message,
7961 const bool graphics)
7962 {
7963 if(!_checkInit()) return;
7964 #if defined(HAVE_FLTK)
7965 _createFltk();
7966 FlGui::instance()->setStatus(message, graphics);
7967 #endif
7968 }
7969
showContextWindow(const int dim,const int tag)7970 GMSH_API void gmsh::fltk::showContextWindow(const int dim, const int tag)
7971 {
7972 if(!_checkInit()) return;
7973 #if defined(HAVE_FLTK)
7974 _createFltk();
7975 FlGui::instance()->showOnelabContext(dim, tag);
7976 #endif
7977 }
7978
openTreeItem(const std::string & name)7979 GMSH_API void gmsh::fltk::openTreeItem(const std::string &name)
7980 {
7981 if(!_checkInit()) return;
7982 #if defined(HAVE_FLTK)
7983 _createFltk();
7984 FlGui::instance()->openTreeItem(name);
7985 #endif
7986 }
7987
closeTreeItem(const std::string & name)7988 GMSH_API void gmsh::fltk::closeTreeItem(const std::string &name)
7989 {
7990 if(!_checkInit()) return;
7991 #if defined(HAVE_FLTK)
7992 _createFltk();
7993 FlGui::instance()->closeTreeItem(name);
7994 #endif
7995 }
7996
7997 // gmsh::onelab
7998
set(const std::string & data,const std::string & format)7999 GMSH_API void gmsh::onelab::set(const std::string &data,
8000 const std::string &format)
8001 {
8002 if(!_checkInit()) return;
8003 #if defined(HAVE_ONELAB)
8004 if(format == "json") {
8005 if(!::onelab::server::instance()->fromJSON(data))
8006 Msg::Error("Could not parse json data '%s'", data.c_str());
8007 }
8008 else
8009 Msg::Error("Unknown data format");
8010 #else
8011 Msg::Error("ONELAB not available");
8012 #endif
8013 }
8014
get(std::string & data,const std::string & name,const std::string & format)8015 GMSH_API void gmsh::onelab::get(std::string &data, const std::string &name,
8016 const std::string &format)
8017 {
8018 if(!_checkInit()) return;
8019 #if defined(HAVE_ONELAB)
8020 data.clear();
8021 if(name.empty()) {
8022 if(format == "json")
8023 ::onelab::server::instance()->toJSON(data, "Gmsh");
8024 else
8025 Msg::Error("Unknown data format");
8026 }
8027 else {
8028 std::vector< ::onelab::number> ps;
8029 ::onelab::server::instance()->get(ps, name);
8030 if(ps.size()) {
8031 if(format == "json")
8032 data = ps[0].toJSON();
8033 else
8034 data = ps[0].toChar();
8035 }
8036 else {
8037 std::vector< ::onelab::string> ps2;
8038 ::onelab::server::instance()->get(ps2, name);
8039 if(ps2.size()) {
8040 if(format == "json")
8041 data = ps2[0].toJSON();
8042 else
8043 data = ps2[0].toChar();
8044 }
8045 }
8046 }
8047 #else
8048 Msg::Error("ONELAB not available");
8049 #endif
8050 }
8051
getNames(std::vector<std::string> & names,const std::string & search)8052 GMSH_API void gmsh::onelab::getNames(std::vector<std::string> &names,
8053 const std::string &search)
8054 {
8055 if(!_checkInit()) return;
8056 #if defined(HAVE_ONELAB)
8057 ::onelab::server::instance()->getParameterNames(names, search);
8058 #else
8059 Msg::Error("ONELAB not available");
8060 #endif
8061 }
8062
setNumber(const std::string & name,const std::vector<double> & value)8063 GMSH_API void gmsh::onelab::setNumber(const std::string &name,
8064 const std::vector<double> &value)
8065 {
8066 if(!_checkInit()) return;
8067 #if defined(HAVE_ONELAB)
8068 ::onelab::number p(name);
8069 std::vector< ::onelab::number> ps;
8070 ::onelab::server::instance()->get(ps, name);
8071 if(ps.size()) p = ps[0];
8072 p.setValues(value);
8073 ::onelab::server::instance()->set(p);
8074 #else
8075 Msg::Error("ONELAB not available");
8076 #endif
8077 }
8078
getNumber(const std::string & name,std::vector<double> & value)8079 GMSH_API void gmsh::onelab::getNumber(const std::string &name,
8080 std::vector<double> &value)
8081 {
8082 if(!_checkInit()) return;
8083 #if defined(HAVE_ONELAB)
8084 value.clear();
8085 std::vector< ::onelab::number> ps;
8086 ::onelab::server::instance()->get(ps, name);
8087 if(ps.size()) value = ps[0].getValues();
8088 #else
8089 Msg::Error("ONELAB not available");
8090 #endif
8091 }
8092
setString(const std::string & name,const std::vector<std::string> & value)8093 GMSH_API void gmsh::onelab::setString(const std::string &name,
8094 const std::vector<std::string> &value)
8095 {
8096 if(!_checkInit()) return;
8097 #if defined(HAVE_ONELAB)
8098 ::onelab::string p(name);
8099 std::vector< ::onelab::string> ps;
8100 ::onelab::server::instance()->get(ps, name);
8101 if(ps.size()) p = ps[0];
8102 p.setValues(value);
8103 ::onelab::server::instance()->set(p);
8104 #else
8105 Msg::Error("ONELAB not available");
8106 #endif
8107 }
8108
getString(const std::string & name,std::vector<std::string> & value)8109 GMSH_API void gmsh::onelab::getString(const std::string &name,
8110 std::vector<std::string> &value)
8111 {
8112 if(!_checkInit()) return;
8113 #if defined(HAVE_ONELAB)
8114 value.clear();
8115 std::vector< ::onelab::string> ps;
8116 ::onelab::server::instance()->get(ps, name);
8117 if(ps.size()) value = ps[0].getValues();
8118 #else
8119 Msg::Error("ONELAB not available");
8120 #endif
8121 }
8122
clear(const std::string & name)8123 GMSH_API void gmsh::onelab::clear(const std::string &name)
8124 {
8125 if(!_checkInit()) return;
8126 #if defined(HAVE_ONELAB)
8127 ::onelab::server::instance()->clear(name);
8128 #else
8129 Msg::Error("ONELAB not available");
8130 #endif
8131 }
8132
run(const std::string & name,const std::string & command)8133 GMSH_API void gmsh::onelab::run(const std::string &name,
8134 const std::string &command)
8135 {
8136 if(!_checkInit()) return;
8137 #if defined(HAVE_ONELAB)
8138 onelabUtils::runClient(name, command);
8139 #endif
8140 }
8141
8142 // gmsh::logger
8143
write(const std::string & message,const std::string & level)8144 GMSH_API void gmsh::logger::write(const std::string &message,
8145 const std::string &level)
8146 {
8147 if(!_checkInit()) return;
8148 if(level == "error")
8149 Msg::Error("%s", message.c_str());
8150 else if(level == "warning")
8151 Msg::Warning("%s", message.c_str());
8152 else
8153 Msg::Info("%s", message.c_str());
8154 }
8155
8156 class apiMsg : public GmshMessage {
8157 private:
8158 std::vector<std::string> _log;
8159
8160 public:
apiMsg()8161 apiMsg() {}
operator ()(std::string level,std::string message)8162 virtual void operator()(std::string level, std::string message)
8163 {
8164 _log.push_back(level + ": " + message);
8165 }
get(std::vector<std::string> & log) const8166 void get(std::vector<std::string> &log) const { log = _log; }
8167 };
8168
start()8169 GMSH_API void gmsh::logger::start()
8170 {
8171 if(!_checkInit()) return;
8172 GmshMessage *msg = Msg::GetCallback();
8173 if(msg) { Msg::Warning("Logger already started - ignoring"); }
8174 else {
8175 msg = new apiMsg();
8176 Msg::SetCallback(msg);
8177 }
8178 }
8179
get(std::vector<std::string> & log)8180 GMSH_API void gmsh::logger::get(std::vector<std::string> &log)
8181 {
8182 if(!_checkInit()) return;
8183 apiMsg *msg = dynamic_cast<apiMsg *>(Msg::GetCallback());
8184 if(msg) { msg->get(log); }
8185 else {
8186 log.clear();
8187 }
8188 }
8189
stop()8190 GMSH_API void gmsh::logger::stop()
8191 {
8192 if(!_checkInit()) return;
8193 GmshMessage *msg = Msg::GetCallback();
8194 if(msg) {
8195 delete msg;
8196 Msg::SetCallback(nullptr);
8197 }
8198 else {
8199 Msg::Warning("Logger not started - ignoring");
8200 }
8201 }
8202
getWallTime()8203 GMSH_API double gmsh::logger::getWallTime()
8204 {
8205 if(!_checkInit()) return -1;
8206 return TimeOfDay();
8207 }
8208
getCpuTime()8209 GMSH_API double gmsh::logger::getCpuTime()
8210 {
8211 if(!_checkInit()) return -1;
8212 return Cpu();
8213 }
8214
getLastError(std::string & error)8215 GMSH_API void gmsh::logger::getLastError(std::string &error)
8216 {
8217 if(!_checkInit()) return;
8218 error = Msg::GetLastError();
8219 }
8220