1// Gmsh - Copyright (C) 1997-2021 C. Geuzaine, J.-F. Remacle
2//
3// See the LICENSE.txt file in the Gmsh root directory for license information.
4// Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5
6#ifndef GMSH_H
7#define GMSH_H
8
9// This file redefines the Gmsh C++ API in terms of the C API (v4.9.2).
10//
11// This is provided as a convenience for users of the binary Gmsh SDK whose C++
12// compiler ABI is not compatible with the ABI of the C++ compiler used to create
13// the SDK (and who can thus not directly use the C++ API defined in `gmsh.h').
14//
15// To use this header file in your C++ code, simply rename it as `gmsh.h'.
16//
17// Note that using this header file will lead to (slightly) reduced performance
18// compared to using the native Gmsh C++ API from the original `gmsh.h', as it
19// entails additional data copies between this C++ wrapper, the C API and the
20// native C++ code.
21//
22// Do not edit this file directly: it is automatically generated by `api/gen.py'.
23
24#include <cmath>
25#include <vector>
26#include <string>
27#include <utility>
28#include <functional>
29
30#ifndef M_PI
31#define M_PI (3.14159265358979323846)
32#endif
33
34extern "C" {
35  #include "gmshc.h"
36}
37
38namespace gmsh {
39
40  // A geometrical entity in the Gmsh API is represented by two integers: its
41  // dimension (dim = 0, 1, 2 or 3) and its tag (its unique, strictly positive
42  // identifier). When dealing with multiple geometrical entities of possibly
43  // different dimensions, the entities are packed as a vector of (dim, tag)
44  // integer pairs.
45  typedef std::vector<std::pair<int, int> > vectorpair;
46
47}
48
49namespace gmsh {
50
51  template<typename t>
52  inline void vector2ptr(const std::vector<t> &v, t **p, size_t *size)
53  {
54    *p = (t*)gmshMalloc(sizeof(t) * v.size());
55    for(size_t i = 0; i < v.size(); ++i){
56      (*p)[i] = v[i];
57    }
58    *size = v.size();
59  }
60
61  inline void vectorpair2intptr(const gmsh::vectorpair &v, int **p, size_t *size)
62  {
63    *p = (int*)gmshMalloc(sizeof(int) * v.size() * 2);
64    for(size_t i = 0; i < v.size(); ++i){
65      (*p)[i * 2 + 0] = v[i].first;
66      (*p)[i * 2 + 1] = v[i].second;
67    }
68    *size = v.size() * 2;
69  }
70
71  inline void vectorstring2charptrptr(const std::vector<std::string> &v, char ***p, size_t *size)
72  {
73    *p = (char**)gmshMalloc(sizeof(char*) * v.size());
74    for(size_t i = 0; i < v.size(); ++i){
75      (*p)[i] = (char*)gmshMalloc(sizeof(char) * (v[i].size() + 1));
76      for(size_t j = 0; j < v[i].size(); j++) (*p)[i][j] = v[i][j];
77      (*p)[i][v[i].size()] = '\0';
78    }
79    *size = v.size();
80  }
81
82  template<typename t>
83  inline void vectorvector2ptrptr(const std::vector<std::vector<t> > &v, t ***p, size_t **size, size_t *sizeSize)
84  {
85    *p = (t**)gmshMalloc(sizeof(t*) * v.size());
86    *size = (size_t*)gmshMalloc(sizeof(size_t) * v.size());
87    for(size_t i = 0; i < v.size(); ++i)
88      vector2ptr(v[i], &((*p)[i]), &((*size)[i]));
89    *sizeSize = v.size();
90  }
91
92  inline void throwLastError()
93  {
94     int ierr = 0;
95     char *api_error_;
96     gmshLoggerGetLastError(&api_error_, &ierr);
97     if(ierr) throw "Could not get last error";
98     std::string error = std::string(api_error_);
99     gmshFree(api_error_);
100     throw error;
101  }
102
103}
104
105namespace gmsh { // Top-level functions
106
107  // Initialize the Gmsh API. This must be called before any call to the other
108  // functions in the API. If `argc' and `argv' (or just `argv' in Python or Julia)
109  // are provided, they will be handled in the same way as the command line
110  // arguments in the Gmsh app. If `readConfigFiles' is set, read system Gmsh
111  // configuration files (gmshrc and gmsh-options). If `run' is set, run in the
112  // same way as the Gmsh app, either interactively or in batch mode depending on
113  // the command line arguments. If `run' is not set, initializing the API sets the
114  // options "General.AbortOnError" to 2 and "General.Terminal" to 1. If compiled
115  // with OpenMP support, it also sets the number of threads to
116  // "General.NumThreads".
117  inline void initialize(int argc = 0, char ** argv = 0,
118                         const bool readConfigFiles = true,
119                         const bool run = false)
120  {
121    int ierr = 0;
122    gmshInitialize(argc, argv, (int)readConfigFiles, (int)run, &ierr);
123    if(ierr) throwLastError();
124  }
125
126  // Finalize the Gmsh API. This must be called when you are done using the Gmsh
127  // API.
128  inline void finalize()
129  {
130    int ierr = 0;
131    gmshFinalize(&ierr);
132    if(ierr) throwLastError();
133  }
134
135  // Open a file. Equivalent to the `File->Open' menu in the Gmsh app. Handling of
136  // the file depends on its extension and/or its contents: opening a file with
137  // model data will create a new model.
138  inline void open(const std::string & fileName)
139  {
140    int ierr = 0;
141    gmshOpen(fileName.c_str(), &ierr);
142    if(ierr) throwLastError();
143  }
144
145  // Merge a file. Equivalent to the `File->Merge' menu in the Gmsh app. Handling
146  // of the file depends on its extension and/or its contents. Merging a file with
147  // model data will add the data to the current model.
148  inline void merge(const std::string & fileName)
149  {
150    int ierr = 0;
151    gmshMerge(fileName.c_str(), &ierr);
152    if(ierr) throwLastError();
153  }
154
155  // Write a file. The export format is determined by the file extension.
156  inline void write(const std::string & fileName)
157  {
158    int ierr = 0;
159    gmshWrite(fileName.c_str(), &ierr);
160    if(ierr) throwLastError();
161  }
162
163  // Clear all loaded models and post-processing data, and add a new empty model.
164  inline void clear()
165  {
166    int ierr = 0;
167    gmshClear(&ierr);
168    if(ierr) throwLastError();
169  }
170
171  namespace option { // Option handling functions
172
173    // Set a numerical option to `value'. `name' is of the form "Category.Option"
174    // or "Category[num].Option". Available categories and options are listed in
175    // the Gmsh reference manual.
176    inline void setNumber(const std::string & name,
177                          const double value)
178    {
179      int ierr = 0;
180      gmshOptionSetNumber(name.c_str(), value, &ierr);
181      if(ierr) throwLastError();
182    }
183
184    // Get the `value' of a numerical option. `name' is of the form
185    // "Category.Option" or "Category[num].Option". Available categories and
186    // options are listed in the Gmsh reference manual.
187    inline void getNumber(const std::string & name,
188                          double & value)
189    {
190      int ierr = 0;
191      gmshOptionGetNumber(name.c_str(), &value, &ierr);
192      if(ierr) throwLastError();
193    }
194
195    // Set a string option to `value'. `name' is of the form "Category.Option" or
196    // "Category[num].Option". Available categories and options are listed in the
197    // Gmsh reference manual.
198    inline void setString(const std::string & name,
199                          const std::string & value)
200    {
201      int ierr = 0;
202      gmshOptionSetString(name.c_str(), value.c_str(), &ierr);
203      if(ierr) throwLastError();
204    }
205
206    // Get the `value' of a string option. `name' is of the form "Category.Option"
207    // or "Category[num].Option". Available categories and options are listed in
208    // the Gmsh reference manual.
209    inline void getString(const std::string & name,
210                          std::string & value)
211    {
212      int ierr = 0;
213      char *api_value_;
214      gmshOptionGetString(name.c_str(), &api_value_, &ierr);
215      if(ierr) throwLastError();
216      value = std::string(api_value_); gmshFree(api_value_);
217    }
218
219    // Set a color option to the RGBA value (`r', `g', `b', `a'), where where `r',
220    // `g', `b' and `a' should be integers between 0 and 255. `name' is of the form
221    // "Category.Color.Option" or "Category[num].Color.Option". Available
222    // categories and options are listed in the Gmsh reference manual. For
223    // conciseness "Color." can be ommitted in `name'.
224    inline void setColor(const std::string & name,
225                         const int r,
226                         const int g,
227                         const int b,
228                         const int a = 255)
229    {
230      int ierr = 0;
231      gmshOptionSetColor(name.c_str(), r, g, b, a, &ierr);
232      if(ierr) throwLastError();
233    }
234
235    // Get the `r', `g', `b', `a' value of a color option. `name' is of the form
236    // "Category.Color.Option" or "Category[num].Color.Option". Available
237    // categories and options are listed in the Gmsh reference manual. For
238    // conciseness "Color." can be ommitted in `name'.
239    inline void getColor(const std::string & name,
240                         int & r,
241                         int & g,
242                         int & b,
243                         int & a)
244    {
245      int ierr = 0;
246      gmshOptionGetColor(name.c_str(), &r, &g, &b, &a, &ierr);
247      if(ierr) throwLastError();
248    }
249
250  } // namespace option
251
252  namespace model { // Model functions
253
254    // Add a new model, with name `name', and set it as the current model.
255    inline void add(const std::string & name)
256    {
257      int ierr = 0;
258      gmshModelAdd(name.c_str(), &ierr);
259      if(ierr) throwLastError();
260    }
261
262    // Remove the current model.
263    inline void remove()
264    {
265      int ierr = 0;
266      gmshModelRemove(&ierr);
267      if(ierr) throwLastError();
268    }
269
270    // List the names of all models.
271    inline void list(std::vector<std::string> & names)
272    {
273      int ierr = 0;
274      char **api_names_; size_t api_names_n_;
275      gmshModelList(&api_names_, &api_names_n_, &ierr);
276      if(ierr) throwLastError();
277      names.resize(api_names_n_); for(size_t i = 0; i < api_names_n_; ++i){ names[i] = std::string(api_names_[i]); gmshFree(api_names_[i]); } gmshFree(api_names_);
278    }
279
280    // Get the name of the current model.
281    inline void getCurrent(std::string & name)
282    {
283      int ierr = 0;
284      char *api_name_;
285      gmshModelGetCurrent(&api_name_, &ierr);
286      if(ierr) throwLastError();
287      name = std::string(api_name_); gmshFree(api_name_);
288    }
289
290    // Set the current model to the model with name `name'. If several models have
291    // the same name, select the one that was added first.
292    inline void setCurrent(const std::string & name)
293    {
294      int ierr = 0;
295      gmshModelSetCurrent(name.c_str(), &ierr);
296      if(ierr) throwLastError();
297    }
298
299    // Get the file name (if any) associated with the current model. A file name is
300    // associated when a model is read from a file on disk.
301    inline void getFileName(std::string & fileName)
302    {
303      int ierr = 0;
304      char *api_fileName_;
305      gmshModelGetFileName(&api_fileName_, &ierr);
306      if(ierr) throwLastError();
307      fileName = std::string(api_fileName_); gmshFree(api_fileName_);
308    }
309
310    // Set the file name associated with the current model.
311    inline void setFileName(const std::string & fileName)
312    {
313      int ierr = 0;
314      gmshModelSetFileName(fileName.c_str(), &ierr);
315      if(ierr) throwLastError();
316    }
317
318    // Get all the entities in the current model. If `dim' is >= 0, return only the
319    // entities of the specified dimension (e.g. points if `dim' == 0). The
320    // entities are returned as a vector of (dim, tag) integer pairs.
321    inline void getEntities(gmsh::vectorpair & dimTags,
322                            const int dim = -1)
323    {
324      int ierr = 0;
325      int *api_dimTags_; size_t api_dimTags_n_;
326      gmshModelGetEntities(&api_dimTags_, &api_dimTags_n_, dim, &ierr);
327      if(ierr) throwLastError();
328      dimTags.resize(api_dimTags_n_ / 2); for(size_t i = 0; i < api_dimTags_n_ / 2; ++i){ dimTags[i].first = api_dimTags_[i * 2 + 0]; dimTags[i].second = api_dimTags_[i * 2 + 1]; } gmshFree(api_dimTags_);
329    }
330
331    // Set the name of the entity of dimension `dim' and tag `tag'.
332    inline void setEntityName(const int dim,
333                              const int tag,
334                              const std::string & name)
335    {
336      int ierr = 0;
337      gmshModelSetEntityName(dim, tag, name.c_str(), &ierr);
338      if(ierr) throwLastError();
339    }
340
341    // Get the name of the entity of dimension `dim' and tag `tag'.
342    inline void getEntityName(const int dim,
343                              const int tag,
344                              std::string & name)
345    {
346      int ierr = 0;
347      char *api_name_;
348      gmshModelGetEntityName(dim, tag, &api_name_, &ierr);
349      if(ierr) throwLastError();
350      name = std::string(api_name_); gmshFree(api_name_);
351    }
352
353    // Get all the physical groups in the current model. If `dim' is >= 0, return
354    // only the entities of the specified dimension (e.g. physical points if `dim'
355    // == 0). The entities are returned as a vector of (dim, tag) integer pairs.
356    inline void getPhysicalGroups(gmsh::vectorpair & dimTags,
357                                  const int dim = -1)
358    {
359      int ierr = 0;
360      int *api_dimTags_; size_t api_dimTags_n_;
361      gmshModelGetPhysicalGroups(&api_dimTags_, &api_dimTags_n_, dim, &ierr);
362      if(ierr) throwLastError();
363      dimTags.resize(api_dimTags_n_ / 2); for(size_t i = 0; i < api_dimTags_n_ / 2; ++i){ dimTags[i].first = api_dimTags_[i * 2 + 0]; dimTags[i].second = api_dimTags_[i * 2 + 1]; } gmshFree(api_dimTags_);
364    }
365
366    // Get the tags of the model entities making up the physical group of dimension
367    // `dim' and tag `tag'.
368    inline void getEntitiesForPhysicalGroup(const int dim,
369                                            const int tag,
370                                            std::vector<int> & tags)
371    {
372      int ierr = 0;
373      int *api_tags_; size_t api_tags_n_;
374      gmshModelGetEntitiesForPhysicalGroup(dim, tag, &api_tags_, &api_tags_n_, &ierr);
375      if(ierr) throwLastError();
376      tags.assign(api_tags_, api_tags_ + api_tags_n_); gmshFree(api_tags_);
377    }
378
379    // Get the tags of the physical groups (if any) to which the model entity of
380    // dimension `dim' and tag `tag' belongs.
381    inline void getPhysicalGroupsForEntity(const int dim,
382                                           const int tag,
383                                           std::vector<int> & physicalTags)
384    {
385      int ierr = 0;
386      int *api_physicalTags_; size_t api_physicalTags_n_;
387      gmshModelGetPhysicalGroupsForEntity(dim, tag, &api_physicalTags_, &api_physicalTags_n_, &ierr);
388      if(ierr) throwLastError();
389      physicalTags.assign(api_physicalTags_, api_physicalTags_ + api_physicalTags_n_); gmshFree(api_physicalTags_);
390    }
391
392    // Add a physical group of dimension `dim', grouping the model entities with
393    // tags `tags'. Return the tag of the physical group, equal to `tag' if `tag'
394    // is positive, or a new tag if `tag' < 0.
395    inline int addPhysicalGroup(const int dim,
396                                const std::vector<int> & tags,
397                                const int tag = -1)
398    {
399      int ierr = 0;
400      int *api_tags_; size_t api_tags_n_; vector2ptr(tags, &api_tags_, &api_tags_n_);
401      int result_api_ = gmshModelAddPhysicalGroup(dim, api_tags_, api_tags_n_, tag, &ierr);
402      if(ierr) throwLastError();
403      gmshFree(api_tags_);
404      return result_api_;
405    }
406
407    // Remove the physical groups `dimTags' from the current model. If `dimTags' is
408    // empty, remove all groups.
409    inline void removePhysicalGroups(const gmsh::vectorpair & dimTags = gmsh::vectorpair())
410    {
411      int ierr = 0;
412      int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
413      gmshModelRemovePhysicalGroups(api_dimTags_, api_dimTags_n_, &ierr);
414      if(ierr) throwLastError();
415      gmshFree(api_dimTags_);
416    }
417
418    // Set the name of the physical group of dimension `dim' and tag `tag'.
419    inline void setPhysicalName(const int dim,
420                                const int tag,
421                                const std::string & name)
422    {
423      int ierr = 0;
424      gmshModelSetPhysicalName(dim, tag, name.c_str(), &ierr);
425      if(ierr) throwLastError();
426    }
427
428    // Remove the physical name `name' from the current model.
429    inline void removePhysicalName(const std::string & name)
430    {
431      int ierr = 0;
432      gmshModelRemovePhysicalName(name.c_str(), &ierr);
433      if(ierr) throwLastError();
434    }
435
436    // Get the name of the physical group of dimension `dim' and tag `tag'.
437    inline void getPhysicalName(const int dim,
438                                const int tag,
439                                std::string & name)
440    {
441      int ierr = 0;
442      char *api_name_;
443      gmshModelGetPhysicalName(dim, tag, &api_name_, &ierr);
444      if(ierr) throwLastError();
445      name = std::string(api_name_); gmshFree(api_name_);
446    }
447
448    // Set the tag of the entity of dimension `dim' and tag `tag' to the new value
449    // `newTag'.
450    inline void setTag(const int dim,
451                       const int tag,
452                       const int newTag)
453    {
454      int ierr = 0;
455      gmshModelSetTag(dim, tag, newTag, &ierr);
456      if(ierr) throwLastError();
457    }
458
459    // Get the boundary of the model entities `dimTags'. Return in `outDimTags' the
460    // boundary of the individual entities (if `combined' is false) or the boundary
461    // of the combined geometrical shape formed by all input entities (if
462    // `combined' is true). Return tags multiplied by the sign of the boundary
463    // entity if `oriented' is true. Apply the boundary operator recursively down
464    // to dimension 0 (i.e. to points) if `recursive' is true.
465    inline void getBoundary(const gmsh::vectorpair & dimTags,
466                            gmsh::vectorpair & outDimTags,
467                            const bool combined = true,
468                            const bool oriented = true,
469                            const bool recursive = false)
470    {
471      int ierr = 0;
472      int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
473      int *api_outDimTags_; size_t api_outDimTags_n_;
474      gmshModelGetBoundary(api_dimTags_, api_dimTags_n_, &api_outDimTags_, &api_outDimTags_n_, (int)combined, (int)oriented, (int)recursive, &ierr);
475      if(ierr) throwLastError();
476      gmshFree(api_dimTags_);
477      outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
478    }
479
480    // Get the upward and downward adjacencies of the model entity of dimension
481    // `dim' and tag `tag'. The `upward' vector returns the adjacent entities of
482    // dimension `dim' + 1; the `downward' vector returns the adjacent entities of
483    // dimension `dim' - 1.
484    inline void getAdjacencies(const int dim,
485                               const int tag,
486                               std::vector<int> & upward,
487                               std::vector<int> & downward)
488    {
489      int ierr = 0;
490      int *api_upward_; size_t api_upward_n_;
491      int *api_downward_; size_t api_downward_n_;
492      gmshModelGetAdjacencies(dim, tag, &api_upward_, &api_upward_n_, &api_downward_, &api_downward_n_, &ierr);
493      if(ierr) throwLastError();
494      upward.assign(api_upward_, api_upward_ + api_upward_n_); gmshFree(api_upward_);
495      downward.assign(api_downward_, api_downward_ + api_downward_n_); gmshFree(api_downward_);
496    }
497
498    // Get the model entities in the bounding box defined by the two points
499    // (`xmin', `ymin', `zmin') and (`xmax', `ymax', `zmax'). If `dim' is >= 0,
500    // return only the entities of the specified dimension (e.g. points if `dim' ==
501    // 0).
502    inline void getEntitiesInBoundingBox(const double xmin,
503                                         const double ymin,
504                                         const double zmin,
505                                         const double xmax,
506                                         const double ymax,
507                                         const double zmax,
508                                         gmsh::vectorpair & tags,
509                                         const int dim = -1)
510    {
511      int ierr = 0;
512      int *api_tags_; size_t api_tags_n_;
513      gmshModelGetEntitiesInBoundingBox(xmin, ymin, zmin, xmax, ymax, zmax, &api_tags_, &api_tags_n_, dim, &ierr);
514      if(ierr) throwLastError();
515      tags.resize(api_tags_n_ / 2); for(size_t i = 0; i < api_tags_n_ / 2; ++i){ tags[i].first = api_tags_[i * 2 + 0]; tags[i].second = api_tags_[i * 2 + 1]; } gmshFree(api_tags_);
516    }
517
518    // Get the bounding box (`xmin', `ymin', `zmin'), (`xmax', `ymax', `zmax') of
519    // the model entity of dimension `dim' and tag `tag'. If `dim' and `tag' are
520    // negative, get the bounding box of the whole model.
521    inline void getBoundingBox(const int dim,
522                               const int tag,
523                               double & xmin,
524                               double & ymin,
525                               double & zmin,
526                               double & xmax,
527                               double & ymax,
528                               double & zmax)
529    {
530      int ierr = 0;
531      gmshModelGetBoundingBox(dim, tag, &xmin, &ymin, &zmin, &xmax, &ymax, &zmax, &ierr);
532      if(ierr) throwLastError();
533    }
534
535    // Return the geometrical dimension of the current model.
536    inline int getDimension()
537    {
538      int ierr = 0;
539      int result_api_ = gmshModelGetDimension(&ierr);
540      if(ierr) throwLastError();
541      return result_api_;
542    }
543
544    // Add a discrete model entity (defined by a mesh) of dimension `dim' in the
545    // current model. Return the tag of the new discrete entity, equal to `tag' if
546    // `tag' is positive, or a new tag if `tag' < 0. `boundary' specifies the tags
547    // of the entities on the boundary of the discrete entity, if any. Specifying
548    // `boundary' allows Gmsh to construct the topology of the overall model.
549    inline int addDiscreteEntity(const int dim,
550                                 const int tag = -1,
551                                 const std::vector<int> & boundary = std::vector<int>())
552    {
553      int ierr = 0;
554      int *api_boundary_; size_t api_boundary_n_; vector2ptr(boundary, &api_boundary_, &api_boundary_n_);
555      int result_api_ = gmshModelAddDiscreteEntity(dim, tag, api_boundary_, api_boundary_n_, &ierr);
556      if(ierr) throwLastError();
557      gmshFree(api_boundary_);
558      return result_api_;
559    }
560
561    // Remove the entities `dimTags' of the current model, provided that they are
562    // not on the boundary of (or embedded in) higher-dimensional entities. If
563    // `recursive' is true, remove all the entities on their boundaries, down to
564    // dimension 0.
565    inline void removeEntities(const gmsh::vectorpair & dimTags,
566                               const bool recursive = false)
567    {
568      int ierr = 0;
569      int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
570      gmshModelRemoveEntities(api_dimTags_, api_dimTags_n_, (int)recursive, &ierr);
571      if(ierr) throwLastError();
572      gmshFree(api_dimTags_);
573    }
574
575    // Remove the entity name `name' from the current model.
576    inline void removeEntityName(const std::string & name)
577    {
578      int ierr = 0;
579      gmshModelRemoveEntityName(name.c_str(), &ierr);
580      if(ierr) throwLastError();
581    }
582
583    // Get the type of the entity of dimension `dim' and tag `tag'.
584    inline void getType(const int dim,
585                        const int tag,
586                        std::string & entityType)
587    {
588      int ierr = 0;
589      char *api_entityType_;
590      gmshModelGetType(dim, tag, &api_entityType_, &ierr);
591      if(ierr) throwLastError();
592      entityType = std::string(api_entityType_); gmshFree(api_entityType_);
593    }
594
595    // In a partitioned model, get the parent of the entity of dimension `dim' and
596    // tag `tag', i.e. from which the entity is a part of, if any. `parentDim' and
597    // `parentTag' are set to -1 if the entity has no parent.
598    inline void getParent(const int dim,
599                          const int tag,
600                          int & parentDim,
601                          int & parentTag)
602    {
603      int ierr = 0;
604      gmshModelGetParent(dim, tag, &parentDim, &parentTag, &ierr);
605      if(ierr) throwLastError();
606    }
607
608    // Return the number of partitions in the model.
609    inline int getNumberOfPartitions()
610    {
611      int ierr = 0;
612      int result_api_ = gmshModelGetNumberOfPartitions(&ierr);
613      if(ierr) throwLastError();
614      return result_api_;
615    }
616
617    // In a partitioned model, return the tags of the partition(s) to which the
618    // entity belongs.
619    inline void getPartitions(const int dim,
620                              const int tag,
621                              std::vector<int> & partitions)
622    {
623      int ierr = 0;
624      int *api_partitions_; size_t api_partitions_n_;
625      gmshModelGetPartitions(dim, tag, &api_partitions_, &api_partitions_n_, &ierr);
626      if(ierr) throwLastError();
627      partitions.assign(api_partitions_, api_partitions_ + api_partitions_n_); gmshFree(api_partitions_);
628    }
629
630    // Evaluate the parametrization of the entity of dimension `dim' and tag `tag'
631    // at the parametric coordinates `parametricCoord'. Only valid for `dim' equal
632    // to 0 (with empty `parametricCoord'), 1 (with `parametricCoord' containing
633    // parametric coordinates on the curve) or 2 (with `parametricCoord' containing
634    // pairs of u, v parametric coordinates on the surface, concatenated: [p1u,
635    // p1v, p2u, ...]). Return triplets of x, y, z coordinates in `coord',
636    // concatenated: [p1x, p1y, p1z, p2x, ...].
637    inline void getValue(const int dim,
638                         const int tag,
639                         const std::vector<double> & parametricCoord,
640                         std::vector<double> & coord)
641    {
642      int ierr = 0;
643      double *api_parametricCoord_; size_t api_parametricCoord_n_; vector2ptr(parametricCoord, &api_parametricCoord_, &api_parametricCoord_n_);
644      double *api_coord_; size_t api_coord_n_;
645      gmshModelGetValue(dim, tag, api_parametricCoord_, api_parametricCoord_n_, &api_coord_, &api_coord_n_, &ierr);
646      if(ierr) throwLastError();
647      gmshFree(api_parametricCoord_);
648      coord.assign(api_coord_, api_coord_ + api_coord_n_); gmshFree(api_coord_);
649    }
650
651    // Evaluate the derivative of the parametrization of the entity of dimension
652    // `dim' and tag `tag' at the parametric coordinates `parametricCoord'. Only
653    // valid for `dim' equal to 1 (with `parametricCoord' containing parametric
654    // coordinates on the curve) or 2 (with `parametricCoord' containing pairs of
655    // u, v parametric coordinates on the surface, concatenated: [p1u, p1v, p2u,
656    // ...]). For `dim' equal to 1 return the x, y, z components of the derivative
657    // with respect to u [d1ux, d1uy, d1uz, d2ux, ...]; for `dim' equal to 2 return
658    // the x, y, z components of the derivative with respect to u and v: [d1ux,
659    // d1uy, d1uz, d1vx, d1vy, d1vz, d2ux, ...].
660    inline void getDerivative(const int dim,
661                              const int tag,
662                              const std::vector<double> & parametricCoord,
663                              std::vector<double> & derivatives)
664    {
665      int ierr = 0;
666      double *api_parametricCoord_; size_t api_parametricCoord_n_; vector2ptr(parametricCoord, &api_parametricCoord_, &api_parametricCoord_n_);
667      double *api_derivatives_; size_t api_derivatives_n_;
668      gmshModelGetDerivative(dim, tag, api_parametricCoord_, api_parametricCoord_n_, &api_derivatives_, &api_derivatives_n_, &ierr);
669      if(ierr) throwLastError();
670      gmshFree(api_parametricCoord_);
671      derivatives.assign(api_derivatives_, api_derivatives_ + api_derivatives_n_); gmshFree(api_derivatives_);
672    }
673
674    // Evaluate the second derivative of the parametrization of the entity of
675    // dimension `dim' and tag `tag' at the parametric coordinates
676    // `parametricCoord'. Only valid for `dim' equal to 1 (with `parametricCoord'
677    // containing parametric coordinates on the curve) or 2 (with `parametricCoord'
678    // containing pairs of u, v parametric coordinates on the surface,
679    // concatenated: [p1u, p1v, p2u, ...]). For `dim' equal to 1 return the x, y, z
680    // components of the second derivative with respect to u [d1uux, d1uuy, d1uuz,
681    // d2uux, ...]; for `dim' equal to 2 return the x, y, z components of the
682    // second derivative with respect to u and v, and the mixed derivative with
683    // respect to u and v: [d1uux, d1uuy, d1uuz, d1vvx, d1vvy, d1vvz, d1uvx, d1uvy,
684    // d1uvz, d2uux, ...].
685    inline void getSecondDerivative(const int dim,
686                                    const int tag,
687                                    const std::vector<double> & parametricCoord,
688                                    std::vector<double> & derivatives)
689    {
690      int ierr = 0;
691      double *api_parametricCoord_; size_t api_parametricCoord_n_; vector2ptr(parametricCoord, &api_parametricCoord_, &api_parametricCoord_n_);
692      double *api_derivatives_; size_t api_derivatives_n_;
693      gmshModelGetSecondDerivative(dim, tag, api_parametricCoord_, api_parametricCoord_n_, &api_derivatives_, &api_derivatives_n_, &ierr);
694      if(ierr) throwLastError();
695      gmshFree(api_parametricCoord_);
696      derivatives.assign(api_derivatives_, api_derivatives_ + api_derivatives_n_); gmshFree(api_derivatives_);
697    }
698
699    // Evaluate the (maximum) curvature of the entity of dimension `dim' and tag
700    // `tag' at the parametric coordinates `parametricCoord'. Only valid for `dim'
701    // equal to 1 (with `parametricCoord' containing parametric coordinates on the
702    // curve) or 2 (with `parametricCoord' containing pairs of u, v parametric
703    // coordinates on the surface, concatenated: [p1u, p1v, p2u, ...]).
704    inline void getCurvature(const int dim,
705                             const int tag,
706                             const std::vector<double> & parametricCoord,
707                             std::vector<double> & curvatures)
708    {
709      int ierr = 0;
710      double *api_parametricCoord_; size_t api_parametricCoord_n_; vector2ptr(parametricCoord, &api_parametricCoord_, &api_parametricCoord_n_);
711      double *api_curvatures_; size_t api_curvatures_n_;
712      gmshModelGetCurvature(dim, tag, api_parametricCoord_, api_parametricCoord_n_, &api_curvatures_, &api_curvatures_n_, &ierr);
713      if(ierr) throwLastError();
714      gmshFree(api_parametricCoord_);
715      curvatures.assign(api_curvatures_, api_curvatures_ + api_curvatures_n_); gmshFree(api_curvatures_);
716    }
717
718    // Evaluate the principal curvatures of the surface with tag `tag' at the
719    // parametric coordinates `parametricCoord', as well as their respective
720    // directions. `parametricCoord' are given by pair of u and v coordinates,
721    // concatenated: [p1u, p1v, p2u, ...].
722    inline void getPrincipalCurvatures(const int tag,
723                                       const std::vector<double> & parametricCoord,
724                                       std::vector<double> & curvatureMax,
725                                       std::vector<double> & curvatureMin,
726                                       std::vector<double> & directionMax,
727                                       std::vector<double> & directionMin)
728    {
729      int ierr = 0;
730      double *api_parametricCoord_; size_t api_parametricCoord_n_; vector2ptr(parametricCoord, &api_parametricCoord_, &api_parametricCoord_n_);
731      double *api_curvatureMax_; size_t api_curvatureMax_n_;
732      double *api_curvatureMin_; size_t api_curvatureMin_n_;
733      double *api_directionMax_; size_t api_directionMax_n_;
734      double *api_directionMin_; size_t api_directionMin_n_;
735      gmshModelGetPrincipalCurvatures(tag, api_parametricCoord_, api_parametricCoord_n_, &api_curvatureMax_, &api_curvatureMax_n_, &api_curvatureMin_, &api_curvatureMin_n_, &api_directionMax_, &api_directionMax_n_, &api_directionMin_, &api_directionMin_n_, &ierr);
736      if(ierr) throwLastError();
737      gmshFree(api_parametricCoord_);
738      curvatureMax.assign(api_curvatureMax_, api_curvatureMax_ + api_curvatureMax_n_); gmshFree(api_curvatureMax_);
739      curvatureMin.assign(api_curvatureMin_, api_curvatureMin_ + api_curvatureMin_n_); gmshFree(api_curvatureMin_);
740      directionMax.assign(api_directionMax_, api_directionMax_ + api_directionMax_n_); gmshFree(api_directionMax_);
741      directionMin.assign(api_directionMin_, api_directionMin_ + api_directionMin_n_); gmshFree(api_directionMin_);
742    }
743
744    // Get the normal to the surface with tag `tag' at the parametric coordinates
745    // `parametricCoord'. `parametricCoord' are given by pairs of u and v
746    // coordinates, concatenated: [p1u, p1v, p2u, ...]. `normals' are returned as
747    // triplets of x, y, z components, concatenated: [n1x, n1y, n1z, n2x, ...].
748    inline void getNormal(const int tag,
749                          const std::vector<double> & parametricCoord,
750                          std::vector<double> & normals)
751    {
752      int ierr = 0;
753      double *api_parametricCoord_; size_t api_parametricCoord_n_; vector2ptr(parametricCoord, &api_parametricCoord_, &api_parametricCoord_n_);
754      double *api_normals_; size_t api_normals_n_;
755      gmshModelGetNormal(tag, api_parametricCoord_, api_parametricCoord_n_, &api_normals_, &api_normals_n_, &ierr);
756      if(ierr) throwLastError();
757      gmshFree(api_parametricCoord_);
758      normals.assign(api_normals_, api_normals_ + api_normals_n_); gmshFree(api_normals_);
759    }
760
761    // Get the parametric coordinates `parametricCoord' for the points `coord' on
762    // the entity of dimension `dim' and tag `tag'. `coord' are given as triplets
763    // of x, y, z coordinates, concatenated: [p1x, p1y, p1z, p2x, ...].
764    // `parametricCoord' returns the parametric coordinates t on the curve (if
765    // `dim' = 1) or pairs of u and v coordinates concatenated on the surface (if
766    // `dim' = 2), i.e. [p1t, p2t, ...] or [p1u, p1v, p2u, ...].
767    inline void getParametrization(const int dim,
768                                   const int tag,
769                                   const std::vector<double> & coord,
770                                   std::vector<double> & parametricCoord)
771    {
772      int ierr = 0;
773      double *api_coord_; size_t api_coord_n_; vector2ptr(coord, &api_coord_, &api_coord_n_);
774      double *api_parametricCoord_; size_t api_parametricCoord_n_;
775      gmshModelGetParametrization(dim, tag, api_coord_, api_coord_n_, &api_parametricCoord_, &api_parametricCoord_n_, &ierr);
776      if(ierr) throwLastError();
777      gmshFree(api_coord_);
778      parametricCoord.assign(api_parametricCoord_, api_parametricCoord_ + api_parametricCoord_n_); gmshFree(api_parametricCoord_);
779    }
780
781    // Get the `min' and `max' bounds of the parametric coordinates for the entity
782    // of dimension `dim' and tag `tag'.
783    inline void getParametrizationBounds(const int dim,
784                                         const int tag,
785                                         std::vector<double> & min,
786                                         std::vector<double> & max)
787    {
788      int ierr = 0;
789      double *api_min_; size_t api_min_n_;
790      double *api_max_; size_t api_max_n_;
791      gmshModelGetParametrizationBounds(dim, tag, &api_min_, &api_min_n_, &api_max_, &api_max_n_, &ierr);
792      if(ierr) throwLastError();
793      min.assign(api_min_, api_min_ + api_min_n_); gmshFree(api_min_);
794      max.assign(api_max_, api_max_ + api_max_n_); gmshFree(api_max_);
795    }
796
797    // Check if the coordinates (or the parametric coordinates if `parametric' is
798    // set) provided in `coord' correspond to points inside the entity of dimension
799    // `dim' and tag `tag', and return the number of points inside. This feature is
800    // only available for a subset of entities, depending on the underyling
801    // geometrical representation.
802    inline int isInside(const int dim,
803                        const int tag,
804                        const std::vector<double> & coord,
805                        const bool parametric = false)
806    {
807      int ierr = 0;
808      double *api_coord_; size_t api_coord_n_; vector2ptr(coord, &api_coord_, &api_coord_n_);
809      int result_api_ = gmshModelIsInside(dim, tag, api_coord_, api_coord_n_, (int)parametric, &ierr);
810      if(ierr) throwLastError();
811      gmshFree(api_coord_);
812      return result_api_;
813    }
814
815    // Get the points `closestCoord' on the entity of dimension `dim' and tag `tag'
816    // to the points `coord', by orthogonal projection. `coord' and `closestCoord'
817    // are given as triplets of x, y, z coordinates, concatenated: [p1x, p1y, p1z,
818    // p2x, ...]. `parametricCoord' returns the parametric coordinates t on the
819    // curve (if `dim' = 1) or pairs of u and v coordinates concatenated on the
820    // surface (if `dim' = 2), i.e. [p1t, p2t, ...] or [p1u, p1v, p2u, ...].
821    inline void getClosestPoint(const int dim,
822                                const int tag,
823                                const std::vector<double> & coord,
824                                std::vector<double> & closestCoord,
825                                std::vector<double> & parametricCoord)
826    {
827      int ierr = 0;
828      double *api_coord_; size_t api_coord_n_; vector2ptr(coord, &api_coord_, &api_coord_n_);
829      double *api_closestCoord_; size_t api_closestCoord_n_;
830      double *api_parametricCoord_; size_t api_parametricCoord_n_;
831      gmshModelGetClosestPoint(dim, tag, api_coord_, api_coord_n_, &api_closestCoord_, &api_closestCoord_n_, &api_parametricCoord_, &api_parametricCoord_n_, &ierr);
832      if(ierr) throwLastError();
833      gmshFree(api_coord_);
834      closestCoord.assign(api_closestCoord_, api_closestCoord_ + api_closestCoord_n_); gmshFree(api_closestCoord_);
835      parametricCoord.assign(api_parametricCoord_, api_parametricCoord_ + api_parametricCoord_n_); gmshFree(api_parametricCoord_);
836    }
837
838    // Reparametrize the boundary entity (point or curve, i.e. with `dim' == 0 or
839    // `dim' == 1) of tag `tag' on the surface `surfaceTag'. If `dim' == 1,
840    // reparametrize all the points corresponding to the parametric coordinates
841    // `parametricCoord'. Multiple matches in case of periodic surfaces can be
842    // selected with `which'. This feature is only available for a subset of
843    // entities, depending on the underyling geometrical representation.
844    inline void reparametrizeOnSurface(const int dim,
845                                       const int tag,
846                                       const std::vector<double> & parametricCoord,
847                                       const int surfaceTag,
848                                       std::vector<double> & surfaceParametricCoord,
849                                       const int which = 0)
850    {
851      int ierr = 0;
852      double *api_parametricCoord_; size_t api_parametricCoord_n_; vector2ptr(parametricCoord, &api_parametricCoord_, &api_parametricCoord_n_);
853      double *api_surfaceParametricCoord_; size_t api_surfaceParametricCoord_n_;
854      gmshModelReparametrizeOnSurface(dim, tag, api_parametricCoord_, api_parametricCoord_n_, surfaceTag, &api_surfaceParametricCoord_, &api_surfaceParametricCoord_n_, which, &ierr);
855      if(ierr) throwLastError();
856      gmshFree(api_parametricCoord_);
857      surfaceParametricCoord.assign(api_surfaceParametricCoord_, api_surfaceParametricCoord_ + api_surfaceParametricCoord_n_); gmshFree(api_surfaceParametricCoord_);
858    }
859
860    // Set the visibility of the model entities `dimTags' to `value'. Apply the
861    // visibility setting recursively if `recursive' is true.
862    inline void setVisibility(const gmsh::vectorpair & dimTags,
863                              const int value,
864                              const bool recursive = false)
865    {
866      int ierr = 0;
867      int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
868      gmshModelSetVisibility(api_dimTags_, api_dimTags_n_, value, (int)recursive, &ierr);
869      if(ierr) throwLastError();
870      gmshFree(api_dimTags_);
871    }
872
873    // Get the visibility of the model entity of dimension `dim' and tag `tag'.
874    inline void getVisibility(const int dim,
875                              const int tag,
876                              int & value)
877    {
878      int ierr = 0;
879      gmshModelGetVisibility(dim, tag, &value, &ierr);
880      if(ierr) throwLastError();
881    }
882
883    // Set the global visibility of the model per window to `value', where
884    // `windowIndex' identifies the window in the window list.
885    inline void setVisibilityPerWindow(const int value,
886                                       const int windowIndex = 0)
887    {
888      int ierr = 0;
889      gmshModelSetVisibilityPerWindow(value, windowIndex, &ierr);
890      if(ierr) throwLastError();
891    }
892
893    // Set the color of the model entities `dimTags' to the RGBA value (`r', `g',
894    // `b', `a'), where `r', `g', `b' and `a' should be integers between 0 and 255.
895    // Apply the color setting recursively if `recursive' is true.
896    inline void setColor(const gmsh::vectorpair & dimTags,
897                         const int r,
898                         const int g,
899                         const int b,
900                         const int a = 255,
901                         const bool recursive = false)
902    {
903      int ierr = 0;
904      int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
905      gmshModelSetColor(api_dimTags_, api_dimTags_n_, r, g, b, a, (int)recursive, &ierr);
906      if(ierr) throwLastError();
907      gmshFree(api_dimTags_);
908    }
909
910    // Get the color of the model entity of dimension `dim' and tag `tag'.
911    inline void getColor(const int dim,
912                         const int tag,
913                         int & r,
914                         int & g,
915                         int & b,
916                         int & a)
917    {
918      int ierr = 0;
919      gmshModelGetColor(dim, tag, &r, &g, &b, &a, &ierr);
920      if(ierr) throwLastError();
921    }
922
923    // Set the `x', `y', `z' coordinates of a geometrical point.
924    inline void setCoordinates(const int tag,
925                               const double x,
926                               const double y,
927                               const double z)
928    {
929      int ierr = 0;
930      gmshModelSetCoordinates(tag, x, y, z, &ierr);
931      if(ierr) throwLastError();
932    }
933
934    namespace mesh { // Mesh functions
935
936      // Generate a mesh of the current model, up to dimension `dim' (0, 1, 2 or
937      // 3).
938      inline void generate(const int dim = 3)
939      {
940        int ierr = 0;
941        gmshModelMeshGenerate(dim, &ierr);
942        if(ierr) throwLastError();
943      }
944
945      // Partition the mesh of the current model into `numPart' partitions.
946      // Optionally, `elementTags' and `partitions' can be provided to specify the
947      // partition of each element explicitly.
948      inline void partition(const int numPart,
949                            const std::vector<std::size_t> & elementTags = std::vector<std::size_t>(),
950                            const std::vector<int> & partitions = std::vector<int>())
951      {
952        int ierr = 0;
953        size_t *api_elementTags_; size_t api_elementTags_n_; vector2ptr(elementTags, &api_elementTags_, &api_elementTags_n_);
954        int *api_partitions_; size_t api_partitions_n_; vector2ptr(partitions, &api_partitions_, &api_partitions_n_);
955        gmshModelMeshPartition(numPart, api_elementTags_, api_elementTags_n_, api_partitions_, api_partitions_n_, &ierr);
956        if(ierr) throwLastError();
957        gmshFree(api_elementTags_);
958        gmshFree(api_partitions_);
959      }
960
961      // Unpartition the mesh of the current model.
962      inline void unpartition()
963      {
964        int ierr = 0;
965        gmshModelMeshUnpartition(&ierr);
966        if(ierr) throwLastError();
967      }
968
969      // Optimize the mesh of the current model using `method' (empty for default
970      // tetrahedral mesh optimizer, "Netgen" for Netgen optimizer, "HighOrder" for
971      // direct high-order mesh optimizer, "HighOrderElastic" for high-order
972      // elastic smoother, "HighOrderFastCurving" for fast curving algorithm,
973      // "Laplace2D" for Laplace smoothing, "Relocate2D" and "Relocate3D" for node
974      // relocation). If `force' is set apply the optimization also to discrete
975      // entities. If `dimTags' is given, only apply the optimizer to the given
976      // entities.
977      inline void optimize(const std::string & method,
978                           const bool force = false,
979                           const int niter = 1,
980                           const gmsh::vectorpair & dimTags = gmsh::vectorpair())
981      {
982        int ierr = 0;
983        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
984        gmshModelMeshOptimize(method.c_str(), (int)force, niter, api_dimTags_, api_dimTags_n_, &ierr);
985        if(ierr) throwLastError();
986        gmshFree(api_dimTags_);
987      }
988
989      // Recombine the mesh of the current model.
990      inline void recombine()
991      {
992        int ierr = 0;
993        gmshModelMeshRecombine(&ierr);
994        if(ierr) throwLastError();
995      }
996
997      // Refine the mesh of the current model by uniformly splitting the elements.
998      inline void refine()
999      {
1000        int ierr = 0;
1001        gmshModelMeshRefine(&ierr);
1002        if(ierr) throwLastError();
1003      }
1004
1005      // Set the order of the elements in the mesh of the current model to `order'.
1006      inline void setOrder(const int order)
1007      {
1008        int ierr = 0;
1009        gmshModelMeshSetOrder(order, &ierr);
1010        if(ierr) throwLastError();
1011      }
1012
1013      // Get the last entities (if any) where a meshing error occurred. Currently
1014      // only populated by the new 3D meshing algorithms.
1015      inline void getLastEntityError(gmsh::vectorpair & dimTags)
1016      {
1017        int ierr = 0;
1018        int *api_dimTags_; size_t api_dimTags_n_;
1019        gmshModelMeshGetLastEntityError(&api_dimTags_, &api_dimTags_n_, &ierr);
1020        if(ierr) throwLastError();
1021        dimTags.resize(api_dimTags_n_ / 2); for(size_t i = 0; i < api_dimTags_n_ / 2; ++i){ dimTags[i].first = api_dimTags_[i * 2 + 0]; dimTags[i].second = api_dimTags_[i * 2 + 1]; } gmshFree(api_dimTags_);
1022      }
1023
1024      // Get the last nodes (if any) where a meshing error occurred. Currently only
1025      // populated by the new 3D meshing algorithms.
1026      inline void getLastNodeError(std::vector<std::size_t> & nodeTags)
1027      {
1028        int ierr = 0;
1029        size_t *api_nodeTags_; size_t api_nodeTags_n_;
1030        gmshModelMeshGetLastNodeError(&api_nodeTags_, &api_nodeTags_n_, &ierr);
1031        if(ierr) throwLastError();
1032        nodeTags.assign(api_nodeTags_, api_nodeTags_ + api_nodeTags_n_); gmshFree(api_nodeTags_);
1033      }
1034
1035      // Clear the mesh, i.e. delete all the nodes and elements, for the entities
1036      // `dimTags'. If `dimTags' is empty, clear the whole mesh. Note that the mesh
1037      // of an entity can only be cleared if this entity is not on the boundary of
1038      // another entity with a non-empty mesh.
1039      inline void clear(const gmsh::vectorpair & dimTags = gmsh::vectorpair())
1040      {
1041        int ierr = 0;
1042        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
1043        gmshModelMeshClear(api_dimTags_, api_dimTags_n_, &ierr);
1044        if(ierr) throwLastError();
1045        gmshFree(api_dimTags_);
1046      }
1047
1048      // Reverse the orientation of the elements in the entities `dimTags'. If
1049      // `dimTags' is empty, reverse the orientation of the elements in the whole
1050      // mesh.
1051      inline void reverse(const gmsh::vectorpair & dimTags = gmsh::vectorpair())
1052      {
1053        int ierr = 0;
1054        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
1055        gmshModelMeshReverse(api_dimTags_, api_dimTags_n_, &ierr);
1056        if(ierr) throwLastError();
1057        gmshFree(api_dimTags_);
1058      }
1059
1060      // Apply the affine transformation `affineTransform' (16 entries of a 4x4
1061      // matrix, by row; only the 12 first can be provided for convenience) to the
1062      // coordinates of the nodes classified on the entities `dimTags'. If
1063      // `dimTags' is empty, transform all the nodes in the mesh.
1064      inline void affineTransform(const std::vector<double> & affineTransform,
1065                                  const gmsh::vectorpair & dimTags = gmsh::vectorpair())
1066      {
1067        int ierr = 0;
1068        double *api_affineTransform_; size_t api_affineTransform_n_; vector2ptr(affineTransform, &api_affineTransform_, &api_affineTransform_n_);
1069        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
1070        gmshModelMeshAffineTransform(api_affineTransform_, api_affineTransform_n_, api_dimTags_, api_dimTags_n_, &ierr);
1071        if(ierr) throwLastError();
1072        gmshFree(api_affineTransform_);
1073        gmshFree(api_dimTags_);
1074      }
1075
1076      // Get the nodes classified on the entity of dimension `dim' and tag `tag'.
1077      // If `tag' < 0, get the nodes for all entities of dimension `dim'. If `dim'
1078      // and `tag' are negative, get all the nodes in the mesh. `nodeTags' contains
1079      // the node tags (their unique, strictly positive identification numbers).
1080      // `coord' is a vector of length 3 times the length of `nodeTags' that
1081      // contains the x, y, z coordinates of the nodes, concatenated: [n1x, n1y,
1082      // n1z, n2x, ...]. If `dim' >= 0 and `returnParamtricCoord' is set,
1083      // `parametricCoord' contains the parametric coordinates ([u1, u2, ...] or
1084      // [u1, v1, u2, ...]) of the nodes, if available. The length of
1085      // `parametricCoord' can be 0 or `dim' times the length of `nodeTags'. If
1086      // `includeBoundary' is set, also return the nodes classified on the boundary
1087      // of the entity (which will be reparametrized on the entity if `dim' >= 0 in
1088      // order to compute their parametric coordinates).
1089      inline void getNodes(std::vector<std::size_t> & nodeTags,
1090                           std::vector<double> & coord,
1091                           std::vector<double> & parametricCoord,
1092                           const int dim = -1,
1093                           const int tag = -1,
1094                           const bool includeBoundary = false,
1095                           const bool returnParametricCoord = true)
1096      {
1097        int ierr = 0;
1098        size_t *api_nodeTags_; size_t api_nodeTags_n_;
1099        double *api_coord_; size_t api_coord_n_;
1100        double *api_parametricCoord_; size_t api_parametricCoord_n_;
1101        gmshModelMeshGetNodes(&api_nodeTags_, &api_nodeTags_n_, &api_coord_, &api_coord_n_, &api_parametricCoord_, &api_parametricCoord_n_, dim, tag, (int)includeBoundary, (int)returnParametricCoord, &ierr);
1102        if(ierr) throwLastError();
1103        nodeTags.assign(api_nodeTags_, api_nodeTags_ + api_nodeTags_n_); gmshFree(api_nodeTags_);
1104        coord.assign(api_coord_, api_coord_ + api_coord_n_); gmshFree(api_coord_);
1105        parametricCoord.assign(api_parametricCoord_, api_parametricCoord_ + api_parametricCoord_n_); gmshFree(api_parametricCoord_);
1106      }
1107
1108      // Get the nodes classified on the entity of tag `tag', for all the elements
1109      // of type `elementType'. The other arguments are treated as in `getNodes'.
1110      inline void getNodesByElementType(const int elementType,
1111                                        std::vector<std::size_t> & nodeTags,
1112                                        std::vector<double> & coord,
1113                                        std::vector<double> & parametricCoord,
1114                                        const int tag = -1,
1115                                        const bool returnParametricCoord = true)
1116      {
1117        int ierr = 0;
1118        size_t *api_nodeTags_; size_t api_nodeTags_n_;
1119        double *api_coord_; size_t api_coord_n_;
1120        double *api_parametricCoord_; size_t api_parametricCoord_n_;
1121        gmshModelMeshGetNodesByElementType(elementType, &api_nodeTags_, &api_nodeTags_n_, &api_coord_, &api_coord_n_, &api_parametricCoord_, &api_parametricCoord_n_, tag, (int)returnParametricCoord, &ierr);
1122        if(ierr) throwLastError();
1123        nodeTags.assign(api_nodeTags_, api_nodeTags_ + api_nodeTags_n_); gmshFree(api_nodeTags_);
1124        coord.assign(api_coord_, api_coord_ + api_coord_n_); gmshFree(api_coord_);
1125        parametricCoord.assign(api_parametricCoord_, api_parametricCoord_ + api_parametricCoord_n_); gmshFree(api_parametricCoord_);
1126      }
1127
1128      // Get the coordinates and the parametric coordinates (if any) of the node
1129      // with tag `tag', as well as the dimension `dim' and tag `tag' of the entity
1130      // on which the node is classified. This function relies on an internal cache
1131      // (a vector in case of dense node numbering, a map otherwise); for large
1132      // meshes accessing nodes in bulk is often preferable.
1133      inline void getNode(const std::size_t nodeTag,
1134                          std::vector<double> & coord,
1135                          std::vector<double> & parametricCoord,
1136                          int & dim,
1137                          int & tag)
1138      {
1139        int ierr = 0;
1140        double *api_coord_; size_t api_coord_n_;
1141        double *api_parametricCoord_; size_t api_parametricCoord_n_;
1142        gmshModelMeshGetNode(nodeTag, &api_coord_, &api_coord_n_, &api_parametricCoord_, &api_parametricCoord_n_, &dim, &tag, &ierr);
1143        if(ierr) throwLastError();
1144        coord.assign(api_coord_, api_coord_ + api_coord_n_); gmshFree(api_coord_);
1145        parametricCoord.assign(api_parametricCoord_, api_parametricCoord_ + api_parametricCoord_n_); gmshFree(api_parametricCoord_);
1146      }
1147
1148      // Set the coordinates and the parametric coordinates (if any) of the node
1149      // with tag `tag'. This function relies on an internal cache (a vector in
1150      // case of dense node numbering, a map otherwise); for large meshes accessing
1151      // nodes in bulk is often preferable.
1152      inline void setNode(const std::size_t nodeTag,
1153                          const std::vector<double> & coord,
1154                          const std::vector<double> & parametricCoord)
1155      {
1156        int ierr = 0;
1157        double *api_coord_; size_t api_coord_n_; vector2ptr(coord, &api_coord_, &api_coord_n_);
1158        double *api_parametricCoord_; size_t api_parametricCoord_n_; vector2ptr(parametricCoord, &api_parametricCoord_, &api_parametricCoord_n_);
1159        gmshModelMeshSetNode(nodeTag, api_coord_, api_coord_n_, api_parametricCoord_, api_parametricCoord_n_, &ierr);
1160        if(ierr) throwLastError();
1161        gmshFree(api_coord_);
1162        gmshFree(api_parametricCoord_);
1163      }
1164
1165      // Rebuild the node cache.
1166      inline void rebuildNodeCache(const bool onlyIfNecessary = true)
1167      {
1168        int ierr = 0;
1169        gmshModelMeshRebuildNodeCache((int)onlyIfNecessary, &ierr);
1170        if(ierr) throwLastError();
1171      }
1172
1173      // Rebuild the element cache.
1174      inline void rebuildElementCache(const bool onlyIfNecessary = true)
1175      {
1176        int ierr = 0;
1177        gmshModelMeshRebuildElementCache((int)onlyIfNecessary, &ierr);
1178        if(ierr) throwLastError();
1179      }
1180
1181      // Get the nodes from all the elements belonging to the physical group of
1182      // dimension `dim' and tag `tag'. `nodeTags' contains the node tags; `coord'
1183      // is a vector of length 3 times the length of `nodeTags' that contains the
1184      // x, y, z coordinates of the nodes, concatenated: [n1x, n1y, n1z, n2x, ...].
1185      inline void getNodesForPhysicalGroup(const int dim,
1186                                           const int tag,
1187                                           std::vector<std::size_t> & nodeTags,
1188                                           std::vector<double> & coord)
1189      {
1190        int ierr = 0;
1191        size_t *api_nodeTags_; size_t api_nodeTags_n_;
1192        double *api_coord_; size_t api_coord_n_;
1193        gmshModelMeshGetNodesForPhysicalGroup(dim, tag, &api_nodeTags_, &api_nodeTags_n_, &api_coord_, &api_coord_n_, &ierr);
1194        if(ierr) throwLastError();
1195        nodeTags.assign(api_nodeTags_, api_nodeTags_ + api_nodeTags_n_); gmshFree(api_nodeTags_);
1196        coord.assign(api_coord_, api_coord_ + api_coord_n_); gmshFree(api_coord_);
1197      }
1198
1199      // Get the maximum tag `maxTag' of a node in the mesh.
1200      inline void getMaxNodeTag(std::size_t & maxTag)
1201      {
1202        int ierr = 0;
1203        gmshModelMeshGetMaxNodeTag(&maxTag, &ierr);
1204        if(ierr) throwLastError();
1205      }
1206
1207      // Add nodes classified on the model entity of dimension `dim' and tag `tag'.
1208      // `nodeTags' contains the node tags (their unique, strictly positive
1209      // identification numbers). `coord' is a vector of length 3 times the length
1210      // of `nodeTags' that contains the x, y, z coordinates of the nodes,
1211      // concatenated: [n1x, n1y, n1z, n2x, ...]. The optional `parametricCoord'
1212      // vector contains the parametric coordinates of the nodes, if any. The
1213      // length of `parametricCoord' can be 0 or `dim' times the length of
1214      // `nodeTags'. If the `nodeTags' vector is empty, new tags are automatically
1215      // assigned to the nodes.
1216      inline void addNodes(const int dim,
1217                           const int tag,
1218                           const std::vector<std::size_t> & nodeTags,
1219                           const std::vector<double> & coord,
1220                           const std::vector<double> & parametricCoord = std::vector<double>())
1221      {
1222        int ierr = 0;
1223        size_t *api_nodeTags_; size_t api_nodeTags_n_; vector2ptr(nodeTags, &api_nodeTags_, &api_nodeTags_n_);
1224        double *api_coord_; size_t api_coord_n_; vector2ptr(coord, &api_coord_, &api_coord_n_);
1225        double *api_parametricCoord_; size_t api_parametricCoord_n_; vector2ptr(parametricCoord, &api_parametricCoord_, &api_parametricCoord_n_);
1226        gmshModelMeshAddNodes(dim, tag, api_nodeTags_, api_nodeTags_n_, api_coord_, api_coord_n_, api_parametricCoord_, api_parametricCoord_n_, &ierr);
1227        if(ierr) throwLastError();
1228        gmshFree(api_nodeTags_);
1229        gmshFree(api_coord_);
1230        gmshFree(api_parametricCoord_);
1231      }
1232
1233      // Reclassify all nodes on their associated model entity, based on the
1234      // elements. Can be used when importing nodes in bulk (e.g. by associating
1235      // them all to a single volume), to reclassify them correctly on model
1236      // surfaces, curves, etc. after the elements have been set.
1237      inline void reclassifyNodes()
1238      {
1239        int ierr = 0;
1240        gmshModelMeshReclassifyNodes(&ierr);
1241        if(ierr) throwLastError();
1242      }
1243
1244      // Relocate the nodes classified on the entity of dimension `dim' and tag
1245      // `tag' using their parametric coordinates. If `tag' < 0, relocate the nodes
1246      // for all entities of dimension `dim'. If `dim' and `tag' are negative,
1247      // relocate all the nodes in the mesh.
1248      inline void relocateNodes(const int dim = -1,
1249                                const int tag = -1)
1250      {
1251        int ierr = 0;
1252        gmshModelMeshRelocateNodes(dim, tag, &ierr);
1253        if(ierr) throwLastError();
1254      }
1255
1256      // Get the elements classified on the entity of dimension `dim' and tag
1257      // `tag'. If `tag' < 0, get the elements for all entities of dimension `dim'.
1258      // If `dim' and `tag' are negative, get all the elements in the mesh.
1259      // `elementTypes' contains the MSH types of the elements (e.g. `2' for 3-node
1260      // triangles: see `getElementProperties' to obtain the properties for a given
1261      // element type). `elementTags' is a vector of the same length as
1262      // `elementTypes'; each entry is a vector containing the tags (unique,
1263      // strictly positive identifiers) of the elements of the corresponding type.
1264      // `nodeTags' is also a vector of the same length as `elementTypes'; each
1265      // entry is a vector of length equal to the number of elements of the given
1266      // type times the number N of nodes for this type of element, that contains
1267      // the node tags of all the elements of the given type, concatenated: [e1n1,
1268      // e1n2, ..., e1nN, e2n1, ...].
1269      inline void getElements(std::vector<int> & elementTypes,
1270                              std::vector<std::vector<std::size_t> > & elementTags,
1271                              std::vector<std::vector<std::size_t> > & nodeTags,
1272                              const int dim = -1,
1273                              const int tag = -1)
1274      {
1275        int ierr = 0;
1276        int *api_elementTypes_; size_t api_elementTypes_n_;
1277        size_t **api_elementTags_; size_t *api_elementTags_n_, api_elementTags_nn_;
1278        size_t **api_nodeTags_; size_t *api_nodeTags_n_, api_nodeTags_nn_;
1279        gmshModelMeshGetElements(&api_elementTypes_, &api_elementTypes_n_, &api_elementTags_, &api_elementTags_n_, &api_elementTags_nn_, &api_nodeTags_, &api_nodeTags_n_, &api_nodeTags_nn_, dim, tag, &ierr);
1280        if(ierr) throwLastError();
1281        elementTypes.assign(api_elementTypes_, api_elementTypes_ + api_elementTypes_n_); gmshFree(api_elementTypes_);
1282        elementTags.resize(api_elementTags_nn_); for(size_t i = 0; i < api_elementTags_nn_; ++i){ elementTags[i].assign(api_elementTags_[i], api_elementTags_[i] + api_elementTags_n_[i]); gmshFree(api_elementTags_[i]); } gmshFree(api_elementTags_); gmshFree(api_elementTags_n_);
1283        nodeTags.resize(api_nodeTags_nn_); for(size_t i = 0; i < api_nodeTags_nn_; ++i){ nodeTags[i].assign(api_nodeTags_[i], api_nodeTags_[i] + api_nodeTags_n_[i]); gmshFree(api_nodeTags_[i]); } gmshFree(api_nodeTags_); gmshFree(api_nodeTags_n_);
1284      }
1285
1286      // Get the type and node tags of the element with tag `tag', as well as the
1287      // dimension `dim' and tag `tag' of the entity on which the element is
1288      // classified. This function relies on an internal cache (a vector in case of
1289      // dense element numbering, a map otherwise); for large meshes accessing
1290      // elements in bulk is often preferable.
1291      inline void getElement(const std::size_t elementTag,
1292                             int & elementType,
1293                             std::vector<std::size_t> & nodeTags,
1294                             int & dim,
1295                             int & tag)
1296      {
1297        int ierr = 0;
1298        size_t *api_nodeTags_; size_t api_nodeTags_n_;
1299        gmshModelMeshGetElement(elementTag, &elementType, &api_nodeTags_, &api_nodeTags_n_, &dim, &tag, &ierr);
1300        if(ierr) throwLastError();
1301        nodeTags.assign(api_nodeTags_, api_nodeTags_ + api_nodeTags_n_); gmshFree(api_nodeTags_);
1302      }
1303
1304      // Search the mesh for an element located at coordinates (`x', `y', `z').
1305      // This function performs a search in a spatial octree. If an element is
1306      // found, return its tag, type and node tags, as well as the local
1307      // coordinates (`u', `v', `w') within the reference element corresponding to
1308      // search location. If `dim' is >= 0, only search for elements of the given
1309      // dimension. If `strict' is not set, use a tolerance to find elements near
1310      // the search location.
1311      inline void getElementByCoordinates(const double x,
1312                                          const double y,
1313                                          const double z,
1314                                          std::size_t & elementTag,
1315                                          int & elementType,
1316                                          std::vector<std::size_t> & nodeTags,
1317                                          double & u,
1318                                          double & v,
1319                                          double & w,
1320                                          const int dim = -1,
1321                                          const bool strict = false)
1322      {
1323        int ierr = 0;
1324        size_t *api_nodeTags_; size_t api_nodeTags_n_;
1325        gmshModelMeshGetElementByCoordinates(x, y, z, &elementTag, &elementType, &api_nodeTags_, &api_nodeTags_n_, &u, &v, &w, dim, (int)strict, &ierr);
1326        if(ierr) throwLastError();
1327        nodeTags.assign(api_nodeTags_, api_nodeTags_ + api_nodeTags_n_); gmshFree(api_nodeTags_);
1328      }
1329
1330      // Search the mesh for element(s) located at coordinates (`x', `y', `z').
1331      // This function performs a search in a spatial octree. Return the tags of
1332      // all found elements in `elementTags'. Additional information about the
1333      // elements can be accessed through `getElement' and
1334      // `getLocalCoordinatesInElement'. If `dim' is >= 0, only search for elements
1335      // of the given dimension. If `strict' is not set, use a tolerance to find
1336      // elements near the search location.
1337      inline void getElementsByCoordinates(const double x,
1338                                           const double y,
1339                                           const double z,
1340                                           std::vector<std::size_t> & elementTags,
1341                                           const int dim = -1,
1342                                           const bool strict = false)
1343      {
1344        int ierr = 0;
1345        size_t *api_elementTags_; size_t api_elementTags_n_;
1346        gmshModelMeshGetElementsByCoordinates(x, y, z, &api_elementTags_, &api_elementTags_n_, dim, (int)strict, &ierr);
1347        if(ierr) throwLastError();
1348        elementTags.assign(api_elementTags_, api_elementTags_ + api_elementTags_n_); gmshFree(api_elementTags_);
1349      }
1350
1351      // Return the local coordinates (`u', `v', `w') within the element
1352      // `elementTag' corresponding to the model coordinates (`x', `y', `z'). This
1353      // function relies on an internal cache (a vector in case of dense element
1354      // numbering, a map otherwise); for large meshes accessing elements in bulk
1355      // is often preferable.
1356      inline void getLocalCoordinatesInElement(const std::size_t elementTag,
1357                                               const double x,
1358                                               const double y,
1359                                               const double z,
1360                                               double & u,
1361                                               double & v,
1362                                               double & w)
1363      {
1364        int ierr = 0;
1365        gmshModelMeshGetLocalCoordinatesInElement(elementTag, x, y, z, &u, &v, &w, &ierr);
1366        if(ierr) throwLastError();
1367      }
1368
1369      // Get the types of elements in the entity of dimension `dim' and tag `tag'.
1370      // If `tag' < 0, get the types for all entities of dimension `dim'. If `dim'
1371      // and `tag' are negative, get all the types in the mesh.
1372      inline void getElementTypes(std::vector<int> & elementTypes,
1373                                  const int dim = -1,
1374                                  const int tag = -1)
1375      {
1376        int ierr = 0;
1377        int *api_elementTypes_; size_t api_elementTypes_n_;
1378        gmshModelMeshGetElementTypes(&api_elementTypes_, &api_elementTypes_n_, dim, tag, &ierr);
1379        if(ierr) throwLastError();
1380        elementTypes.assign(api_elementTypes_, api_elementTypes_ + api_elementTypes_n_); gmshFree(api_elementTypes_);
1381      }
1382
1383      // Return an element type given its family name `familyName' ("Point",
1384      // "Line", "Triangle", "Quadrangle", "Tetrahedron", "Pyramid", "Prism",
1385      // "Hexahedron") and polynomial order `order'. If `serendip' is true, return
1386      // the corresponding serendip element type (element without interior nodes).
1387      inline int getElementType(const std::string & familyName,
1388                                const int order,
1389                                const bool serendip = false)
1390      {
1391        int ierr = 0;
1392        int result_api_ = gmshModelMeshGetElementType(familyName.c_str(), order, (int)serendip, &ierr);
1393        if(ierr) throwLastError();
1394        return result_api_;
1395      }
1396
1397      // Get the properties of an element of type `elementType': its name
1398      // (`elementName'), dimension (`dim'), order (`order'), number of nodes
1399      // (`numNodes'), local coordinates of the nodes in the reference element
1400      // (`localNodeCoord' vector, of length `dim' times `numNodes') and number of
1401      // primary (first order) nodes (`numPrimaryNodes').
1402      inline void getElementProperties(const int elementType,
1403                                       std::string & elementName,
1404                                       int & dim,
1405                                       int & order,
1406                                       int & numNodes,
1407                                       std::vector<double> & localNodeCoord,
1408                                       int & numPrimaryNodes)
1409      {
1410        int ierr = 0;
1411        char *api_elementName_;
1412        double *api_localNodeCoord_; size_t api_localNodeCoord_n_;
1413        gmshModelMeshGetElementProperties(elementType, &api_elementName_, &dim, &order, &numNodes, &api_localNodeCoord_, &api_localNodeCoord_n_, &numPrimaryNodes, &ierr);
1414        if(ierr) throwLastError();
1415        elementName = std::string(api_elementName_); gmshFree(api_elementName_);
1416        localNodeCoord.assign(api_localNodeCoord_, api_localNodeCoord_ + api_localNodeCoord_n_); gmshFree(api_localNodeCoord_);
1417      }
1418
1419      // Get the elements of type `elementType' classified on the entity of tag
1420      // `tag'. If `tag' < 0, get the elements for all entities. `elementTags' is a
1421      // vector containing the tags (unique, strictly positive identifiers) of the
1422      // elements of the corresponding type. `nodeTags' is a vector of length equal
1423      // to the number of elements of the given type times the number N of nodes
1424      // for this type of element, that contains the node tags of all the elements
1425      // of the given type, concatenated: [e1n1, e1n2, ..., e1nN, e2n1, ...]. If
1426      // `numTasks' > 1, only compute and return the part of the data indexed by
1427      // `task'.
1428      inline void getElementsByType(const int elementType,
1429                                    std::vector<std::size_t> & elementTags,
1430                                    std::vector<std::size_t> & nodeTags,
1431                                    const int tag = -1,
1432                                    const std::size_t task = 0,
1433                                    const std::size_t numTasks = 1)
1434      {
1435        int ierr = 0;
1436        size_t *api_elementTags_; size_t api_elementTags_n_;
1437        size_t *api_nodeTags_; size_t api_nodeTags_n_;
1438        gmshModelMeshGetElementsByType(elementType, &api_elementTags_, &api_elementTags_n_, &api_nodeTags_, &api_nodeTags_n_, tag, task, numTasks, &ierr);
1439        if(ierr) throwLastError();
1440        elementTags.assign(api_elementTags_, api_elementTags_ + api_elementTags_n_); gmshFree(api_elementTags_);
1441        nodeTags.assign(api_nodeTags_, api_nodeTags_ + api_nodeTags_n_); gmshFree(api_nodeTags_);
1442      }
1443
1444      // Get the maximum tag `maxTag' of an element in the mesh.
1445      inline void getMaxElementTag(std::size_t & maxTag)
1446      {
1447        int ierr = 0;
1448        gmshModelMeshGetMaxElementTag(&maxTag, &ierr);
1449        if(ierr) throwLastError();
1450      }
1451
1452      // Preallocate data before calling `getElementsByType' with `numTasks' > 1.
1453      // For C and C++ only.
1454      inline void preallocateElementsByType(const int elementType,
1455                                            const bool elementTag,
1456                                            const bool nodeTag,
1457                                            std::vector<std::size_t> & elementTags,
1458                                            std::vector<std::size_t> & nodeTags,
1459                                            const int tag = -1)
1460      {
1461        int ierr = 0;
1462        size_t *api_elementTags_; size_t api_elementTags_n_;
1463        size_t *api_nodeTags_; size_t api_nodeTags_n_;
1464        gmshModelMeshPreallocateElementsByType(elementType, (int)elementTag, (int)nodeTag, &api_elementTags_, &api_elementTags_n_, &api_nodeTags_, &api_nodeTags_n_, tag, &ierr);
1465        if(ierr) throwLastError();
1466        elementTags.assign(api_elementTags_, api_elementTags_ + api_elementTags_n_); gmshFree(api_elementTags_);
1467        nodeTags.assign(api_nodeTags_, api_nodeTags_ + api_nodeTags_n_); gmshFree(api_nodeTags_);
1468      }
1469
1470      // Add elements classified on the entity of dimension `dim' and tag `tag'.
1471      // `types' contains the MSH types of the elements (e.g. `2' for 3-node
1472      // triangles: see the Gmsh reference manual). `elementTags' is a vector of
1473      // the same length as `types'; each entry is a vector containing the tags
1474      // (unique, strictly positive identifiers) of the elements of the
1475      // corresponding type. `nodeTags' is also a vector of the same length as
1476      // `types'; each entry is a vector of length equal to the number of elements
1477      // of the given type times the number N of nodes per element, that contains
1478      // the node tags of all the elements of the given type, concatenated: [e1n1,
1479      // e1n2, ..., e1nN, e2n1, ...].
1480      inline void addElements(const int dim,
1481                              const int tag,
1482                              const std::vector<int> & elementTypes,
1483                              const std::vector<std::vector<std::size_t> > & elementTags,
1484                              const std::vector<std::vector<std::size_t> > & nodeTags)
1485      {
1486        int ierr = 0;
1487        int *api_elementTypes_; size_t api_elementTypes_n_; vector2ptr(elementTypes, &api_elementTypes_, &api_elementTypes_n_);
1488        size_t **api_elementTags_; size_t *api_elementTags_n_, api_elementTags_nn_; vectorvector2ptrptr(elementTags, &api_elementTags_, &api_elementTags_n_, &api_elementTags_nn_);
1489        size_t **api_nodeTags_; size_t *api_nodeTags_n_, api_nodeTags_nn_; vectorvector2ptrptr(nodeTags, &api_nodeTags_, &api_nodeTags_n_, &api_nodeTags_nn_);
1490        gmshModelMeshAddElements(dim, tag, api_elementTypes_, api_elementTypes_n_, (const size_t **)api_elementTags_, api_elementTags_n_, api_elementTags_nn_, (const size_t **)api_nodeTags_, api_nodeTags_n_, api_nodeTags_nn_, &ierr);
1491        if(ierr) throwLastError();
1492        gmshFree(api_elementTypes_);
1493        for(size_t i = 0; i < api_elementTags_nn_; ++i){ gmshFree(api_elementTags_[i]); } gmshFree(api_elementTags_); gmshFree(api_elementTags_n_);
1494        for(size_t i = 0; i < api_nodeTags_nn_; ++i){ gmshFree(api_nodeTags_[i]); } gmshFree(api_nodeTags_); gmshFree(api_nodeTags_n_);
1495      }
1496
1497      // Add elements of type `elementType' classified on the entity of tag `tag'.
1498      // `elementTags' contains the tags (unique, strictly positive identifiers) of
1499      // the elements of the corresponding type. `nodeTags' is a vector of length
1500      // equal to the number of elements times the number N of nodes per element,
1501      // that contains the node tags of all the elements, concatenated: [e1n1,
1502      // e1n2, ..., e1nN, e2n1, ...]. If the `elementTag' vector is empty, new tags
1503      // are automatically assigned to the elements.
1504      inline void addElementsByType(const int tag,
1505                                    const int elementType,
1506                                    const std::vector<std::size_t> & elementTags,
1507                                    const std::vector<std::size_t> & nodeTags)
1508      {
1509        int ierr = 0;
1510        size_t *api_elementTags_; size_t api_elementTags_n_; vector2ptr(elementTags, &api_elementTags_, &api_elementTags_n_);
1511        size_t *api_nodeTags_; size_t api_nodeTags_n_; vector2ptr(nodeTags, &api_nodeTags_, &api_nodeTags_n_);
1512        gmshModelMeshAddElementsByType(tag, elementType, api_elementTags_, api_elementTags_n_, api_nodeTags_, api_nodeTags_n_, &ierr);
1513        if(ierr) throwLastError();
1514        gmshFree(api_elementTags_);
1515        gmshFree(api_nodeTags_);
1516      }
1517
1518      // Get the numerical quadrature information for the given element type
1519      // `elementType' and integration rule `integrationType', where
1520      // `integrationType' concatenates the integration rule family name with the
1521      // desired order (e.g. "Gauss4" for a quadrature suited for integrating 4th
1522      // order polynomials). The "CompositeGauss" family uses tensor-product rules
1523      // based the 1D Gauss-Legendre rule; the "Gauss" family uses an economic
1524      // scheme when available (i.e. with a minimal number of points), and falls
1525      // back to "CompositeGauss" otherwise. Note that integration points for the
1526      // "Gauss" family can fall outside of the reference element for high-order
1527      // rules. `localCoord' contains the u, v, w coordinates of the G integration
1528      // points in the reference element: [g1u, g1v, g1w, ..., gGu, gGv, gGw].
1529      // `weights' contains the associated weights: [g1q, ..., gGq].
1530      inline void getIntegrationPoints(const int elementType,
1531                                       const std::string & integrationType,
1532                                       std::vector<double> & localCoord,
1533                                       std::vector<double> & weights)
1534      {
1535        int ierr = 0;
1536        double *api_localCoord_; size_t api_localCoord_n_;
1537        double *api_weights_; size_t api_weights_n_;
1538        gmshModelMeshGetIntegrationPoints(elementType, integrationType.c_str(), &api_localCoord_, &api_localCoord_n_, &api_weights_, &api_weights_n_, &ierr);
1539        if(ierr) throwLastError();
1540        localCoord.assign(api_localCoord_, api_localCoord_ + api_localCoord_n_); gmshFree(api_localCoord_);
1541        weights.assign(api_weights_, api_weights_ + api_weights_n_); gmshFree(api_weights_);
1542      }
1543
1544      // Get the Jacobians of all the elements of type `elementType' classified on
1545      // the entity of tag `tag', at the G evaluation points `localCoord' given as
1546      // concatenated triplets of coordinates in the reference element [g1u, g1v,
1547      // g1w, ..., gGu, gGv, gGw]. Data is returned by element, with elements in
1548      // the same order as in `getElements' and `getElementsByType'. `jacobians'
1549      // contains for each element the 9 entries of the 3x3 Jacobian matrix at each
1550      // evaluation point. The matrix is returned by column: [e1g1Jxu, e1g1Jyu,
1551      // e1g1Jzu, e1g1Jxv, ..., e1g1Jzw, e1g2Jxu, ..., e1gGJzw, e2g1Jxu, ...], with
1552      // Jxu=dx/du, Jyu=dy/du, etc. `determinants' contains for each element the
1553      // determinant of the Jacobian matrix at each evaluation point: [e1g1, e1g2,
1554      // ... e1gG, e2g1, ...]. `coord' contains for each element the x, y, z
1555      // coordinates of the evaluation points. If `tag' < 0, get the Jacobian data
1556      // for all entities. If `numTasks' > 1, only compute and return the part of
1557      // the data indexed by `task'.
1558      inline void getJacobians(const int elementType,
1559                               const std::vector<double> & localCoord,
1560                               std::vector<double> & jacobians,
1561                               std::vector<double> & determinants,
1562                               std::vector<double> & coord,
1563                               const int tag = -1,
1564                               const std::size_t task = 0,
1565                               const std::size_t numTasks = 1)
1566      {
1567        int ierr = 0;
1568        double *api_localCoord_; size_t api_localCoord_n_; vector2ptr(localCoord, &api_localCoord_, &api_localCoord_n_);
1569        double *api_jacobians_; size_t api_jacobians_n_;
1570        double *api_determinants_; size_t api_determinants_n_;
1571        double *api_coord_; size_t api_coord_n_;
1572        gmshModelMeshGetJacobians(elementType, api_localCoord_, api_localCoord_n_, &api_jacobians_, &api_jacobians_n_, &api_determinants_, &api_determinants_n_, &api_coord_, &api_coord_n_, tag, task, numTasks, &ierr);
1573        if(ierr) throwLastError();
1574        gmshFree(api_localCoord_);
1575        jacobians.assign(api_jacobians_, api_jacobians_ + api_jacobians_n_); gmshFree(api_jacobians_);
1576        determinants.assign(api_determinants_, api_determinants_ + api_determinants_n_); gmshFree(api_determinants_);
1577        coord.assign(api_coord_, api_coord_ + api_coord_n_); gmshFree(api_coord_);
1578      }
1579
1580      // Preallocate data before calling `getJacobians' with `numTasks' > 1. For C
1581      // and C++ only.
1582      inline void preallocateJacobians(const int elementType,
1583                                       const int numEvaluationPoints,
1584                                       const bool allocateJacobians,
1585                                       const bool allocateDeterminants,
1586                                       const bool allocateCoord,
1587                                       std::vector<double> & jacobians,
1588                                       std::vector<double> & determinants,
1589                                       std::vector<double> & coord,
1590                                       const int tag = -1)
1591      {
1592        int ierr = 0;
1593        double *api_jacobians_; size_t api_jacobians_n_;
1594        double *api_determinants_; size_t api_determinants_n_;
1595        double *api_coord_; size_t api_coord_n_;
1596        gmshModelMeshPreallocateJacobians(elementType, numEvaluationPoints, (int)allocateJacobians, (int)allocateDeterminants, (int)allocateCoord, &api_jacobians_, &api_jacobians_n_, &api_determinants_, &api_determinants_n_, &api_coord_, &api_coord_n_, tag, &ierr);
1597        if(ierr) throwLastError();
1598        jacobians.assign(api_jacobians_, api_jacobians_ + api_jacobians_n_); gmshFree(api_jacobians_);
1599        determinants.assign(api_determinants_, api_determinants_ + api_determinants_n_); gmshFree(api_determinants_);
1600        coord.assign(api_coord_, api_coord_ + api_coord_n_); gmshFree(api_coord_);
1601      }
1602
1603      // Get the Jacobian for a single element `elementTag', at the G evaluation
1604      // points `localCoord' given as concatenated triplets of coordinates in the
1605      // reference element [g1u, g1v, g1w, ..., gGu, gGv, gGw]. `jacobians'
1606      // contains the 9 entries of the 3x3 Jacobian matrix at each evaluation
1607      // point. The matrix is returned by column: [e1g1Jxu, e1g1Jyu, e1g1Jzu,
1608      // e1g1Jxv, ..., e1g1Jzw, e1g2Jxu, ..., e1gGJzw, e2g1Jxu, ...], with
1609      // Jxu=dx/du, Jyu=dy/du, etc. `determinants' contains the determinant of the
1610      // Jacobian matrix at each evaluation point. `coord' contains the x, y, z
1611      // coordinates of the evaluation points. This function relies on an internal
1612      // cache (a vector in case of dense element numbering, a map otherwise); for
1613      // large meshes accessing Jacobians in bulk is often preferable.
1614      inline void getJacobian(const std::size_t elementTag,
1615                              const std::vector<double> & localCoord,
1616                              std::vector<double> & jacobians,
1617                              std::vector<double> & determinants,
1618                              std::vector<double> & coord)
1619      {
1620        int ierr = 0;
1621        double *api_localCoord_; size_t api_localCoord_n_; vector2ptr(localCoord, &api_localCoord_, &api_localCoord_n_);
1622        double *api_jacobians_; size_t api_jacobians_n_;
1623        double *api_determinants_; size_t api_determinants_n_;
1624        double *api_coord_; size_t api_coord_n_;
1625        gmshModelMeshGetJacobian(elementTag, api_localCoord_, api_localCoord_n_, &api_jacobians_, &api_jacobians_n_, &api_determinants_, &api_determinants_n_, &api_coord_, &api_coord_n_, &ierr);
1626        if(ierr) throwLastError();
1627        gmshFree(api_localCoord_);
1628        jacobians.assign(api_jacobians_, api_jacobians_ + api_jacobians_n_); gmshFree(api_jacobians_);
1629        determinants.assign(api_determinants_, api_determinants_ + api_determinants_n_); gmshFree(api_determinants_);
1630        coord.assign(api_coord_, api_coord_ + api_coord_n_); gmshFree(api_coord_);
1631      }
1632
1633      // Get the basis functions of the element of type `elementType' at the
1634      // evaluation points `localCoord' (given as concatenated triplets of
1635      // coordinates in the reference element [g1u, g1v, g1w, ..., gGu, gGv, gGw]),
1636      // for the function space `functionSpaceType'. Currently supported function
1637      // spaces include "Lagrange" and "GradLagrange" for isoparametric Lagrange
1638      // basis functions and their gradient in the u, v, w coordinates of the
1639      // reference element; "LagrangeN" and "GradLagrangeN", with N = 1, 2, ...,
1640      // for N-th order Lagrange basis functions; "H1LegendreN" and
1641      // "GradH1LegendreN", with N = 1, 2, ..., for N-th order hierarchical H1
1642      // Legendre functions; "HcurlLegendreN" and "CurlHcurlLegendreN", with N = 1,
1643      // 2, ..., for N-th order curl-conforming basis functions. `numComponents'
1644      // returns the number C of components of a basis function (e.g. 1 for scalar
1645      // functions and 3 for vector functions). `basisFunctions' returns the value
1646      // of the N basis functions at the evaluation points, i.e. [g1f1, g1f2, ...,
1647      // g1fN, g2f1, ...] when C == 1 or [g1f1u, g1f1v, g1f1w, g1f2u, ..., g1fNw,
1648      // g2f1u, ...] when C == 3. For basis functions that depend on the
1649      // orientation of the elements, all values for the first orientation are
1650      // returned first, followed by values for the second, etc. `numOrientations'
1651      // returns the overall number of orientations. If `wantedOrientations' is not
1652      // empty, only return the values for the desired orientation indices.
1653      inline void getBasisFunctions(const int elementType,
1654                                    const std::vector<double> & localCoord,
1655                                    const std::string & functionSpaceType,
1656                                    int & numComponents,
1657                                    std::vector<double> & basisFunctions,
1658                                    int & numOrientations,
1659                                    const std::vector<int> & wantedOrientations = std::vector<int>())
1660      {
1661        int ierr = 0;
1662        double *api_localCoord_; size_t api_localCoord_n_; vector2ptr(localCoord, &api_localCoord_, &api_localCoord_n_);
1663        double *api_basisFunctions_; size_t api_basisFunctions_n_;
1664        int *api_wantedOrientations_; size_t api_wantedOrientations_n_; vector2ptr(wantedOrientations, &api_wantedOrientations_, &api_wantedOrientations_n_);
1665        gmshModelMeshGetBasisFunctions(elementType, api_localCoord_, api_localCoord_n_, functionSpaceType.c_str(), &numComponents, &api_basisFunctions_, &api_basisFunctions_n_, &numOrientations, api_wantedOrientations_, api_wantedOrientations_n_, &ierr);
1666        if(ierr) throwLastError();
1667        gmshFree(api_localCoord_);
1668        basisFunctions.assign(api_basisFunctions_, api_basisFunctions_ + api_basisFunctions_n_); gmshFree(api_basisFunctions_);
1669        gmshFree(api_wantedOrientations_);
1670      }
1671
1672      // Get the orientation index of the elements of type `elementType' in the
1673      // entity of tag `tag'. The arguments have the same meaning as in
1674      // `getBasisFunctions'. `basisFunctionsOrientation' is a vector giving for
1675      // each element the orientation index in the values returned by
1676      // `getBasisFunctions'. For Lagrange basis functions the call is superfluous
1677      // as it will return a vector of zeros.
1678      inline void getBasisFunctionsOrientation(const int elementType,
1679                                               const std::string & functionSpaceType,
1680                                               std::vector<int> & basisFunctionsOrientation,
1681                                               const int tag = -1,
1682                                               const std::size_t task = 0,
1683                                               const std::size_t numTasks = 1)
1684      {
1685        int ierr = 0;
1686        int *api_basisFunctionsOrientation_; size_t api_basisFunctionsOrientation_n_;
1687        gmshModelMeshGetBasisFunctionsOrientation(elementType, functionSpaceType.c_str(), &api_basisFunctionsOrientation_, &api_basisFunctionsOrientation_n_, tag, task, numTasks, &ierr);
1688        if(ierr) throwLastError();
1689        basisFunctionsOrientation.assign(api_basisFunctionsOrientation_, api_basisFunctionsOrientation_ + api_basisFunctionsOrientation_n_); gmshFree(api_basisFunctionsOrientation_);
1690      }
1691
1692      // Get the orientation of a single element `elementTag'.
1693      inline void getBasisFunctionsOrientationForElement(const std::size_t elementTag,
1694                                                         const std::string & functionSpaceType,
1695                                                         int & basisFunctionsOrientation)
1696      {
1697        int ierr = 0;
1698        gmshModelMeshGetBasisFunctionsOrientationForElement(elementTag, functionSpaceType.c_str(), &basisFunctionsOrientation, &ierr);
1699        if(ierr) throwLastError();
1700      }
1701
1702      // Get the number of possible orientations for elements of type `elementType'
1703      // and function space named `functionSpaceType'.
1704      inline int getNumberOfOrientations(const int elementType,
1705                                         const std::string & functionSpaceType)
1706      {
1707        int ierr = 0;
1708        int result_api_ = gmshModelMeshGetNumberOfOrientations(elementType, functionSpaceType.c_str(), &ierr);
1709        if(ierr) throwLastError();
1710        return result_api_;
1711      }
1712
1713      // Preallocate data before calling `getBasisFunctionsOrientation' with
1714      // `numTasks' > 1. For C and C++ only.
1715      inline void preallocateBasisFunctionsOrientation(const int elementType,
1716                                                       std::vector<int> & basisFunctionsOrientation,
1717                                                       const int tag = -1)
1718      {
1719        int ierr = 0;
1720        int *api_basisFunctionsOrientation_; size_t api_basisFunctionsOrientation_n_;
1721        gmshModelMeshPreallocateBasisFunctionsOrientation(elementType, &api_basisFunctionsOrientation_, &api_basisFunctionsOrientation_n_, tag, &ierr);
1722        if(ierr) throwLastError();
1723        basisFunctionsOrientation.assign(api_basisFunctionsOrientation_, api_basisFunctionsOrientation_ + api_basisFunctionsOrientation_n_); gmshFree(api_basisFunctionsOrientation_);
1724      }
1725
1726      // Get the global unique mesh edge identifiers `edgeTags' and orientations
1727      // `edgeOrientation' for an input list of node tag pairs defining these
1728      // edges, concatenated in the vector `nodeTags'. Mesh edges are created e.g.
1729      // by `createEdges()', `getKeys()' or `addEdges()'. The reference positive
1730      // orientation is n1 < n2, where n1 and n2 are the tags of the two edge
1731      // nodes, which corresponds to the local orientation of edge-based basis
1732      // functions as well.
1733      inline void getEdges(const std::vector<std::size_t> & nodeTags,
1734                           std::vector<std::size_t> & edgeTags,
1735                           std::vector<int> & edgeOrientations)
1736      {
1737        int ierr = 0;
1738        size_t *api_nodeTags_; size_t api_nodeTags_n_; vector2ptr(nodeTags, &api_nodeTags_, &api_nodeTags_n_);
1739        size_t *api_edgeTags_; size_t api_edgeTags_n_;
1740        int *api_edgeOrientations_; size_t api_edgeOrientations_n_;
1741        gmshModelMeshGetEdges(api_nodeTags_, api_nodeTags_n_, &api_edgeTags_, &api_edgeTags_n_, &api_edgeOrientations_, &api_edgeOrientations_n_, &ierr);
1742        if(ierr) throwLastError();
1743        gmshFree(api_nodeTags_);
1744        edgeTags.assign(api_edgeTags_, api_edgeTags_ + api_edgeTags_n_); gmshFree(api_edgeTags_);
1745        edgeOrientations.assign(api_edgeOrientations_, api_edgeOrientations_ + api_edgeOrientations_n_); gmshFree(api_edgeOrientations_);
1746      }
1747
1748      // Get the global unique mesh face identifiers `faceTags' and orientations
1749      // `faceOrientations' for an input list of node tag triplets (if `faceType'
1750      // == 3) or quadruplets (if `faceType' == 4) defining these faces,
1751      // concatenated in the vector `nodeTags'. Mesh faces are created e.g. by
1752      // `createFaces()', `getKeys()' or `addFaces()'.
1753      inline void getFaces(const int faceType,
1754                           const std::vector<std::size_t> & nodeTags,
1755                           std::vector<std::size_t> & faceTags,
1756                           std::vector<int> & faceOrientations)
1757      {
1758        int ierr = 0;
1759        size_t *api_nodeTags_; size_t api_nodeTags_n_; vector2ptr(nodeTags, &api_nodeTags_, &api_nodeTags_n_);
1760        size_t *api_faceTags_; size_t api_faceTags_n_;
1761        int *api_faceOrientations_; size_t api_faceOrientations_n_;
1762        gmshModelMeshGetFaces(faceType, api_nodeTags_, api_nodeTags_n_, &api_faceTags_, &api_faceTags_n_, &api_faceOrientations_, &api_faceOrientations_n_, &ierr);
1763        if(ierr) throwLastError();
1764        gmshFree(api_nodeTags_);
1765        faceTags.assign(api_faceTags_, api_faceTags_ + api_faceTags_n_); gmshFree(api_faceTags_);
1766        faceOrientations.assign(api_faceOrientations_, api_faceOrientations_ + api_faceOrientations_n_); gmshFree(api_faceOrientations_);
1767      }
1768
1769      // Create unique mesh edges for the entities `dimTags'.
1770      inline void createEdges(const gmsh::vectorpair & dimTags = gmsh::vectorpair())
1771      {
1772        int ierr = 0;
1773        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
1774        gmshModelMeshCreateEdges(api_dimTags_, api_dimTags_n_, &ierr);
1775        if(ierr) throwLastError();
1776        gmshFree(api_dimTags_);
1777      }
1778
1779      // Create unique mesh faces for the entities `dimTags'.
1780      inline void createFaces(const gmsh::vectorpair & dimTags = gmsh::vectorpair())
1781      {
1782        int ierr = 0;
1783        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
1784        gmshModelMeshCreateFaces(api_dimTags_, api_dimTags_n_, &ierr);
1785        if(ierr) throwLastError();
1786        gmshFree(api_dimTags_);
1787      }
1788
1789      // Get the global unique identifiers `edgeTags' and the nodes `edgeNodes' of
1790      // the edges in the mesh. Mesh edges are created e.g. by `createEdges()',
1791      // `getKeys()' or addEdges().
1792      inline void getAllEdges(std::vector<std::size_t> & edgeTags,
1793                              std::vector<std::size_t> & edgeNodes)
1794      {
1795        int ierr = 0;
1796        size_t *api_edgeTags_; size_t api_edgeTags_n_;
1797        size_t *api_edgeNodes_; size_t api_edgeNodes_n_;
1798        gmshModelMeshGetAllEdges(&api_edgeTags_, &api_edgeTags_n_, &api_edgeNodes_, &api_edgeNodes_n_, &ierr);
1799        if(ierr) throwLastError();
1800        edgeTags.assign(api_edgeTags_, api_edgeTags_ + api_edgeTags_n_); gmshFree(api_edgeTags_);
1801        edgeNodes.assign(api_edgeNodes_, api_edgeNodes_ + api_edgeNodes_n_); gmshFree(api_edgeNodes_);
1802      }
1803
1804      // Get the global unique identifiers `faceTags' and the nodes `faceNodes' of
1805      // the faces of type `faceType' in the mesh. Mesh faces are created e.g. by
1806      // `createFaces()', `getKeys()' or addFaces().
1807      inline void getAllFaces(const int faceType,
1808                              std::vector<std::size_t> & faceTags,
1809                              std::vector<std::size_t> & faceNodes)
1810      {
1811        int ierr = 0;
1812        size_t *api_faceTags_; size_t api_faceTags_n_;
1813        size_t *api_faceNodes_; size_t api_faceNodes_n_;
1814        gmshModelMeshGetAllFaces(faceType, &api_faceTags_, &api_faceTags_n_, &api_faceNodes_, &api_faceNodes_n_, &ierr);
1815        if(ierr) throwLastError();
1816        faceTags.assign(api_faceTags_, api_faceTags_ + api_faceTags_n_); gmshFree(api_faceTags_);
1817        faceNodes.assign(api_faceNodes_, api_faceNodes_ + api_faceNodes_n_); gmshFree(api_faceNodes_);
1818      }
1819
1820      // Add mesh edges defined by their global unique identifiers `edgeTags' and
1821      // their nodes `edgeNodes'.
1822      inline void addEdges(const std::vector<std::size_t> & edgeTags,
1823                           const std::vector<std::size_t> & edgeNodes)
1824      {
1825        int ierr = 0;
1826        size_t *api_edgeTags_; size_t api_edgeTags_n_; vector2ptr(edgeTags, &api_edgeTags_, &api_edgeTags_n_);
1827        size_t *api_edgeNodes_; size_t api_edgeNodes_n_; vector2ptr(edgeNodes, &api_edgeNodes_, &api_edgeNodes_n_);
1828        gmshModelMeshAddEdges(api_edgeTags_, api_edgeTags_n_, api_edgeNodes_, api_edgeNodes_n_, &ierr);
1829        if(ierr) throwLastError();
1830        gmshFree(api_edgeTags_);
1831        gmshFree(api_edgeNodes_);
1832      }
1833
1834      // Add mesh faces of type `faceType' defined by their global unique
1835      // identifiers `faceTags' and their nodes `faceNodes'.
1836      inline void addFaces(const int faceType,
1837                           const std::vector<std::size_t> & faceTags,
1838                           const std::vector<std::size_t> & faceNodes)
1839      {
1840        int ierr = 0;
1841        size_t *api_faceTags_; size_t api_faceTags_n_; vector2ptr(faceTags, &api_faceTags_, &api_faceTags_n_);
1842        size_t *api_faceNodes_; size_t api_faceNodes_n_; vector2ptr(faceNodes, &api_faceNodes_, &api_faceNodes_n_);
1843        gmshModelMeshAddFaces(faceType, api_faceTags_, api_faceTags_n_, api_faceNodes_, api_faceNodes_n_, &ierr);
1844        if(ierr) throwLastError();
1845        gmshFree(api_faceTags_);
1846        gmshFree(api_faceNodes_);
1847      }
1848
1849      // Generate the pair of keys for the elements of type `elementType' in the
1850      // entity of tag `tag', for the `functionSpaceType' function space. Each pair
1851      // (`typeKey', `entityKey') uniquely identifies a basis function in the
1852      // function space. If `returnCoord' is set, the `coord' vector contains the
1853      // x, y, z coordinates locating basis functions for sorting purposes.
1854      // Warning: this is an experimental feature and will probably change in a
1855      // future release.
1856      inline void getKeys(const int elementType,
1857                          const std::string & functionSpaceType,
1858                          std::vector<int> & typeKeys,
1859                          std::vector<std::size_t> & entityKeys,
1860                          std::vector<double> & coord,
1861                          const int tag = -1,
1862                          const bool returnCoord = true)
1863      {
1864        int ierr = 0;
1865        int *api_typeKeys_; size_t api_typeKeys_n_;
1866        size_t *api_entityKeys_; size_t api_entityKeys_n_;
1867        double *api_coord_; size_t api_coord_n_;
1868        gmshModelMeshGetKeys(elementType, functionSpaceType.c_str(), &api_typeKeys_, &api_typeKeys_n_, &api_entityKeys_, &api_entityKeys_n_, &api_coord_, &api_coord_n_, tag, (int)returnCoord, &ierr);
1869        if(ierr) throwLastError();
1870        typeKeys.assign(api_typeKeys_, api_typeKeys_ + api_typeKeys_n_); gmshFree(api_typeKeys_);
1871        entityKeys.assign(api_entityKeys_, api_entityKeys_ + api_entityKeys_n_); gmshFree(api_entityKeys_);
1872        coord.assign(api_coord_, api_coord_ + api_coord_n_); gmshFree(api_coord_);
1873      }
1874
1875      // Get the pair of keys for a single element `elementTag'.
1876      inline void getKeysForElement(const std::size_t elementTag,
1877                                    const std::string & functionSpaceType,
1878                                    std::vector<int> & typeKeys,
1879                                    std::vector<std::size_t> & entityKeys,
1880                                    std::vector<double> & coord,
1881                                    const bool returnCoord = true)
1882      {
1883        int ierr = 0;
1884        int *api_typeKeys_; size_t api_typeKeys_n_;
1885        size_t *api_entityKeys_; size_t api_entityKeys_n_;
1886        double *api_coord_; size_t api_coord_n_;
1887        gmshModelMeshGetKeysForElement(elementTag, functionSpaceType.c_str(), &api_typeKeys_, &api_typeKeys_n_, &api_entityKeys_, &api_entityKeys_n_, &api_coord_, &api_coord_n_, (int)returnCoord, &ierr);
1888        if(ierr) throwLastError();
1889        typeKeys.assign(api_typeKeys_, api_typeKeys_ + api_typeKeys_n_); gmshFree(api_typeKeys_);
1890        entityKeys.assign(api_entityKeys_, api_entityKeys_ + api_entityKeys_n_); gmshFree(api_entityKeys_);
1891        coord.assign(api_coord_, api_coord_ + api_coord_n_); gmshFree(api_coord_);
1892      }
1893
1894      // Get the number of keys by elements of type `elementType' for function
1895      // space named `functionSpaceType'.
1896      inline int getNumberOfKeys(const int elementType,
1897                                 const std::string & functionSpaceType)
1898      {
1899        int ierr = 0;
1900        int result_api_ = gmshModelMeshGetNumberOfKeys(elementType, functionSpaceType.c_str(), &ierr);
1901        if(ierr) throwLastError();
1902        return result_api_;
1903      }
1904
1905      // Get information about the pair of `keys'. `infoKeys' returns information
1906      // about the functions associated with the pairs (`typeKeys', `entityKey').
1907      // `infoKeys[0].first' describes the type of function (0 for  vertex
1908      // function, 1 for edge function, 2 for face function and 3 for bubble
1909      // function). `infoKeys[0].second' gives the order of the function associated
1910      // with the key. Warning: this is an experimental feature and will probably
1911      // change in a future release.
1912      inline void getKeysInformation(const std::vector<int> & typeKeys,
1913                                     const std::vector<std::size_t> & entityKeys,
1914                                     const int elementType,
1915                                     const std::string & functionSpaceType,
1916                                     gmsh::vectorpair & infoKeys)
1917      {
1918        int ierr = 0;
1919        int *api_typeKeys_; size_t api_typeKeys_n_; vector2ptr(typeKeys, &api_typeKeys_, &api_typeKeys_n_);
1920        size_t *api_entityKeys_; size_t api_entityKeys_n_; vector2ptr(entityKeys, &api_entityKeys_, &api_entityKeys_n_);
1921        int *api_infoKeys_; size_t api_infoKeys_n_;
1922        gmshModelMeshGetKeysInformation(api_typeKeys_, api_typeKeys_n_, api_entityKeys_, api_entityKeys_n_, elementType, functionSpaceType.c_str(), &api_infoKeys_, &api_infoKeys_n_, &ierr);
1923        if(ierr) throwLastError();
1924        gmshFree(api_typeKeys_);
1925        gmshFree(api_entityKeys_);
1926        infoKeys.resize(api_infoKeys_n_ / 2); for(size_t i = 0; i < api_infoKeys_n_ / 2; ++i){ infoKeys[i].first = api_infoKeys_[i * 2 + 0]; infoKeys[i].second = api_infoKeys_[i * 2 + 1]; } gmshFree(api_infoKeys_);
1927      }
1928
1929      // Get the barycenters of all elements of type `elementType' classified on
1930      // the entity of tag `tag'. If `primary' is set, only the primary nodes of
1931      // the elements are taken into account for the barycenter calculation. If
1932      // `fast' is set, the function returns the sum of the primary node
1933      // coordinates (without normalizing by the number of nodes). If `tag' < 0,
1934      // get the barycenters for all entities. If `numTasks' > 1, only compute and
1935      // return the part of the data indexed by `task'.
1936      inline void getBarycenters(const int elementType,
1937                                 const int tag,
1938                                 const bool fast,
1939                                 const bool primary,
1940                                 std::vector<double> & barycenters,
1941                                 const std::size_t task = 0,
1942                                 const std::size_t numTasks = 1)
1943      {
1944        int ierr = 0;
1945        double *api_barycenters_; size_t api_barycenters_n_;
1946        gmshModelMeshGetBarycenters(elementType, tag, (int)fast, (int)primary, &api_barycenters_, &api_barycenters_n_, task, numTasks, &ierr);
1947        if(ierr) throwLastError();
1948        barycenters.assign(api_barycenters_, api_barycenters_ + api_barycenters_n_); gmshFree(api_barycenters_);
1949      }
1950
1951      // Preallocate data before calling `getBarycenters' with `numTasks' > 1. For
1952      // C and C++ only.
1953      inline void preallocateBarycenters(const int elementType,
1954                                         std::vector<double> & barycenters,
1955                                         const int tag = -1)
1956      {
1957        int ierr = 0;
1958        double *api_barycenters_; size_t api_barycenters_n_;
1959        gmshModelMeshPreallocateBarycenters(elementType, &api_barycenters_, &api_barycenters_n_, tag, &ierr);
1960        if(ierr) throwLastError();
1961        barycenters.assign(api_barycenters_, api_barycenters_ + api_barycenters_n_); gmshFree(api_barycenters_);
1962      }
1963
1964      // Get the nodes on the edges of all elements of type `elementType'
1965      // classified on the entity of tag `tag'. `nodeTags' contains the node tags
1966      // of the edges for all the elements: [e1a1n1, e1a1n2, e1a2n1, ...]. Data is
1967      // returned by element, with elements in the same order as in `getElements'
1968      // and `getElementsByType'. If `primary' is set, only the primary (begin/end)
1969      // nodes of the edges are returned. If `tag' < 0, get the edge nodes for all
1970      // entities. If `numTasks' > 1, only compute and return the part of the data
1971      // indexed by `task'.
1972      inline void getElementEdgeNodes(const int elementType,
1973                                      std::vector<std::size_t> & nodeTags,
1974                                      const int tag = -1,
1975                                      const bool primary = false,
1976                                      const std::size_t task = 0,
1977                                      const std::size_t numTasks = 1)
1978      {
1979        int ierr = 0;
1980        size_t *api_nodeTags_; size_t api_nodeTags_n_;
1981        gmshModelMeshGetElementEdgeNodes(elementType, &api_nodeTags_, &api_nodeTags_n_, tag, (int)primary, task, numTasks, &ierr);
1982        if(ierr) throwLastError();
1983        nodeTags.assign(api_nodeTags_, api_nodeTags_ + api_nodeTags_n_); gmshFree(api_nodeTags_);
1984      }
1985
1986      // Get the nodes on the faces of type `faceType' (3 for triangular faces, 4
1987      // for quadrangular faces) of all elements of type `elementType' classified
1988      // on the entity of tag `tag'. `nodeTags' contains the node tags of the faces
1989      // for all elements: [e1f1n1, ..., e1f1nFaceType, e1f2n1, ...]. Data is
1990      // returned by element, with elements in the same order as in `getElements'
1991      // and `getElementsByType'. If `primary' is set, only the primary (corner)
1992      // nodes of the faces are returned. If `tag' < 0, get the face nodes for all
1993      // entities. If `numTasks' > 1, only compute and return the part of the data
1994      // indexed by `task'.
1995      inline void getElementFaceNodes(const int elementType,
1996                                      const int faceType,
1997                                      std::vector<std::size_t> & nodeTags,
1998                                      const int tag = -1,
1999                                      const bool primary = false,
2000                                      const std::size_t task = 0,
2001                                      const std::size_t numTasks = 1)
2002      {
2003        int ierr = 0;
2004        size_t *api_nodeTags_; size_t api_nodeTags_n_;
2005        gmshModelMeshGetElementFaceNodes(elementType, faceType, &api_nodeTags_, &api_nodeTags_n_, tag, (int)primary, task, numTasks, &ierr);
2006        if(ierr) throwLastError();
2007        nodeTags.assign(api_nodeTags_, api_nodeTags_ + api_nodeTags_n_); gmshFree(api_nodeTags_);
2008      }
2009
2010      // Get the ghost elements `elementTags' and their associated `partitions'
2011      // stored in the ghost entity of dimension `dim' and tag `tag'.
2012      inline void getGhostElements(const int dim,
2013                                   const int tag,
2014                                   std::vector<std::size_t> & elementTags,
2015                                   std::vector<int> & partitions)
2016      {
2017        int ierr = 0;
2018        size_t *api_elementTags_; size_t api_elementTags_n_;
2019        int *api_partitions_; size_t api_partitions_n_;
2020        gmshModelMeshGetGhostElements(dim, tag, &api_elementTags_, &api_elementTags_n_, &api_partitions_, &api_partitions_n_, &ierr);
2021        if(ierr) throwLastError();
2022        elementTags.assign(api_elementTags_, api_elementTags_ + api_elementTags_n_); gmshFree(api_elementTags_);
2023        partitions.assign(api_partitions_, api_partitions_ + api_partitions_n_); gmshFree(api_partitions_);
2024      }
2025
2026      // Set a mesh size constraint on the model entities `dimTags'. Currently only
2027      // entities of dimension 0 (points) are handled.
2028      inline void setSize(const gmsh::vectorpair & dimTags,
2029                          const double size)
2030      {
2031        int ierr = 0;
2032        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
2033        gmshModelMeshSetSize(api_dimTags_, api_dimTags_n_, size, &ierr);
2034        if(ierr) throwLastError();
2035        gmshFree(api_dimTags_);
2036      }
2037
2038      // Get the mesh size constraints (if any) associated with the model entities
2039      // `dimTags'. A zero entry in the output `sizes' vector indicates that no
2040      // size constraint is specified on the corresponding entity.
2041      inline void getSizes(const gmsh::vectorpair & dimTags,
2042                           std::vector<double> & sizes)
2043      {
2044        int ierr = 0;
2045        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
2046        double *api_sizes_; size_t api_sizes_n_;
2047        gmshModelMeshGetSizes(api_dimTags_, api_dimTags_n_, &api_sizes_, &api_sizes_n_, &ierr);
2048        if(ierr) throwLastError();
2049        gmshFree(api_dimTags_);
2050        sizes.assign(api_sizes_, api_sizes_ + api_sizes_n_); gmshFree(api_sizes_);
2051      }
2052
2053      // Set mesh size constraints at the given parametric points `parametricCoord'
2054      // on the model entity of dimension `dim' and tag `tag'. Currently only
2055      // entities of dimension 1 (lines) are handled.
2056      inline void setSizeAtParametricPoints(const int dim,
2057                                            const int tag,
2058                                            const std::vector<double> & parametricCoord,
2059                                            const std::vector<double> & sizes)
2060      {
2061        int ierr = 0;
2062        double *api_parametricCoord_; size_t api_parametricCoord_n_; vector2ptr(parametricCoord, &api_parametricCoord_, &api_parametricCoord_n_);
2063        double *api_sizes_; size_t api_sizes_n_; vector2ptr(sizes, &api_sizes_, &api_sizes_n_);
2064        gmshModelMeshSetSizeAtParametricPoints(dim, tag, api_parametricCoord_, api_parametricCoord_n_, api_sizes_, api_sizes_n_, &ierr);
2065        if(ierr) throwLastError();
2066        gmshFree(api_parametricCoord_);
2067        gmshFree(api_sizes_);
2068      }
2069
2070      // Set a mesh size callback for the current model. The callback function
2071      // should take six arguments as input (`dim', `tag', `x', `y', `z' and `lc').
2072      // The first two integer arguments correspond to the dimension `dim' and tag
2073      // `tag' of the entity being meshed. The next four double precision arguments
2074      // correspond to the coordinates `x', `y' and `z' around which to prescribe
2075      // the mesh size and to the mesh size `lc' that would be prescribed if the
2076      // callback had not been called. The callback function should return a double
2077      // precision number specifying the desired mesh size; returning `lc' is
2078      // equivalent to a no-op.
2079      inline void setSizeCallback(std::function<double(int, int, double, double, double, double)> callback)
2080      {
2081        int ierr = 0;
2082        struct callback_caller_  {
2083          static double call(int dim, int tag, double x, double y, double z, double lc, void * callbackp_) {
2084            return (*static_cast<std::function<double(int, int, double, double, double, double)>*> (callbackp_))(dim, tag, x, y, z, lc);
2085          }
2086        };
2087        // FIXME memory leak
2088        auto *callback_ptr_ = new std::function<double(int, int, double, double, double, double)>(callback);
2089        gmshModelMeshSetSizeCallback(&callback_caller_::call, callback_ptr_, &ierr);
2090        if(ierr) throwLastError();
2091      }
2092
2093      // Remove the mesh size callback from the current model.
2094      inline void removeSizeCallback()
2095      {
2096        int ierr = 0;
2097        gmshModelMeshRemoveSizeCallback(&ierr);
2098        if(ierr) throwLastError();
2099      }
2100
2101      // Set a transfinite meshing constraint on the curve `tag', with `numNodes'
2102      // nodes distributed according to `meshType' and `coef'. Currently supported
2103      // types are "Progression" (geometrical progression with power `coef'),
2104      // "Bump" (refinement toward both extremities of the curve) and "Beta" (beta
2105      // law).
2106      inline void setTransfiniteCurve(const int tag,
2107                                      const int numNodes,
2108                                      const std::string & meshType = "Progression",
2109                                      const double coef = 1.)
2110      {
2111        int ierr = 0;
2112        gmshModelMeshSetTransfiniteCurve(tag, numNodes, meshType.c_str(), coef, &ierr);
2113        if(ierr) throwLastError();
2114      }
2115
2116      // Set a transfinite meshing constraint on the surface `tag'. `arrangement'
2117      // describes the arrangement of the triangles when the surface is not flagged
2118      // as recombined: currently supported values are "Left", "Right",
2119      // "AlternateLeft" and "AlternateRight". `cornerTags' can be used to specify
2120      // the (3 or 4) corners of the transfinite interpolation explicitly;
2121      // specifying the corners explicitly is mandatory if the surface has more
2122      // that 3 or 4 points on its boundary.
2123      inline void setTransfiniteSurface(const int tag,
2124                                        const std::string & arrangement = "Left",
2125                                        const std::vector<int> & cornerTags = std::vector<int>())
2126      {
2127        int ierr = 0;
2128        int *api_cornerTags_; size_t api_cornerTags_n_; vector2ptr(cornerTags, &api_cornerTags_, &api_cornerTags_n_);
2129        gmshModelMeshSetTransfiniteSurface(tag, arrangement.c_str(), api_cornerTags_, api_cornerTags_n_, &ierr);
2130        if(ierr) throwLastError();
2131        gmshFree(api_cornerTags_);
2132      }
2133
2134      // Set a transfinite meshing constraint on the surface `tag'. `cornerTags'
2135      // can be used to specify the (6 or 8) corners of the transfinite
2136      // interpolation explicitly.
2137      inline void setTransfiniteVolume(const int tag,
2138                                       const std::vector<int> & cornerTags = std::vector<int>())
2139      {
2140        int ierr = 0;
2141        int *api_cornerTags_; size_t api_cornerTags_n_; vector2ptr(cornerTags, &api_cornerTags_, &api_cornerTags_n_);
2142        gmshModelMeshSetTransfiniteVolume(tag, api_cornerTags_, api_cornerTags_n_, &ierr);
2143        if(ierr) throwLastError();
2144        gmshFree(api_cornerTags_);
2145      }
2146
2147      // Set transfinite meshing constraints on the model entities in `dimTag'.
2148      // Transfinite meshing constraints are added to the curves of the
2149      // quadrangular surfaces and to the faces of 6-sided volumes. Quadragular
2150      // faces with a corner angle superior to `cornerAngle' (in radians) are
2151      // ignored. The number of points is automatically determined from the sizing
2152      // constraints. If `dimTag' is empty, the constraints are applied to all
2153      // entities in the model. If `recombine' is true, the recombine flag is
2154      // automatically set on the transfinite surfaces.
2155      inline void setTransfiniteAutomatic(const gmsh::vectorpair & dimTags = gmsh::vectorpair(),
2156                                          const double cornerAngle = 2.35,
2157                                          const bool recombine = true)
2158      {
2159        int ierr = 0;
2160        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
2161        gmshModelMeshSetTransfiniteAutomatic(api_dimTags_, api_dimTags_n_, cornerAngle, (int)recombine, &ierr);
2162        if(ierr) throwLastError();
2163        gmshFree(api_dimTags_);
2164      }
2165
2166      // Set a recombination meshing constraint on the model entity of dimension
2167      // `dim' and tag `tag'. Currently only entities of dimension 2 (to recombine
2168      // triangles into quadrangles) are supported.
2169      inline void setRecombine(const int dim,
2170                               const int tag)
2171      {
2172        int ierr = 0;
2173        gmshModelMeshSetRecombine(dim, tag, &ierr);
2174        if(ierr) throwLastError();
2175      }
2176
2177      // Set a smoothing meshing constraint on the model entity of dimension `dim'
2178      // and tag `tag'. `val' iterations of a Laplace smoother are applied.
2179      inline void setSmoothing(const int dim,
2180                               const int tag,
2181                               const int val)
2182      {
2183        int ierr = 0;
2184        gmshModelMeshSetSmoothing(dim, tag, val, &ierr);
2185        if(ierr) throwLastError();
2186      }
2187
2188      // Set a reverse meshing constraint on the model entity of dimension `dim'
2189      // and tag `tag'. If `val' is true, the mesh orientation will be reversed
2190      // with respect to the natural mesh orientation (i.e. the orientation
2191      // consistent with the orientation of the geometry). If `val' is false, the
2192      // mesh is left as-is.
2193      inline void setReverse(const int dim,
2194                             const int tag,
2195                             const bool val = true)
2196      {
2197        int ierr = 0;
2198        gmshModelMeshSetReverse(dim, tag, (int)val, &ierr);
2199        if(ierr) throwLastError();
2200      }
2201
2202      // Set the meshing algorithm on the model entity of dimension `dim' and tag
2203      // `tag'. Currently only supported for `dim' == 2.
2204      inline void setAlgorithm(const int dim,
2205                               const int tag,
2206                               const int val)
2207      {
2208        int ierr = 0;
2209        gmshModelMeshSetAlgorithm(dim, tag, val, &ierr);
2210        if(ierr) throwLastError();
2211      }
2212
2213      // Force the mesh size to be extended from the boundary, or not, for the
2214      // model entity of dimension `dim' and tag `tag'. Currently only supported
2215      // for `dim' == 2.
2216      inline void setSizeFromBoundary(const int dim,
2217                                      const int tag,
2218                                      const int val)
2219      {
2220        int ierr = 0;
2221        gmshModelMeshSetSizeFromBoundary(dim, tag, val, &ierr);
2222        if(ierr) throwLastError();
2223      }
2224
2225      // Set a compound meshing constraint on the model entities of dimension `dim'
2226      // and tags `tags'. During meshing, compound entities are treated as a single
2227      // discrete entity, which is automatically reparametrized.
2228      inline void setCompound(const int dim,
2229                              const std::vector<int> & tags)
2230      {
2231        int ierr = 0;
2232        int *api_tags_; size_t api_tags_n_; vector2ptr(tags, &api_tags_, &api_tags_n_);
2233        gmshModelMeshSetCompound(dim, api_tags_, api_tags_n_, &ierr);
2234        if(ierr) throwLastError();
2235        gmshFree(api_tags_);
2236      }
2237
2238      // Set meshing constraints on the bounding surfaces of the volume of tag
2239      // `tag' so that all surfaces are oriented with outward pointing normals; and
2240      // if a mesh already exists, reorient it. Currently only available with the
2241      // OpenCASCADE kernel, as it relies on the STL triangulation.
2242      inline void setOutwardOrientation(const int tag)
2243      {
2244        int ierr = 0;
2245        gmshModelMeshSetOutwardOrientation(tag, &ierr);
2246        if(ierr) throwLastError();
2247      }
2248
2249      // Remove all meshing constraints from the model entities `dimTags'. If
2250      // `dimTags' is empty, remove all constraings.
2251      inline void removeConstraints(const gmsh::vectorpair & dimTags = gmsh::vectorpair())
2252      {
2253        int ierr = 0;
2254        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
2255        gmshModelMeshRemoveConstraints(api_dimTags_, api_dimTags_n_, &ierr);
2256        if(ierr) throwLastError();
2257        gmshFree(api_dimTags_);
2258      }
2259
2260      // Embed the model entities of dimension `dim' and tags `tags' in the
2261      // (`inDim', `inTag') model entity. The dimension `dim' can 0, 1 or 2 and
2262      // must be strictly smaller than `inDim', which must be either 2 or 3. The
2263      // embedded entities should not intersect each other or be part of the
2264      // boundary of the entity `inTag', whose mesh will conform to the mesh of the
2265      // embedded entities. With the OpenCASCADE kernel, if the `fragment'
2266      // operation is applied to entities of different dimensions, the lower
2267      // dimensional entities will be automatically embedded in the higher
2268      // dimensional entities if they are not on their boundary.
2269      inline void embed(const int dim,
2270                        const std::vector<int> & tags,
2271                        const int inDim,
2272                        const int inTag)
2273      {
2274        int ierr = 0;
2275        int *api_tags_; size_t api_tags_n_; vector2ptr(tags, &api_tags_, &api_tags_n_);
2276        gmshModelMeshEmbed(dim, api_tags_, api_tags_n_, inDim, inTag, &ierr);
2277        if(ierr) throwLastError();
2278        gmshFree(api_tags_);
2279      }
2280
2281      // Remove embedded entities from the model entities `dimTags'. if `dim' is >=
2282      // 0, only remove embedded entities of the given dimension (e.g. embedded
2283      // points if `dim' == 0).
2284      inline void removeEmbedded(const gmsh::vectorpair & dimTags,
2285                                 const int dim = -1)
2286      {
2287        int ierr = 0;
2288        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
2289        gmshModelMeshRemoveEmbedded(api_dimTags_, api_dimTags_n_, dim, &ierr);
2290        if(ierr) throwLastError();
2291        gmshFree(api_dimTags_);
2292      }
2293
2294      // Get the entities (if any) embedded in the model entity of dimension `dim'
2295      // and tag `tag'.
2296      inline void getEmbedded(const int dim,
2297                              const int tag,
2298                              gmsh::vectorpair & dimTags)
2299      {
2300        int ierr = 0;
2301        int *api_dimTags_; size_t api_dimTags_n_;
2302        gmshModelMeshGetEmbedded(dim, tag, &api_dimTags_, &api_dimTags_n_, &ierr);
2303        if(ierr) throwLastError();
2304        dimTags.resize(api_dimTags_n_ / 2); for(size_t i = 0; i < api_dimTags_n_ / 2; ++i){ dimTags[i].first = api_dimTags_[i * 2 + 0]; dimTags[i].second = api_dimTags_[i * 2 + 1]; } gmshFree(api_dimTags_);
2305      }
2306
2307      // Reorder the elements of type `elementType' classified on the entity of tag
2308      // `tag' according to `ordering'.
2309      inline void reorderElements(const int elementType,
2310                                  const int tag,
2311                                  const std::vector<std::size_t> & ordering)
2312      {
2313        int ierr = 0;
2314        size_t *api_ordering_; size_t api_ordering_n_; vector2ptr(ordering, &api_ordering_, &api_ordering_n_);
2315        gmshModelMeshReorderElements(elementType, tag, api_ordering_, api_ordering_n_, &ierr);
2316        if(ierr) throwLastError();
2317        gmshFree(api_ordering_);
2318      }
2319
2320      // Renumber the node tags in a continuous sequence.
2321      inline void renumberNodes()
2322      {
2323        int ierr = 0;
2324        gmshModelMeshRenumberNodes(&ierr);
2325        if(ierr) throwLastError();
2326      }
2327
2328      // Renumber the element tags in a continuous sequence.
2329      inline void renumberElements()
2330      {
2331        int ierr = 0;
2332        gmshModelMeshRenumberElements(&ierr);
2333        if(ierr) throwLastError();
2334      }
2335
2336      // Set the meshes of the entities of dimension `dim' and tag `tags' as
2337      // periodic copies of the meshes of entities `tagsMaster', using the affine
2338      // transformation specified in `affineTransformation' (16 entries of a 4x4
2339      // matrix, by row). If used after meshing, generate the periodic node
2340      // correspondence information assuming the meshes of entities `tags'
2341      // effectively match the meshes of entities `tagsMaster' (useful for
2342      // structured and extruded meshes). Currently only available for @code{dim}
2343      // == 1 and @code{dim} == 2.
2344      inline void setPeriodic(const int dim,
2345                              const std::vector<int> & tags,
2346                              const std::vector<int> & tagsMaster,
2347                              const std::vector<double> & affineTransform)
2348      {
2349        int ierr = 0;
2350        int *api_tags_; size_t api_tags_n_; vector2ptr(tags, &api_tags_, &api_tags_n_);
2351        int *api_tagsMaster_; size_t api_tagsMaster_n_; vector2ptr(tagsMaster, &api_tagsMaster_, &api_tagsMaster_n_);
2352        double *api_affineTransform_; size_t api_affineTransform_n_; vector2ptr(affineTransform, &api_affineTransform_, &api_affineTransform_n_);
2353        gmshModelMeshSetPeriodic(dim, api_tags_, api_tags_n_, api_tagsMaster_, api_tagsMaster_n_, api_affineTransform_, api_affineTransform_n_, &ierr);
2354        if(ierr) throwLastError();
2355        gmshFree(api_tags_);
2356        gmshFree(api_tagsMaster_);
2357        gmshFree(api_affineTransform_);
2358      }
2359
2360      // Get master entities `tagsMaster' for the entities of dimension `dim' and
2361      // tags `tags'.
2362      inline void getPeriodic(const int dim,
2363                              const std::vector<int> & tags,
2364                              std::vector<int> & tagMaster)
2365      {
2366        int ierr = 0;
2367        int *api_tags_; size_t api_tags_n_; vector2ptr(tags, &api_tags_, &api_tags_n_);
2368        int *api_tagMaster_; size_t api_tagMaster_n_;
2369        gmshModelMeshGetPeriodic(dim, api_tags_, api_tags_n_, &api_tagMaster_, &api_tagMaster_n_, &ierr);
2370        if(ierr) throwLastError();
2371        gmshFree(api_tags_);
2372        tagMaster.assign(api_tagMaster_, api_tagMaster_ + api_tagMaster_n_); gmshFree(api_tagMaster_);
2373      }
2374
2375      // Get the master entity `tagMaster', the node tags `nodeTags' and their
2376      // corresponding master node tags `nodeTagsMaster', and the affine transform
2377      // `affineTransform' for the entity of dimension `dim' and tag `tag'. If
2378      // `includeHighOrderNodes' is set, include high-order nodes in the returned
2379      // data.
2380      inline void getPeriodicNodes(const int dim,
2381                                   const int tag,
2382                                   int & tagMaster,
2383                                   std::vector<std::size_t> & nodeTags,
2384                                   std::vector<std::size_t> & nodeTagsMaster,
2385                                   std::vector<double> & affineTransform,
2386                                   const bool includeHighOrderNodes = false)
2387      {
2388        int ierr = 0;
2389        size_t *api_nodeTags_; size_t api_nodeTags_n_;
2390        size_t *api_nodeTagsMaster_; size_t api_nodeTagsMaster_n_;
2391        double *api_affineTransform_; size_t api_affineTransform_n_;
2392        gmshModelMeshGetPeriodicNodes(dim, tag, &tagMaster, &api_nodeTags_, &api_nodeTags_n_, &api_nodeTagsMaster_, &api_nodeTagsMaster_n_, &api_affineTransform_, &api_affineTransform_n_, (int)includeHighOrderNodes, &ierr);
2393        if(ierr) throwLastError();
2394        nodeTags.assign(api_nodeTags_, api_nodeTags_ + api_nodeTags_n_); gmshFree(api_nodeTags_);
2395        nodeTagsMaster.assign(api_nodeTagsMaster_, api_nodeTagsMaster_ + api_nodeTagsMaster_n_); gmshFree(api_nodeTagsMaster_);
2396        affineTransform.assign(api_affineTransform_, api_affineTransform_ + api_affineTransform_n_); gmshFree(api_affineTransform_);
2397      }
2398
2399      // Get the master entity `tagMaster' and the key pairs (`typeKeyMaster',
2400      // `entityKeyMaster') corresponding to the entity `tag' and the key pairs
2401      // (`typeKey', `entityKey') for the elements of type `elementType' and
2402      // function space type `functionSpaceType'. If `returnCoord' is set, the
2403      // `coord' and `coordMaster' vectors contain the x, y, z coordinates locating
2404      // basis functions for sorting purposes.
2405      inline void getPeriodicKeys(const int elementType,
2406                                  const std::string & functionSpaceType,
2407                                  const int tag,
2408                                  int & tagMaster,
2409                                  std::vector<int> & typeKeys,
2410                                  std::vector<int> & typeKeysMaster,
2411                                  std::vector<std::size_t> & entityKeys,
2412                                  std::vector<std::size_t> & entityKeysMaster,
2413                                  std::vector<double> & coord,
2414                                  std::vector<double> & coordMaster,
2415                                  const bool returnCoord = true)
2416      {
2417        int ierr = 0;
2418        int *api_typeKeys_; size_t api_typeKeys_n_;
2419        int *api_typeKeysMaster_; size_t api_typeKeysMaster_n_;
2420        size_t *api_entityKeys_; size_t api_entityKeys_n_;
2421        size_t *api_entityKeysMaster_; size_t api_entityKeysMaster_n_;
2422        double *api_coord_; size_t api_coord_n_;
2423        double *api_coordMaster_; size_t api_coordMaster_n_;
2424        gmshModelMeshGetPeriodicKeys(elementType, functionSpaceType.c_str(), tag, &tagMaster, &api_typeKeys_, &api_typeKeys_n_, &api_typeKeysMaster_, &api_typeKeysMaster_n_, &api_entityKeys_, &api_entityKeys_n_, &api_entityKeysMaster_, &api_entityKeysMaster_n_, &api_coord_, &api_coord_n_, &api_coordMaster_, &api_coordMaster_n_, (int)returnCoord, &ierr);
2425        if(ierr) throwLastError();
2426        typeKeys.assign(api_typeKeys_, api_typeKeys_ + api_typeKeys_n_); gmshFree(api_typeKeys_);
2427        typeKeysMaster.assign(api_typeKeysMaster_, api_typeKeysMaster_ + api_typeKeysMaster_n_); gmshFree(api_typeKeysMaster_);
2428        entityKeys.assign(api_entityKeys_, api_entityKeys_ + api_entityKeys_n_); gmshFree(api_entityKeys_);
2429        entityKeysMaster.assign(api_entityKeysMaster_, api_entityKeysMaster_ + api_entityKeysMaster_n_); gmshFree(api_entityKeysMaster_);
2430        coord.assign(api_coord_, api_coord_ + api_coord_n_); gmshFree(api_coord_);
2431        coordMaster.assign(api_coordMaster_, api_coordMaster_ + api_coordMaster_n_); gmshFree(api_coordMaster_);
2432      }
2433
2434      // Remove duplicate nodes in the mesh of the current model.
2435      inline void removeDuplicateNodes()
2436      {
2437        int ierr = 0;
2438        gmshModelMeshRemoveDuplicateNodes(&ierr);
2439        if(ierr) throwLastError();
2440      }
2441
2442      // Split (into two triangles) all quadrangles in surface `tag' whose quality
2443      // is lower than `quality'. If `tag' < 0, split quadrangles in all surfaces.
2444      inline void splitQuadrangles(const double quality = 1.,
2445                                   const int tag = -1)
2446      {
2447        int ierr = 0;
2448        gmshModelMeshSplitQuadrangles(quality, tag, &ierr);
2449        if(ierr) throwLastError();
2450      }
2451
2452      // Classify ("color") the surface mesh based on the angle threshold `angle'
2453      // (in radians), and create new discrete surfaces, curves and points
2454      // accordingly. If `boundary' is set, also create discrete curves on the
2455      // boundary if the surface is open. If `forReparametrization' is set, create
2456      // curves and surfaces that can be reparametrized using a single map. If
2457      // `curveAngle' is less than Pi, also force curves to be split according to
2458      // `curveAngle'. If `exportDiscrete' is set, clear any built-in CAD kernel
2459      // entities and export the discrete entities in the built-in CAD kernel.
2460      inline void classifySurfaces(const double angle,
2461                                   const bool boundary = true,
2462                                   const bool forReparametrization = false,
2463                                   const double curveAngle = M_PI,
2464                                   const bool exportDiscrete = true)
2465      {
2466        int ierr = 0;
2467        gmshModelMeshClassifySurfaces(angle, (int)boundary, (int)forReparametrization, curveAngle, (int)exportDiscrete, &ierr);
2468        if(ierr) throwLastError();
2469      }
2470
2471      // Create a geometry for the discrete entities `dimTags' (represented solely
2472      // by a mesh, without an underlying CAD description), i.e. create a
2473      // parametrization for discrete curves and surfaces, assuming that each can
2474      // be parametrized with a single map. If `dimTags' is empty, create a
2475      // geometry for all the discrete entities.
2476      inline void createGeometry(const gmsh::vectorpair & dimTags = gmsh::vectorpair())
2477      {
2478        int ierr = 0;
2479        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
2480        gmshModelMeshCreateGeometry(api_dimTags_, api_dimTags_n_, &ierr);
2481        if(ierr) throwLastError();
2482        gmshFree(api_dimTags_);
2483      }
2484
2485      // Create a boundary representation from the mesh if the model does not have
2486      // one (e.g. when imported from mesh file formats with no BRep representation
2487      // of the underlying model). If `makeSimplyConnected' is set, enforce simply
2488      // connected discrete surfaces and volumes. If `exportDiscrete' is set, clear
2489      // any built-in CAD kernel entities and export the discrete entities in the
2490      // built-in CAD kernel.
2491      inline void createTopology(const bool makeSimplyConnected = true,
2492                                 const bool exportDiscrete = true)
2493      {
2494        int ierr = 0;
2495        gmshModelMeshCreateTopology((int)makeSimplyConnected, (int)exportDiscrete, &ierr);
2496        if(ierr) throwLastError();
2497      }
2498
2499      // Compute a basis representation for homology spaces after a mesh has been
2500      // generated. The computation domain is given in a list of physical group
2501      // tags `domainTags'; if empty, the whole mesh is the domain. The computation
2502      // subdomain for relative homology computation is given in a list of physical
2503      // group tags `subdomainTags'; if empty, absolute homology is computed. The
2504      // dimensions homology bases to be computed are given in the list `dim'; if
2505      // empty, all bases are computed. Resulting basis representation chains are
2506      // stored as physical groups in the mesh.
2507      inline void computeHomology(const std::vector<int> & domainTags = std::vector<int>(),
2508                                  const std::vector<int> & subdomainTags = std::vector<int>(),
2509                                  const std::vector<int> & dims = std::vector<int>())
2510      {
2511        int ierr = 0;
2512        int *api_domainTags_; size_t api_domainTags_n_; vector2ptr(domainTags, &api_domainTags_, &api_domainTags_n_);
2513        int *api_subdomainTags_; size_t api_subdomainTags_n_; vector2ptr(subdomainTags, &api_subdomainTags_, &api_subdomainTags_n_);
2514        int *api_dims_; size_t api_dims_n_; vector2ptr(dims, &api_dims_, &api_dims_n_);
2515        gmshModelMeshComputeHomology(api_domainTags_, api_domainTags_n_, api_subdomainTags_, api_subdomainTags_n_, api_dims_, api_dims_n_, &ierr);
2516        if(ierr) throwLastError();
2517        gmshFree(api_domainTags_);
2518        gmshFree(api_subdomainTags_);
2519        gmshFree(api_dims_);
2520      }
2521
2522      // Compute a basis representation for cohomology spaces after a mesh has been
2523      // generated. The computation domain is given in a list of physical group
2524      // tags `domainTags'; if empty, the whole mesh is the domain. The computation
2525      // subdomain for relative cohomology computation is given in a list of
2526      // physical group tags `subdomainTags'; if empty, absolute cohomology is
2527      // computed. The dimensions homology bases to be computed are given in the
2528      // list `dim'; if empty, all bases are computed. Resulting basis
2529      // representation cochains are stored as physical groups in the mesh.
2530      inline void computeCohomology(const std::vector<int> & domainTags = std::vector<int>(),
2531                                    const std::vector<int> & subdomainTags = std::vector<int>(),
2532                                    const std::vector<int> & dims = std::vector<int>())
2533      {
2534        int ierr = 0;
2535        int *api_domainTags_; size_t api_domainTags_n_; vector2ptr(domainTags, &api_domainTags_, &api_domainTags_n_);
2536        int *api_subdomainTags_; size_t api_subdomainTags_n_; vector2ptr(subdomainTags, &api_subdomainTags_, &api_subdomainTags_n_);
2537        int *api_dims_; size_t api_dims_n_; vector2ptr(dims, &api_dims_, &api_dims_n_);
2538        gmshModelMeshComputeCohomology(api_domainTags_, api_domainTags_n_, api_subdomainTags_, api_subdomainTags_n_, api_dims_, api_dims_n_, &ierr);
2539        if(ierr) throwLastError();
2540        gmshFree(api_domainTags_);
2541        gmshFree(api_subdomainTags_);
2542        gmshFree(api_dims_);
2543      }
2544
2545      // Compute a cross field for the current mesh. The function creates 3 views:
2546      // the H function, the Theta function and cross directions. Return the tags
2547      // of the views.
2548      inline void computeCrossField(std::vector<int> & viewTags)
2549      {
2550        int ierr = 0;
2551        int *api_viewTags_; size_t api_viewTags_n_;
2552        gmshModelMeshComputeCrossField(&api_viewTags_, &api_viewTags_n_, &ierr);
2553        if(ierr) throwLastError();
2554        viewTags.assign(api_viewTags_, api_viewTags_ + api_viewTags_n_); gmshFree(api_viewTags_);
2555      }
2556
2557      // Triangulate the points given in the `coord' vector as pairs of u, v
2558      // coordinates, and return the node tags (with numbering starting at 1) of
2559      // the resulting triangles in `tri'.
2560      inline void triangulate(const std::vector<double> & coord,
2561                              std::vector<std::size_t> & tri)
2562      {
2563        int ierr = 0;
2564        double *api_coord_; size_t api_coord_n_; vector2ptr(coord, &api_coord_, &api_coord_n_);
2565        size_t *api_tri_; size_t api_tri_n_;
2566        gmshModelMeshTriangulate(api_coord_, api_coord_n_, &api_tri_, &api_tri_n_, &ierr);
2567        if(ierr) throwLastError();
2568        gmshFree(api_coord_);
2569        tri.assign(api_tri_, api_tri_ + api_tri_n_); gmshFree(api_tri_);
2570      }
2571
2572      // Tetrahedralize the points given in the `coord' vector as triplets of x, y,
2573      // z coordinates, and return the node tags (with numbering starting at 1) of
2574      // the resulting tetrahedra in `tetra'.
2575      inline void tetrahedralize(const std::vector<double> & coord,
2576                                 std::vector<std::size_t> & tetra)
2577      {
2578        int ierr = 0;
2579        double *api_coord_; size_t api_coord_n_; vector2ptr(coord, &api_coord_, &api_coord_n_);
2580        size_t *api_tetra_; size_t api_tetra_n_;
2581        gmshModelMeshTetrahedralize(api_coord_, api_coord_n_, &api_tetra_, &api_tetra_n_, &ierr);
2582        if(ierr) throwLastError();
2583        gmshFree(api_coord_);
2584        tetra.assign(api_tetra_, api_tetra_ + api_tetra_n_); gmshFree(api_tetra_);
2585      }
2586
2587      namespace field { // Mesh size field functions
2588
2589        // Add a new mesh size field of type `fieldType'. If `tag' is positive,
2590        // assign the tag explicitly; otherwise a new tag is assigned
2591        // automatically. Return the field tag.
2592        inline int add(const std::string & fieldType,
2593                       const int tag = -1)
2594        {
2595          int ierr = 0;
2596          int result_api_ = gmshModelMeshFieldAdd(fieldType.c_str(), tag, &ierr);
2597          if(ierr) throwLastError();
2598          return result_api_;
2599        }
2600
2601        // Remove the field with tag `tag'.
2602        inline void remove(const int tag)
2603        {
2604          int ierr = 0;
2605          gmshModelMeshFieldRemove(tag, &ierr);
2606          if(ierr) throwLastError();
2607        }
2608
2609        // Get the list of all fields.
2610        inline void list(std::vector<int> & tags)
2611        {
2612          int ierr = 0;
2613          int *api_tags_; size_t api_tags_n_;
2614          gmshModelMeshFieldList(&api_tags_, &api_tags_n_, &ierr);
2615          if(ierr) throwLastError();
2616          tags.assign(api_tags_, api_tags_ + api_tags_n_); gmshFree(api_tags_);
2617        }
2618
2619        // Get the type `fieldType' of the field with tag `tag'.
2620        inline void getType(const int tag,
2621                            std::string & fileType)
2622        {
2623          int ierr = 0;
2624          char *api_fileType_;
2625          gmshModelMeshFieldGetType(tag, &api_fileType_, &ierr);
2626          if(ierr) throwLastError();
2627          fileType = std::string(api_fileType_); gmshFree(api_fileType_);
2628        }
2629
2630        // Set the numerical option `option' to value `value' for field `tag'.
2631        inline void setNumber(const int tag,
2632                              const std::string & option,
2633                              const double value)
2634        {
2635          int ierr = 0;
2636          gmshModelMeshFieldSetNumber(tag, option.c_str(), value, &ierr);
2637          if(ierr) throwLastError();
2638        }
2639
2640        // Get the value of the numerical option `option' for field `tag'.
2641        inline void getNumber(const int tag,
2642                              const std::string & option,
2643                              double & value)
2644        {
2645          int ierr = 0;
2646          gmshModelMeshFieldGetNumber(tag, option.c_str(), &value, &ierr);
2647          if(ierr) throwLastError();
2648        }
2649
2650        // Set the string option `option' to value `value' for field `tag'.
2651        inline void setString(const int tag,
2652                              const std::string & option,
2653                              const std::string & value)
2654        {
2655          int ierr = 0;
2656          gmshModelMeshFieldSetString(tag, option.c_str(), value.c_str(), &ierr);
2657          if(ierr) throwLastError();
2658        }
2659
2660        // Get the value of the string option `option' for field `tag'.
2661        inline void getString(const int tag,
2662                              const std::string & option,
2663                              std::string & value)
2664        {
2665          int ierr = 0;
2666          char *api_value_;
2667          gmshModelMeshFieldGetString(tag, option.c_str(), &api_value_, &ierr);
2668          if(ierr) throwLastError();
2669          value = std::string(api_value_); gmshFree(api_value_);
2670        }
2671
2672        // Set the numerical list option `option' to value `value' for field `tag'.
2673        inline void setNumbers(const int tag,
2674                               const std::string & option,
2675                               const std::vector<double> & value)
2676        {
2677          int ierr = 0;
2678          double *api_value_; size_t api_value_n_; vector2ptr(value, &api_value_, &api_value_n_);
2679          gmshModelMeshFieldSetNumbers(tag, option.c_str(), api_value_, api_value_n_, &ierr);
2680          if(ierr) throwLastError();
2681          gmshFree(api_value_);
2682        }
2683
2684        // Get the value of the numerical list option `option' for field `tag'.
2685        inline void getNumbers(const int tag,
2686                               const std::string & option,
2687                               std::vector<double> & value)
2688        {
2689          int ierr = 0;
2690          double *api_value_; size_t api_value_n_;
2691          gmshModelMeshFieldGetNumbers(tag, option.c_str(), &api_value_, &api_value_n_, &ierr);
2692          if(ierr) throwLastError();
2693          value.assign(api_value_, api_value_ + api_value_n_); gmshFree(api_value_);
2694        }
2695
2696        // Set the field `tag' as the background mesh size field.
2697        inline void setAsBackgroundMesh(const int tag)
2698        {
2699          int ierr = 0;
2700          gmshModelMeshFieldSetAsBackgroundMesh(tag, &ierr);
2701          if(ierr) throwLastError();
2702        }
2703
2704        // Set the field `tag' as a boundary layer size field.
2705        inline void setAsBoundaryLayer(const int tag)
2706        {
2707          int ierr = 0;
2708          gmshModelMeshFieldSetAsBoundaryLayer(tag, &ierr);
2709          if(ierr) throwLastError();
2710        }
2711
2712      } // namespace field
2713
2714    } // namespace mesh
2715
2716    namespace geo { // Built-in CAD kernel functions
2717
2718      // Add a geometrical point in the built-in CAD representation, at coordinates
2719      // (`x', `y', `z'). If `meshSize' is > 0, add a meshing constraint at that
2720      // point. If `tag' is positive, set the tag explicitly; otherwise a new tag
2721      // is selected automatically. Return the tag of the point. (Note that the
2722      // point will be added in the current model only after `synchronize' is
2723      // called. This behavior holds for all the entities added in the geo module.)
2724      inline int addPoint(const double x,
2725                          const double y,
2726                          const double z,
2727                          const double meshSize = 0.,
2728                          const int tag = -1)
2729      {
2730        int ierr = 0;
2731        int result_api_ = gmshModelGeoAddPoint(x, y, z, meshSize, tag, &ierr);
2732        if(ierr) throwLastError();
2733        return result_api_;
2734      }
2735
2736      // Add a straight line segment in the built-in CAD representation, between
2737      // the two points with tags `startTag' and `endTag'. If `tag' is positive,
2738      // set the tag explicitly; otherwise a new tag is selected automatically.
2739      // Return the tag of the line.
2740      inline int addLine(const int startTag,
2741                         const int endTag,
2742                         const int tag = -1)
2743      {
2744        int ierr = 0;
2745        int result_api_ = gmshModelGeoAddLine(startTag, endTag, tag, &ierr);
2746        if(ierr) throwLastError();
2747        return result_api_;
2748      }
2749
2750      // Add a circle arc (strictly smaller than Pi) in the built-in CAD
2751      // representation, between the two points with tags `startTag' and `endTag',
2752      // and with center `centerTag'. If `tag' is positive, set the tag explicitly;
2753      // otherwise a new tag is selected automatically. If (`nx', `ny', `nz') !=
2754      // (0, 0, 0), explicitly set the plane of the circle arc. Return the tag of
2755      // the circle arc.
2756      inline int addCircleArc(const int startTag,
2757                              const int centerTag,
2758                              const int endTag,
2759                              const int tag = -1,
2760                              const double nx = 0.,
2761                              const double ny = 0.,
2762                              const double nz = 0.)
2763      {
2764        int ierr = 0;
2765        int result_api_ = gmshModelGeoAddCircleArc(startTag, centerTag, endTag, tag, nx, ny, nz, &ierr);
2766        if(ierr) throwLastError();
2767        return result_api_;
2768      }
2769
2770      // Add an ellipse arc (strictly smaller than Pi) in the built-in CAD
2771      // representation, between the two points `startTag' and `endTag', and with
2772      // center `centerTag' and major axis point `majorTag'. If `tag' is positive,
2773      // set the tag explicitly; otherwise a new tag is selected automatically. If
2774      // (`nx', `ny', `nz') != (0, 0, 0), explicitly set the plane of the circle
2775      // arc. Return the tag of the ellipse arc.
2776      inline int addEllipseArc(const int startTag,
2777                               const int centerTag,
2778                               const int majorTag,
2779                               const int endTag,
2780                               const int tag = -1,
2781                               const double nx = 0.,
2782                               const double ny = 0.,
2783                               const double nz = 0.)
2784      {
2785        int ierr = 0;
2786        int result_api_ = gmshModelGeoAddEllipseArc(startTag, centerTag, majorTag, endTag, tag, nx, ny, nz, &ierr);
2787        if(ierr) throwLastError();
2788        return result_api_;
2789      }
2790
2791      // Add a spline (Catmull-Rom) curve in the built-in CAD representation, going
2792      // through the points `pointTags'. If `tag' is positive, set the tag
2793      // explicitly; otherwise a new tag is selected automatically. Create a
2794      // periodic curve if the first and last points are the same. Return the tag
2795      // of the spline curve.
2796      inline int addSpline(const std::vector<int> & pointTags,
2797                           const int tag = -1)
2798      {
2799        int ierr = 0;
2800        int *api_pointTags_; size_t api_pointTags_n_; vector2ptr(pointTags, &api_pointTags_, &api_pointTags_n_);
2801        int result_api_ = gmshModelGeoAddSpline(api_pointTags_, api_pointTags_n_, tag, &ierr);
2802        if(ierr) throwLastError();
2803        gmshFree(api_pointTags_);
2804        return result_api_;
2805      }
2806
2807      // Add a cubic b-spline curve in the built-in CAD representation, with
2808      // `pointTags' control points. If `tag' is positive, set the tag explicitly;
2809      // otherwise a new tag is selected automatically. Creates a periodic curve if
2810      // the first and last points are the same. Return the tag of the b-spline
2811      // curve.
2812      inline int addBSpline(const std::vector<int> & pointTags,
2813                            const int tag = -1)
2814      {
2815        int ierr = 0;
2816        int *api_pointTags_; size_t api_pointTags_n_; vector2ptr(pointTags, &api_pointTags_, &api_pointTags_n_);
2817        int result_api_ = gmshModelGeoAddBSpline(api_pointTags_, api_pointTags_n_, tag, &ierr);
2818        if(ierr) throwLastError();
2819        gmshFree(api_pointTags_);
2820        return result_api_;
2821      }
2822
2823      // Add a Bezier curve in the built-in CAD representation, with `pointTags'
2824      // control points. If `tag' is positive, set the tag explicitly; otherwise a
2825      // new tag is selected automatically.  Return the tag of the Bezier curve.
2826      inline int addBezier(const std::vector<int> & pointTags,
2827                           const int tag = -1)
2828      {
2829        int ierr = 0;
2830        int *api_pointTags_; size_t api_pointTags_n_; vector2ptr(pointTags, &api_pointTags_, &api_pointTags_n_);
2831        int result_api_ = gmshModelGeoAddBezier(api_pointTags_, api_pointTags_n_, tag, &ierr);
2832        if(ierr) throwLastError();
2833        gmshFree(api_pointTags_);
2834        return result_api_;
2835      }
2836
2837      // Add a polyline curve in the built-in CAD representation, going through the
2838      // points `pointTags'. If `tag' is positive, set the tag explicitly;
2839      // otherwise a new tag is selected automatically. Create a periodic curve if
2840      // the first and last points are the same. Return the tag of the polyline
2841      // curve.
2842      inline int addPolyline(const std::vector<int> & pointTags,
2843                             const int tag = -1)
2844      {
2845        int ierr = 0;
2846        int *api_pointTags_; size_t api_pointTags_n_; vector2ptr(pointTags, &api_pointTags_, &api_pointTags_n_);
2847        int result_api_ = gmshModelGeoAddPolyline(api_pointTags_, api_pointTags_n_, tag, &ierr);
2848        if(ierr) throwLastError();
2849        gmshFree(api_pointTags_);
2850        return result_api_;
2851      }
2852
2853      // Add a spline (Catmull-Rom) curve in the built-in CAD representation, going
2854      // through points sampling the curves in `curveTags'. The density of sampling
2855      // points on each curve is governed by `numIntervals'. If `tag' is positive,
2856      // set the tag explicitly; otherwise a new tag is selected automatically.
2857      // Return the tag of the spline.
2858      inline int addCompoundSpline(const std::vector<int> & curveTags,
2859                                   const int numIntervals = 5,
2860                                   const int tag = -1)
2861      {
2862        int ierr = 0;
2863        int *api_curveTags_; size_t api_curveTags_n_; vector2ptr(curveTags, &api_curveTags_, &api_curveTags_n_);
2864        int result_api_ = gmshModelGeoAddCompoundSpline(api_curveTags_, api_curveTags_n_, numIntervals, tag, &ierr);
2865        if(ierr) throwLastError();
2866        gmshFree(api_curveTags_);
2867        return result_api_;
2868      }
2869
2870      // Add a b-spline curve in the built-in CAD representation, with control
2871      // points sampling the curves in `curveTags'. The density of sampling points
2872      // on each curve is governed by `numIntervals'. If `tag' is positive, set the
2873      // tag explicitly; otherwise a new tag is selected automatically. Return the
2874      // tag of the b-spline.
2875      inline int addCompoundBSpline(const std::vector<int> & curveTags,
2876                                    const int numIntervals = 20,
2877                                    const int tag = -1)
2878      {
2879        int ierr = 0;
2880        int *api_curveTags_; size_t api_curveTags_n_; vector2ptr(curveTags, &api_curveTags_, &api_curveTags_n_);
2881        int result_api_ = gmshModelGeoAddCompoundBSpline(api_curveTags_, api_curveTags_n_, numIntervals, tag, &ierr);
2882        if(ierr) throwLastError();
2883        gmshFree(api_curveTags_);
2884        return result_api_;
2885      }
2886
2887      // Add a curve loop (a closed wire) in the built-in CAD representation,
2888      // formed by the curves `curveTags'. `curveTags' should contain (signed) tags
2889      // of model entities of dimension 1 forming a closed loop: a negative tag
2890      // signifies that the underlying curve is considered with reversed
2891      // orientation. If `tag' is positive, set the tag explicitly; otherwise a new
2892      // tag is selected automatically. If `reorient' is set, automatically
2893      // reorient the curves if necessary. Return the tag of the curve loop.
2894      inline int addCurveLoop(const std::vector<int> & curveTags,
2895                              const int tag = -1,
2896                              const bool reorient = false)
2897      {
2898        int ierr = 0;
2899        int *api_curveTags_; size_t api_curveTags_n_; vector2ptr(curveTags, &api_curveTags_, &api_curveTags_n_);
2900        int result_api_ = gmshModelGeoAddCurveLoop(api_curveTags_, api_curveTags_n_, tag, (int)reorient, &ierr);
2901        if(ierr) throwLastError();
2902        gmshFree(api_curveTags_);
2903        return result_api_;
2904      }
2905
2906      // Add curve loops in the built-in CAD representation based on the curves
2907      // `curveTags'. Return the `tags' of found curve loops, if any.
2908      inline void addCurveLoops(const std::vector<int> & curveTags,
2909                                std::vector<int> & tags)
2910      {
2911        int ierr = 0;
2912        int *api_curveTags_; size_t api_curveTags_n_; vector2ptr(curveTags, &api_curveTags_, &api_curveTags_n_);
2913        int *api_tags_; size_t api_tags_n_;
2914        gmshModelGeoAddCurveLoops(api_curveTags_, api_curveTags_n_, &api_tags_, &api_tags_n_, &ierr);
2915        if(ierr) throwLastError();
2916        gmshFree(api_curveTags_);
2917        tags.assign(api_tags_, api_tags_ + api_tags_n_); gmshFree(api_tags_);
2918      }
2919
2920      // Add a plane surface in the built-in CAD representation, defined by one or
2921      // more curve loops `wireTags'. The first curve loop defines the exterior
2922      // contour; additional curve loop define holes. If `tag' is positive, set the
2923      // tag explicitly; otherwise a new tag is selected automatically. Return the
2924      // tag of the surface.
2925      inline int addPlaneSurface(const std::vector<int> & wireTags,
2926                                 const int tag = -1)
2927      {
2928        int ierr = 0;
2929        int *api_wireTags_; size_t api_wireTags_n_; vector2ptr(wireTags, &api_wireTags_, &api_wireTags_n_);
2930        int result_api_ = gmshModelGeoAddPlaneSurface(api_wireTags_, api_wireTags_n_, tag, &ierr);
2931        if(ierr) throwLastError();
2932        gmshFree(api_wireTags_);
2933        return result_api_;
2934      }
2935
2936      // Add a surface in the built-in CAD representation, filling the curve loops
2937      // in `wireTags' using transfinite interpolation. Currently only a single
2938      // curve loop is supported; this curve loop should be composed by 3 or 4
2939      // curves only. If `tag' is positive, set the tag explicitly; otherwise a new
2940      // tag is selected automatically. Return the tag of the surface.
2941      inline int addSurfaceFilling(const std::vector<int> & wireTags,
2942                                   const int tag = -1,
2943                                   const int sphereCenterTag = -1)
2944      {
2945        int ierr = 0;
2946        int *api_wireTags_; size_t api_wireTags_n_; vector2ptr(wireTags, &api_wireTags_, &api_wireTags_n_);
2947        int result_api_ = gmshModelGeoAddSurfaceFilling(api_wireTags_, api_wireTags_n_, tag, sphereCenterTag, &ierr);
2948        if(ierr) throwLastError();
2949        gmshFree(api_wireTags_);
2950        return result_api_;
2951      }
2952
2953      // Add a surface loop (a closed shell) formed by `surfaceTags' in the built-
2954      // in CAD representation.  If `tag' is positive, set the tag explicitly;
2955      // otherwise a new tag is selected automatically. Return the tag of the
2956      // shell.
2957      inline int addSurfaceLoop(const std::vector<int> & surfaceTags,
2958                                const int tag = -1)
2959      {
2960        int ierr = 0;
2961        int *api_surfaceTags_; size_t api_surfaceTags_n_; vector2ptr(surfaceTags, &api_surfaceTags_, &api_surfaceTags_n_);
2962        int result_api_ = gmshModelGeoAddSurfaceLoop(api_surfaceTags_, api_surfaceTags_n_, tag, &ierr);
2963        if(ierr) throwLastError();
2964        gmshFree(api_surfaceTags_);
2965        return result_api_;
2966      }
2967
2968      // Add a volume (a region) in the built-in CAD representation, defined by one
2969      // or more shells `shellTags'. The first surface loop defines the exterior
2970      // boundary; additional surface loop define holes. If `tag' is positive, set
2971      // the tag explicitly; otherwise a new tag is selected automatically. Return
2972      // the tag of the volume.
2973      inline int addVolume(const std::vector<int> & shellTags,
2974                           const int tag = -1)
2975      {
2976        int ierr = 0;
2977        int *api_shellTags_; size_t api_shellTags_n_; vector2ptr(shellTags, &api_shellTags_, &api_shellTags_n_);
2978        int result_api_ = gmshModelGeoAddVolume(api_shellTags_, api_shellTags_n_, tag, &ierr);
2979        if(ierr) throwLastError();
2980        gmshFree(api_shellTags_);
2981        return result_api_;
2982      }
2983
2984      // Extrude the entities `dimTags' in the built-in CAD representation, using a
2985      // translation along (`dx', `dy', `dz'). Return extruded entities in
2986      // `outDimTags'. If `numElements' is not empty, also extrude the mesh: the
2987      // entries in `numElements' give the number of elements in each layer. If
2988      // `height' is not empty, it provides the (cumulative) height of the
2989      // different layers, normalized to 1. If `recombine' is set, recombine the
2990      // mesh in the layers.
2991      inline void extrude(const gmsh::vectorpair & dimTags,
2992                          const double dx,
2993                          const double dy,
2994                          const double dz,
2995                          gmsh::vectorpair & outDimTags,
2996                          const std::vector<int> & numElements = std::vector<int>(),
2997                          const std::vector<double> & heights = std::vector<double>(),
2998                          const bool recombine = false)
2999      {
3000        int ierr = 0;
3001        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
3002        int *api_outDimTags_; size_t api_outDimTags_n_;
3003        int *api_numElements_; size_t api_numElements_n_; vector2ptr(numElements, &api_numElements_, &api_numElements_n_);
3004        double *api_heights_; size_t api_heights_n_; vector2ptr(heights, &api_heights_, &api_heights_n_);
3005        gmshModelGeoExtrude(api_dimTags_, api_dimTags_n_, dx, dy, dz, &api_outDimTags_, &api_outDimTags_n_, api_numElements_, api_numElements_n_, api_heights_, api_heights_n_, (int)recombine, &ierr);
3006        if(ierr) throwLastError();
3007        gmshFree(api_dimTags_);
3008        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
3009        gmshFree(api_numElements_);
3010        gmshFree(api_heights_);
3011      }
3012
3013      // Extrude the entities `dimTags' in the built-in CAD representation, using a
3014      // rotation of `angle' radians around the axis of revolution defined by the
3015      // point (`x', `y', `z') and the direction (`ax', `ay', `az'). The angle
3016      // should be strictly smaller than Pi. Return extruded entities in
3017      // `outDimTags'. If `numElements' is not empty, also extrude the mesh: the
3018      // entries in `numElements' give the number of elements in each layer. If
3019      // `height' is not empty, it provides the (cumulative) height of the
3020      // different layers, normalized to 1. If `recombine' is set, recombine the
3021      // mesh in the layers.
3022      inline void revolve(const gmsh::vectorpair & dimTags,
3023                          const double x,
3024                          const double y,
3025                          const double z,
3026                          const double ax,
3027                          const double ay,
3028                          const double az,
3029                          const double angle,
3030                          gmsh::vectorpair & outDimTags,
3031                          const std::vector<int> & numElements = std::vector<int>(),
3032                          const std::vector<double> & heights = std::vector<double>(),
3033                          const bool recombine = false)
3034      {
3035        int ierr = 0;
3036        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
3037        int *api_outDimTags_; size_t api_outDimTags_n_;
3038        int *api_numElements_; size_t api_numElements_n_; vector2ptr(numElements, &api_numElements_, &api_numElements_n_);
3039        double *api_heights_; size_t api_heights_n_; vector2ptr(heights, &api_heights_, &api_heights_n_);
3040        gmshModelGeoRevolve(api_dimTags_, api_dimTags_n_, x, y, z, ax, ay, az, angle, &api_outDimTags_, &api_outDimTags_n_, api_numElements_, api_numElements_n_, api_heights_, api_heights_n_, (int)recombine, &ierr);
3041        if(ierr) throwLastError();
3042        gmshFree(api_dimTags_);
3043        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
3044        gmshFree(api_numElements_);
3045        gmshFree(api_heights_);
3046      }
3047
3048      // Extrude the entities `dimTags' in the built-in CAD representation, using a
3049      // combined translation and rotation of `angle' radians, along (`dx', `dy',
3050      // `dz') and around the axis of revolution defined by the point (`x', `y',
3051      // `z') and the direction (`ax', `ay', `az'). The angle should be strictly
3052      // smaller than Pi. Return extruded entities in `outDimTags'. If
3053      // `numElements' is not empty, also extrude the mesh: the entries in
3054      // `numElements' give the number of elements in each layer. If `height' is
3055      // not empty, it provides the (cumulative) height of the different layers,
3056      // normalized to 1. If `recombine' is set, recombine the mesh in the layers.
3057      inline void twist(const gmsh::vectorpair & dimTags,
3058                        const double x,
3059                        const double y,
3060                        const double z,
3061                        const double dx,
3062                        const double dy,
3063                        const double dz,
3064                        const double ax,
3065                        const double ay,
3066                        const double az,
3067                        const double angle,
3068                        gmsh::vectorpair & outDimTags,
3069                        const std::vector<int> & numElements = std::vector<int>(),
3070                        const std::vector<double> & heights = std::vector<double>(),
3071                        const bool recombine = false)
3072      {
3073        int ierr = 0;
3074        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
3075        int *api_outDimTags_; size_t api_outDimTags_n_;
3076        int *api_numElements_; size_t api_numElements_n_; vector2ptr(numElements, &api_numElements_, &api_numElements_n_);
3077        double *api_heights_; size_t api_heights_n_; vector2ptr(heights, &api_heights_, &api_heights_n_);
3078        gmshModelGeoTwist(api_dimTags_, api_dimTags_n_, x, y, z, dx, dy, dz, ax, ay, az, angle, &api_outDimTags_, &api_outDimTags_n_, api_numElements_, api_numElements_n_, api_heights_, api_heights_n_, (int)recombine, &ierr);
3079        if(ierr) throwLastError();
3080        gmshFree(api_dimTags_);
3081        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
3082        gmshFree(api_numElements_);
3083        gmshFree(api_heights_);
3084      }
3085
3086      // Extrude the entities `dimTags' in the built-in CAD representation along
3087      // the normals of the mesh, creating discrete boundary layer entities. Return
3088      // extruded entities in `outDimTags'. The entries in `numElements' give the
3089      // number of elements in each layer. If `height' is not empty, it provides
3090      // the height of the different layers. If `recombine' is set, recombine the
3091      // mesh in the layers. A second boundary layer can be created from the same
3092      // entities if `second' is set. If `viewIndex' is >= 0, use the corresponding
3093      // view to either specify the normals (if the view contains a vector field)
3094      // or scale the normals (if the view is scalar).
3095      inline void extrudeBoundaryLayer(const gmsh::vectorpair & dimTags,
3096                                       gmsh::vectorpair & outDimTags,
3097                                       const std::vector<int> & numElements = std::vector<int>(1, 1),
3098                                       const std::vector<double> & heights = std::vector<double>(),
3099                                       const bool recombine = false,
3100                                       const bool second = false,
3101                                       const int viewIndex = -1)
3102      {
3103        int ierr = 0;
3104        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
3105        int *api_outDimTags_; size_t api_outDimTags_n_;
3106        int *api_numElements_; size_t api_numElements_n_; vector2ptr(numElements, &api_numElements_, &api_numElements_n_);
3107        double *api_heights_; size_t api_heights_n_; vector2ptr(heights, &api_heights_, &api_heights_n_);
3108        gmshModelGeoExtrudeBoundaryLayer(api_dimTags_, api_dimTags_n_, &api_outDimTags_, &api_outDimTags_n_, api_numElements_, api_numElements_n_, api_heights_, api_heights_n_, (int)recombine, (int)second, viewIndex, &ierr);
3109        if(ierr) throwLastError();
3110        gmshFree(api_dimTags_);
3111        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
3112        gmshFree(api_numElements_);
3113        gmshFree(api_heights_);
3114      }
3115
3116      // Translate the entities `dimTags' in the built-in CAD representation along
3117      // (`dx', `dy', `dz').
3118      inline void translate(const gmsh::vectorpair & dimTags,
3119                            const double dx,
3120                            const double dy,
3121                            const double dz)
3122      {
3123        int ierr = 0;
3124        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
3125        gmshModelGeoTranslate(api_dimTags_, api_dimTags_n_, dx, dy, dz, &ierr);
3126        if(ierr) throwLastError();
3127        gmshFree(api_dimTags_);
3128      }
3129
3130      // Rotate the entities `dimTags' in the built-in CAD representation by
3131      // `angle' radians around the axis of revolution defined by the point (`x',
3132      // `y', `z') and the direction (`ax', `ay', `az').
3133      inline void rotate(const gmsh::vectorpair & dimTags,
3134                         const double x,
3135                         const double y,
3136                         const double z,
3137                         const double ax,
3138                         const double ay,
3139                         const double az,
3140                         const double angle)
3141      {
3142        int ierr = 0;
3143        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
3144        gmshModelGeoRotate(api_dimTags_, api_dimTags_n_, x, y, z, ax, ay, az, angle, &ierr);
3145        if(ierr) throwLastError();
3146        gmshFree(api_dimTags_);
3147      }
3148
3149      // Scale the entities `dimTag' in the built-in CAD representation by factors
3150      // `a', `b' and `c' along the three coordinate axes; use (`x', `y', `z') as
3151      // the center of the homothetic transformation.
3152      inline void dilate(const gmsh::vectorpair & dimTags,
3153                         const double x,
3154                         const double y,
3155                         const double z,
3156                         const double a,
3157                         const double b,
3158                         const double c)
3159      {
3160        int ierr = 0;
3161        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
3162        gmshModelGeoDilate(api_dimTags_, api_dimTags_n_, x, y, z, a, b, c, &ierr);
3163        if(ierr) throwLastError();
3164        gmshFree(api_dimTags_);
3165      }
3166
3167      // Mirror the entities `dimTag' in the built-in CAD representation, with
3168      // respect to the plane of equation `a' * x + `b' * y + `c' * z + `d' = 0.
3169      inline void mirror(const gmsh::vectorpair & dimTags,
3170                         const double a,
3171                         const double b,
3172                         const double c,
3173                         const double d)
3174      {
3175        int ierr = 0;
3176        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
3177        gmshModelGeoMirror(api_dimTags_, api_dimTags_n_, a, b, c, d, &ierr);
3178        if(ierr) throwLastError();
3179        gmshFree(api_dimTags_);
3180      }
3181
3182      // Mirror the entities `dimTag' in the built-in CAD representation, with
3183      // respect to the plane of equation `a' * x + `b' * y + `c' * z + `d' = 0.
3184      // (This is a synonym for `mirror', which will be deprecated in a future
3185      // release.)
3186      inline void symmetrize(const gmsh::vectorpair & dimTags,
3187                             const double a,
3188                             const double b,
3189                             const double c,
3190                             const double d)
3191      {
3192        int ierr = 0;
3193        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
3194        gmshModelGeoSymmetrize(api_dimTags_, api_dimTags_n_, a, b, c, d, &ierr);
3195        if(ierr) throwLastError();
3196        gmshFree(api_dimTags_);
3197      }
3198
3199      // Copy the entities `dimTags' in the built-in CAD representation; the new
3200      // entities are returned in `outDimTags'.
3201      inline void copy(const gmsh::vectorpair & dimTags,
3202                       gmsh::vectorpair & outDimTags)
3203      {
3204        int ierr = 0;
3205        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
3206        int *api_outDimTags_; size_t api_outDimTags_n_;
3207        gmshModelGeoCopy(api_dimTags_, api_dimTags_n_, &api_outDimTags_, &api_outDimTags_n_, &ierr);
3208        if(ierr) throwLastError();
3209        gmshFree(api_dimTags_);
3210        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
3211      }
3212
3213      // Remove the entities `dimTags' in the built-in CAD representation, provided
3214      // that they are not on the boundary of higher-dimensional entities. If
3215      // `recursive' is true, remove all the entities on their boundaries, down to
3216      // dimension 0.
3217      inline void remove(const gmsh::vectorpair & dimTags,
3218                         const bool recursive = false)
3219      {
3220        int ierr = 0;
3221        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
3222        gmshModelGeoRemove(api_dimTags_, api_dimTags_n_, (int)recursive, &ierr);
3223        if(ierr) throwLastError();
3224        gmshFree(api_dimTags_);
3225      }
3226
3227      // Remove all duplicate entities in the built-in CAD representation
3228      // (different entities at the same geometrical location).
3229      inline void removeAllDuplicates()
3230      {
3231        int ierr = 0;
3232        gmshModelGeoRemoveAllDuplicates(&ierr);
3233        if(ierr) throwLastError();
3234      }
3235
3236      // Split the curve of tag `tag' in the built-in CAD representation, on the
3237      // specified control points `pointTags'. This feature is only available for
3238      // lines, splines and b-splines. Return the tag(s) `curveTags' of the newly
3239      // created curve(s).
3240      inline void splitCurve(const int tag,
3241                             const std::vector<int> & pointTags,
3242                             std::vector<int> & curveTags)
3243      {
3244        int ierr = 0;
3245        int *api_pointTags_; size_t api_pointTags_n_; vector2ptr(pointTags, &api_pointTags_, &api_pointTags_n_);
3246        int *api_curveTags_; size_t api_curveTags_n_;
3247        gmshModelGeoSplitCurve(tag, api_pointTags_, api_pointTags_n_, &api_curveTags_, &api_curveTags_n_, &ierr);
3248        if(ierr) throwLastError();
3249        gmshFree(api_pointTags_);
3250        curveTags.assign(api_curveTags_, api_curveTags_ + api_curveTags_n_); gmshFree(api_curveTags_);
3251      }
3252
3253      // Get the maximum tag of entities of dimension `dim' in the built-in CAD
3254      // representation.
3255      inline int getMaxTag(const int dim)
3256      {
3257        int ierr = 0;
3258        int result_api_ = gmshModelGeoGetMaxTag(dim, &ierr);
3259        if(ierr) throwLastError();
3260        return result_api_;
3261      }
3262
3263      // Set the maximum tag `maxTag' for entities of dimension `dim' in the built-
3264      // in CAD representation.
3265      inline void setMaxTag(const int dim,
3266                            const int maxTag)
3267      {
3268        int ierr = 0;
3269        gmshModelGeoSetMaxTag(dim, maxTag, &ierr);
3270        if(ierr) throwLastError();
3271      }
3272
3273      // Add a physical group of dimension `dim', grouping the entities with tags
3274      // `tags' in the built-in CAD representation. Return the tag of the physical
3275      // group, equal to `tag' if `tag' is positive, or a new tag if `tag' < 0.
3276      inline int addPhysicalGroup(const int dim,
3277                                  const std::vector<int> & tags,
3278                                  const int tag = -1)
3279      {
3280        int ierr = 0;
3281        int *api_tags_; size_t api_tags_n_; vector2ptr(tags, &api_tags_, &api_tags_n_);
3282        int result_api_ = gmshModelGeoAddPhysicalGroup(dim, api_tags_, api_tags_n_, tag, &ierr);
3283        if(ierr) throwLastError();
3284        gmshFree(api_tags_);
3285        return result_api_;
3286      }
3287
3288      // Remove the physical groups `dimTags' from the built-in CAD representation.
3289      // If `dimTags' is empty, remove all groups.
3290      inline void removePhysicalGroups(const gmsh::vectorpair & dimTags = gmsh::vectorpair())
3291      {
3292        int ierr = 0;
3293        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
3294        gmshModelGeoRemovePhysicalGroups(api_dimTags_, api_dimTags_n_, &ierr);
3295        if(ierr) throwLastError();
3296        gmshFree(api_dimTags_);
3297      }
3298
3299      // Synchronize the built-in CAD representation with the current Gmsh model.
3300      // This can be called at any time, but since it involves a non trivial amount
3301      // of processing, the number of synchronization points should normally be
3302      // minimized. Without synchronization the entities in the built-in CAD
3303      // representation are not available to any function outside of the built-in
3304      // CAD kernel functions.
3305      inline void synchronize()
3306      {
3307        int ierr = 0;
3308        gmshModelGeoSynchronize(&ierr);
3309        if(ierr) throwLastError();
3310      }
3311
3312      namespace mesh { // Built-in CAD kernel meshing constraints
3313
3314        // Set a mesh size constraint on the entities `dimTags' in the built-in CAD
3315        // kernel representation. Currently only entities of dimension 0 (points)
3316        // are handled.
3317        inline void setSize(const gmsh::vectorpair & dimTags,
3318                            const double size)
3319        {
3320          int ierr = 0;
3321          int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
3322          gmshModelGeoMeshSetSize(api_dimTags_, api_dimTags_n_, size, &ierr);
3323          if(ierr) throwLastError();
3324          gmshFree(api_dimTags_);
3325        }
3326
3327        // Set a transfinite meshing constraint on the curve `tag' in the built-in
3328        // CAD kernel representation, with `numNodes' nodes distributed according
3329        // to `meshType' and `coef'. Currently supported types are "Progression"
3330        // (geometrical progression with power `coef') and "Bump" (refinement
3331        // toward both extremities of the curve).
3332        inline void setTransfiniteCurve(const int tag,
3333                                        const int nPoints,
3334                                        const std::string & meshType = "Progression",
3335                                        const double coef = 1.)
3336        {
3337          int ierr = 0;
3338          gmshModelGeoMeshSetTransfiniteCurve(tag, nPoints, meshType.c_str(), coef, &ierr);
3339          if(ierr) throwLastError();
3340        }
3341
3342        // Set a transfinite meshing constraint on the surface `tag' in the built-
3343        // in CAD kernel representation. `arrangement' describes the arrangement of
3344        // the triangles when the surface is not flagged as recombined: currently
3345        // supported values are "Left", "Right", "AlternateLeft" and
3346        // "AlternateRight". `cornerTags' can be used to specify the (3 or 4)
3347        // corners of the transfinite interpolation explicitly; specifying the
3348        // corners explicitly is mandatory if the surface has more that 3 or 4
3349        // points on its boundary.
3350        inline void setTransfiniteSurface(const int tag,
3351                                          const std::string & arrangement = "Left",
3352                                          const std::vector<int> & cornerTags = std::vector<int>())
3353        {
3354          int ierr = 0;
3355          int *api_cornerTags_; size_t api_cornerTags_n_; vector2ptr(cornerTags, &api_cornerTags_, &api_cornerTags_n_);
3356          gmshModelGeoMeshSetTransfiniteSurface(tag, arrangement.c_str(), api_cornerTags_, api_cornerTags_n_, &ierr);
3357          if(ierr) throwLastError();
3358          gmshFree(api_cornerTags_);
3359        }
3360
3361        // Set a transfinite meshing constraint on the surface `tag' in the built-
3362        // in CAD kernel representation. `cornerTags' can be used to specify the (6
3363        // or 8) corners of the transfinite interpolation explicitly.
3364        inline void setTransfiniteVolume(const int tag,
3365                                         const std::vector<int> & cornerTags = std::vector<int>())
3366        {
3367          int ierr = 0;
3368          int *api_cornerTags_; size_t api_cornerTags_n_; vector2ptr(cornerTags, &api_cornerTags_, &api_cornerTags_n_);
3369          gmshModelGeoMeshSetTransfiniteVolume(tag, api_cornerTags_, api_cornerTags_n_, &ierr);
3370          if(ierr) throwLastError();
3371          gmshFree(api_cornerTags_);
3372        }
3373
3374        // Set a recombination meshing constraint on the entity of dimension `dim'
3375        // and tag `tag' in the built-in CAD kernel representation. Currently only
3376        // entities of dimension 2 (to recombine triangles into quadrangles) are
3377        // supported.
3378        inline void setRecombine(const int dim,
3379                                 const int tag,
3380                                 const double angle = 45.)
3381        {
3382          int ierr = 0;
3383          gmshModelGeoMeshSetRecombine(dim, tag, angle, &ierr);
3384          if(ierr) throwLastError();
3385        }
3386
3387        // Set a smoothing meshing constraint on the entity of dimension `dim' and
3388        // tag `tag' in the built-in CAD kernel representation. `val' iterations of
3389        // a Laplace smoother are applied.
3390        inline void setSmoothing(const int dim,
3391                                 const int tag,
3392                                 const int val)
3393        {
3394          int ierr = 0;
3395          gmshModelGeoMeshSetSmoothing(dim, tag, val, &ierr);
3396          if(ierr) throwLastError();
3397        }
3398
3399        // Set a reverse meshing constraint on the entity of dimension `dim' and
3400        // tag `tag' in the built-in CAD kernel representation. If `val' is true,
3401        // the mesh orientation will be reversed with respect to the natural mesh
3402        // orientation (i.e. the orientation consistent with the orientation of the
3403        // geometry). If `val' is false, the mesh is left as-is.
3404        inline void setReverse(const int dim,
3405                               const int tag,
3406                               const bool val = true)
3407        {
3408          int ierr = 0;
3409          gmshModelGeoMeshSetReverse(dim, tag, (int)val, &ierr);
3410          if(ierr) throwLastError();
3411        }
3412
3413        // Set the meshing algorithm on the entity of dimension `dim' and tag `tag'
3414        // in the built-in CAD kernel representation. Currently only supported for
3415        // `dim' == 2.
3416        inline void setAlgorithm(const int dim,
3417                                 const int tag,
3418                                 const int val)
3419        {
3420          int ierr = 0;
3421          gmshModelGeoMeshSetAlgorithm(dim, tag, val, &ierr);
3422          if(ierr) throwLastError();
3423        }
3424
3425        // Force the mesh size to be extended from the boundary, or not, for the
3426        // entity of dimension `dim' and tag `tag' in the built-in CAD kernel
3427        // representation. Currently only supported for `dim' == 2.
3428        inline void setSizeFromBoundary(const int dim,
3429                                        const int tag,
3430                                        const int val)
3431        {
3432          int ierr = 0;
3433          gmshModelGeoMeshSetSizeFromBoundary(dim, tag, val, &ierr);
3434          if(ierr) throwLastError();
3435        }
3436
3437      } // namespace mesh
3438
3439    } // namespace geo
3440
3441    namespace occ { // OpenCASCADE CAD kernel functions
3442
3443      // Add a geometrical point in the OpenCASCADE CAD representation, at
3444      // coordinates (`x', `y', `z'). If `meshSize' is > 0, add a meshing
3445      // constraint at that point. If `tag' is positive, set the tag explicitly;
3446      // otherwise a new tag is selected automatically. Return the tag of the
3447      // point. (Note that the point will be added in the current model only after
3448      // `synchronize' is called. This behavior holds for all the entities added in
3449      // the occ module.)
3450      inline int addPoint(const double x,
3451                          const double y,
3452                          const double z,
3453                          const double meshSize = 0.,
3454                          const int tag = -1)
3455      {
3456        int ierr = 0;
3457        int result_api_ = gmshModelOccAddPoint(x, y, z, meshSize, tag, &ierr);
3458        if(ierr) throwLastError();
3459        return result_api_;
3460      }
3461
3462      // Add a straight line segment in the OpenCASCADE CAD representation, between
3463      // the two points with tags `startTag' and `endTag'. If `tag' is positive,
3464      // set the tag explicitly; otherwise a new tag is selected automatically.
3465      // Return the tag of the line.
3466      inline int addLine(const int startTag,
3467                         const int endTag,
3468                         const int tag = -1)
3469      {
3470        int ierr = 0;
3471        int result_api_ = gmshModelOccAddLine(startTag, endTag, tag, &ierr);
3472        if(ierr) throwLastError();
3473        return result_api_;
3474      }
3475
3476      // Add a circle arc in the OpenCASCADE CAD representation, between the two
3477      // points with tags `startTag' and `endTag', with center `centerTag'. If
3478      // `tag' is positive, set the tag explicitly; otherwise a new tag is selected
3479      // automatically. Return the tag of the circle arc.
3480      inline int addCircleArc(const int startTag,
3481                              const int centerTag,
3482                              const int endTag,
3483                              const int tag = -1)
3484      {
3485        int ierr = 0;
3486        int result_api_ = gmshModelOccAddCircleArc(startTag, centerTag, endTag, tag, &ierr);
3487        if(ierr) throwLastError();
3488        return result_api_;
3489      }
3490
3491      // Add a circle of center (`x', `y', `z') and radius `r' in the OpenCASCADE
3492      // CAD representation. If `tag' is positive, set the tag explicitly;
3493      // otherwise a new tag is selected automatically. If `angle1' and `angle2'
3494      // are specified, create a circle arc between the two angles. Return the tag
3495      // of the circle.
3496      inline int addCircle(const double x,
3497                           const double y,
3498                           const double z,
3499                           const double r,
3500                           const int tag = -1,
3501                           const double angle1 = 0.,
3502                           const double angle2 = 2*M_PI)
3503      {
3504        int ierr = 0;
3505        int result_api_ = gmshModelOccAddCircle(x, y, z, r, tag, angle1, angle2, &ierr);
3506        if(ierr) throwLastError();
3507        return result_api_;
3508      }
3509
3510      // Add an ellipse arc in the OpenCASCADE CAD representation, between the two
3511      // points `startTag' and `endTag', and with center `centerTag' and major axis
3512      // point `majorTag'. If `tag' is positive, set the tag explicitly; otherwise
3513      // a new tag is selected automatically. Return the tag of the ellipse arc.
3514      // Note that OpenCASCADE does not allow creating ellipse arcs with the major
3515      // radius smaller than the minor radius.
3516      inline int addEllipseArc(const int startTag,
3517                               const int centerTag,
3518                               const int majorTag,
3519                               const int endTag,
3520                               const int tag = -1)
3521      {
3522        int ierr = 0;
3523        int result_api_ = gmshModelOccAddEllipseArc(startTag, centerTag, majorTag, endTag, tag, &ierr);
3524        if(ierr) throwLastError();
3525        return result_api_;
3526      }
3527
3528      // Add an ellipse of center (`x', `y', `z') and radii `r1' and `r2' along the
3529      // x- and y-axes, respectively, in the OpenCASCADE CAD representation. If
3530      // `tag' is positive, set the tag explicitly; otherwise a new tag is selected
3531      // automatically. If `angle1' and `angle2' are specified, create an ellipse
3532      // arc between the two angles. Return the tag of the ellipse. Note that
3533      // OpenCASCADE does not allow creating ellipses with the major radius (along
3534      // the x-axis) smaller than or equal to the minor radius (along the y-axis):
3535      // rotate the shape or use `addCircle' in such cases.
3536      inline int addEllipse(const double x,
3537                            const double y,
3538                            const double z,
3539                            const double r1,
3540                            const double r2,
3541                            const int tag = -1,
3542                            const double angle1 = 0.,
3543                            const double angle2 = 2*M_PI)
3544      {
3545        int ierr = 0;
3546        int result_api_ = gmshModelOccAddEllipse(x, y, z, r1, r2, tag, angle1, angle2, &ierr);
3547        if(ierr) throwLastError();
3548        return result_api_;
3549      }
3550
3551      // Add a spline (C2 b-spline) curve in the OpenCASCADE CAD representation,
3552      // going through the points `pointTags'. If `tag' is positive, set the tag
3553      // explicitly; otherwise a new tag is selected automatically. Create a
3554      // periodic curve if the first and last points are the same. Return the tag
3555      // of the spline curve.
3556      inline int addSpline(const std::vector<int> & pointTags,
3557                           const int tag = -1)
3558      {
3559        int ierr = 0;
3560        int *api_pointTags_; size_t api_pointTags_n_; vector2ptr(pointTags, &api_pointTags_, &api_pointTags_n_);
3561        int result_api_ = gmshModelOccAddSpline(api_pointTags_, api_pointTags_n_, tag, &ierr);
3562        if(ierr) throwLastError();
3563        gmshFree(api_pointTags_);
3564        return result_api_;
3565      }
3566
3567      // Add a b-spline curve of degree `degree' in the OpenCASCADE CAD
3568      // representation, with `pointTags' control points. If `weights', `knots' or
3569      // `multiplicities' are not provided, default parameters are computed
3570      // automatically. If `tag' is positive, set the tag explicitly; otherwise a
3571      // new tag is selected automatically. Create a periodic curve if the first
3572      // and last points are the same. Return the tag of the b-spline curve.
3573      inline int addBSpline(const std::vector<int> & pointTags,
3574                            const int tag = -1,
3575                            const int degree = 3,
3576                            const std::vector<double> & weights = std::vector<double>(),
3577                            const std::vector<double> & knots = std::vector<double>(),
3578                            const std::vector<int> & multiplicities = std::vector<int>())
3579      {
3580        int ierr = 0;
3581        int *api_pointTags_; size_t api_pointTags_n_; vector2ptr(pointTags, &api_pointTags_, &api_pointTags_n_);
3582        double *api_weights_; size_t api_weights_n_; vector2ptr(weights, &api_weights_, &api_weights_n_);
3583        double *api_knots_; size_t api_knots_n_; vector2ptr(knots, &api_knots_, &api_knots_n_);
3584        int *api_multiplicities_; size_t api_multiplicities_n_; vector2ptr(multiplicities, &api_multiplicities_, &api_multiplicities_n_);
3585        int result_api_ = gmshModelOccAddBSpline(api_pointTags_, api_pointTags_n_, tag, degree, api_weights_, api_weights_n_, api_knots_, api_knots_n_, api_multiplicities_, api_multiplicities_n_, &ierr);
3586        if(ierr) throwLastError();
3587        gmshFree(api_pointTags_);
3588        gmshFree(api_weights_);
3589        gmshFree(api_knots_);
3590        gmshFree(api_multiplicities_);
3591        return result_api_;
3592      }
3593
3594      // Add a Bezier curve in the OpenCASCADE CAD representation, with `pointTags'
3595      // control points. If `tag' is positive, set the tag explicitly; otherwise a
3596      // new tag is selected automatically. Return the tag of the Bezier curve.
3597      inline int addBezier(const std::vector<int> & pointTags,
3598                           const int tag = -1)
3599      {
3600        int ierr = 0;
3601        int *api_pointTags_; size_t api_pointTags_n_; vector2ptr(pointTags, &api_pointTags_, &api_pointTags_n_);
3602        int result_api_ = gmshModelOccAddBezier(api_pointTags_, api_pointTags_n_, tag, &ierr);
3603        if(ierr) throwLastError();
3604        gmshFree(api_pointTags_);
3605        return result_api_;
3606      }
3607
3608      // Add a wire (open or closed) in the OpenCASCADE CAD representation, formed
3609      // by the curves `curveTags'. Note that an OpenCASCADE wire can be made of
3610      // curves that share geometrically identical (but topologically different)
3611      // points. If `tag' is positive, set the tag explicitly; otherwise a new tag
3612      // is selected automatically. Return the tag of the wire.
3613      inline int addWire(const std::vector<int> & curveTags,
3614                         const int tag = -1,
3615                         const bool checkClosed = false)
3616      {
3617        int ierr = 0;
3618        int *api_curveTags_; size_t api_curveTags_n_; vector2ptr(curveTags, &api_curveTags_, &api_curveTags_n_);
3619        int result_api_ = gmshModelOccAddWire(api_curveTags_, api_curveTags_n_, tag, (int)checkClosed, &ierr);
3620        if(ierr) throwLastError();
3621        gmshFree(api_curveTags_);
3622        return result_api_;
3623      }
3624
3625      // Add a curve loop (a closed wire) in the OpenCASCADE CAD representation,
3626      // formed by the curves `curveTags'. `curveTags' should contain tags of
3627      // curves forming a closed loop. Negative tags can be specified for
3628      // compatibility with the built-in kernel, but are simply ignored: the wire
3629      // is oriented according to the orientation of its first curve. Note that an
3630      // OpenCASCADE curve loop can be made of curves that share geometrically
3631      // identical (but topologically different) points. If `tag' is positive, set
3632      // the tag explicitly; otherwise a new tag is selected automatically. Return
3633      // the tag of the curve loop.
3634      inline int addCurveLoop(const std::vector<int> & curveTags,
3635                              const int tag = -1)
3636      {
3637        int ierr = 0;
3638        int *api_curveTags_; size_t api_curveTags_n_; vector2ptr(curveTags, &api_curveTags_, &api_curveTags_n_);
3639        int result_api_ = gmshModelOccAddCurveLoop(api_curveTags_, api_curveTags_n_, tag, &ierr);
3640        if(ierr) throwLastError();
3641        gmshFree(api_curveTags_);
3642        return result_api_;
3643      }
3644
3645      // Add a rectangle in the OpenCASCADE CAD representation, with lower left
3646      // corner at (`x', `y', `z') and upper right corner at (`x' + `dx', `y' +
3647      // `dy', `z'). If `tag' is positive, set the tag explicitly; otherwise a new
3648      // tag is selected automatically. Round the corners if `roundedRadius' is
3649      // nonzero. Return the tag of the rectangle.
3650      inline int addRectangle(const double x,
3651                              const double y,
3652                              const double z,
3653                              const double dx,
3654                              const double dy,
3655                              const int tag = -1,
3656                              const double roundedRadius = 0.)
3657      {
3658        int ierr = 0;
3659        int result_api_ = gmshModelOccAddRectangle(x, y, z, dx, dy, tag, roundedRadius, &ierr);
3660        if(ierr) throwLastError();
3661        return result_api_;
3662      }
3663
3664      // Add a disk in the OpenCASCADE CAD representation, with center (`xc', `yc',
3665      // `zc') and radius `rx' along the x-axis and `ry' along the y-axis. If `tag'
3666      // is positive, set the tag explicitly; otherwise a new tag is selected
3667      // automatically. Return the tag of the disk.
3668      inline int addDisk(const double xc,
3669                         const double yc,
3670                         const double zc,
3671                         const double rx,
3672                         const double ry,
3673                         const int tag = -1)
3674      {
3675        int ierr = 0;
3676        int result_api_ = gmshModelOccAddDisk(xc, yc, zc, rx, ry, tag, &ierr);
3677        if(ierr) throwLastError();
3678        return result_api_;
3679      }
3680
3681      // Add a plane surface in the OpenCASCADE CAD representation, defined by one
3682      // or more curve loops (or closed wires) `wireTags'. The first curve loop
3683      // defines the exterior contour; additional curve loop define holes. If `tag'
3684      // is positive, set the tag explicitly; otherwise a new tag is selected
3685      // automatically. Return the tag of the surface.
3686      inline int addPlaneSurface(const std::vector<int> & wireTags,
3687                                 const int tag = -1)
3688      {
3689        int ierr = 0;
3690        int *api_wireTags_; size_t api_wireTags_n_; vector2ptr(wireTags, &api_wireTags_, &api_wireTags_n_);
3691        int result_api_ = gmshModelOccAddPlaneSurface(api_wireTags_, api_wireTags_n_, tag, &ierr);
3692        if(ierr) throwLastError();
3693        gmshFree(api_wireTags_);
3694        return result_api_;
3695      }
3696
3697      // Add a surface in the OpenCASCADE CAD representation, filling the curve
3698      // loop `wireTag'. If `tag' is positive, set the tag explicitly; otherwise a
3699      // new tag is selected automatically. Return the tag of the surface. If
3700      // `pointTags' are provided, force the surface to pass through the given
3701      // points. The other optional arguments are `degree' (the degree of the
3702      // energy criterion to minimize for computing the deformation of the
3703      // surface), `numPointsOnCurves' (the average number of points for
3704      // discretisation of the bounding curves), `numIter' (the maximum number of
3705      // iterations of the optimization process), `anisotropic' (improve
3706      // performance when the ratio of the length along the two parametric
3707      // coordinates of the surface is high), `tol2d' (tolerance to the constraints
3708      // in the parametric plane of the surface), `tol3d' (the maximum distance
3709      // allowed between the support surface and the constraints), `tolAng' (the
3710      // maximum angle allowed between the normal of the surface and the
3711      // constraints), `tolCurv' (the maximum difference of curvature allowed
3712      // between the surface and the constraint), `maxDegree' (the highest degree
3713      // which the polynomial defining the filling surface can have) and,
3714      // `maxSegments' (the largest number of segments which the filling surface
3715      // can have).
3716      inline int addSurfaceFilling(const int wireTag,
3717                                   const int tag = -1,
3718                                   const std::vector<int> & pointTags = std::vector<int>(),
3719                                   const int degree = 3,
3720                                   const int numPointsOnCurves = 15,
3721                                   const int numIter = 2,
3722                                   const bool anisotropic = false,
3723                                   const double tol2d = 0.00001,
3724                                   const double tol3d = 0.0001,
3725                                   const double tolAng = 0.01,
3726                                   const double tolCurv = 0.1,
3727                                   const int maxDegree = 8,
3728                                   const int maxSegments = 9)
3729      {
3730        int ierr = 0;
3731        int *api_pointTags_; size_t api_pointTags_n_; vector2ptr(pointTags, &api_pointTags_, &api_pointTags_n_);
3732        int result_api_ = gmshModelOccAddSurfaceFilling(wireTag, tag, api_pointTags_, api_pointTags_n_, degree, numPointsOnCurves, numIter, (int)anisotropic, tol2d, tol3d, tolAng, tolCurv, maxDegree, maxSegments, &ierr);
3733        if(ierr) throwLastError();
3734        gmshFree(api_pointTags_);
3735        return result_api_;
3736      }
3737
3738      // Add a BSpline surface in the OpenCASCADE CAD representation, filling the
3739      // curve loop `wireTag'. The curve loop should be made of 2, 3 or 4 BSpline
3740      // curves. The optional `type' argument specifies the type of filling:
3741      // "Stretch" creates the flattest patch, "Curved" (the default) creates the
3742      // most rounded patch, and "Coons" creates a rounded patch with less depth
3743      // than "Curved". If `tag' is positive, set the tag explicitly; otherwise a
3744      // new tag is selected automatically. Return the tag of the surface.
3745      inline int addBSplineFilling(const int wireTag,
3746                                   const int tag = -1,
3747                                   const std::string & type = "")
3748      {
3749        int ierr = 0;
3750        int result_api_ = gmshModelOccAddBSplineFilling(wireTag, tag, type.c_str(), &ierr);
3751        if(ierr) throwLastError();
3752        return result_api_;
3753      }
3754
3755      // Add a Bezier surface in the OpenCASCADE CAD representation, filling the
3756      // curve loop `wireTag'. The curve loop should be made of 2, 3 or 4 Bezier
3757      // curves. The optional `type' argument specifies the type of filling:
3758      // "Stretch" creates the flattest patch, "Curved" (the default) creates the
3759      // most rounded patch, and "Coons" creates a rounded patch with less depth
3760      // than "Curved". If `tag' is positive, set the tag explicitly; otherwise a
3761      // new tag is selected automatically. Return the tag of the surface.
3762      inline int addBezierFilling(const int wireTag,
3763                                  const int tag = -1,
3764                                  const std::string & type = "")
3765      {
3766        int ierr = 0;
3767        int result_api_ = gmshModelOccAddBezierFilling(wireTag, tag, type.c_str(), &ierr);
3768        if(ierr) throwLastError();
3769        return result_api_;
3770      }
3771
3772      // Add a b-spline surface of degree `degreeU' x `degreeV' in the OpenCASCADE
3773      // CAD representation, with `pointTags' control points given as a single
3774      // vector [Pu1v1, ... Pu`numPointsU'v1, Pu1v2, ...]. If `weights', `knotsU',
3775      // `knotsV', `multiplicitiesU' or `multiplicitiesV' are not provided, default
3776      // parameters are computed automatically. If `tag' is positive, set the tag
3777      // explicitly; otherwise a new tag is selected automatically. If `wireTags'
3778      // is provided, trim the b-spline patch using the provided wires: the first
3779      // wire defines the external contour, the others define holes. If `wire3D' is
3780      // set, consider wire curves as 3D curves and project them on the b-spline
3781      // surface; otherwise consider the wire curves as defined in the parametric
3782      // space of the surface. Return the tag of the b-spline surface.
3783      inline int addBSplineSurface(const std::vector<int> & pointTags,
3784                                   const int numPointsU,
3785                                   const int tag = -1,
3786                                   const int degreeU = 3,
3787                                   const int degreeV = 3,
3788                                   const std::vector<double> & weights = std::vector<double>(),
3789                                   const std::vector<double> & knotsU = std::vector<double>(),
3790                                   const std::vector<double> & knotsV = std::vector<double>(),
3791                                   const std::vector<int> & multiplicitiesU = std::vector<int>(),
3792                                   const std::vector<int> & multiplicitiesV = std::vector<int>(),
3793                                   const std::vector<int> & wireTags = std::vector<int>(),
3794                                   const bool wire3D = false)
3795      {
3796        int ierr = 0;
3797        int *api_pointTags_; size_t api_pointTags_n_; vector2ptr(pointTags, &api_pointTags_, &api_pointTags_n_);
3798        double *api_weights_; size_t api_weights_n_; vector2ptr(weights, &api_weights_, &api_weights_n_);
3799        double *api_knotsU_; size_t api_knotsU_n_; vector2ptr(knotsU, &api_knotsU_, &api_knotsU_n_);
3800        double *api_knotsV_; size_t api_knotsV_n_; vector2ptr(knotsV, &api_knotsV_, &api_knotsV_n_);
3801        int *api_multiplicitiesU_; size_t api_multiplicitiesU_n_; vector2ptr(multiplicitiesU, &api_multiplicitiesU_, &api_multiplicitiesU_n_);
3802        int *api_multiplicitiesV_; size_t api_multiplicitiesV_n_; vector2ptr(multiplicitiesV, &api_multiplicitiesV_, &api_multiplicitiesV_n_);
3803        int *api_wireTags_; size_t api_wireTags_n_; vector2ptr(wireTags, &api_wireTags_, &api_wireTags_n_);
3804        int result_api_ = gmshModelOccAddBSplineSurface(api_pointTags_, api_pointTags_n_, numPointsU, tag, degreeU, degreeV, api_weights_, api_weights_n_, api_knotsU_, api_knotsU_n_, api_knotsV_, api_knotsV_n_, api_multiplicitiesU_, api_multiplicitiesU_n_, api_multiplicitiesV_, api_multiplicitiesV_n_, api_wireTags_, api_wireTags_n_, (int)wire3D, &ierr);
3805        if(ierr) throwLastError();
3806        gmshFree(api_pointTags_);
3807        gmshFree(api_weights_);
3808        gmshFree(api_knotsU_);
3809        gmshFree(api_knotsV_);
3810        gmshFree(api_multiplicitiesU_);
3811        gmshFree(api_multiplicitiesV_);
3812        gmshFree(api_wireTags_);
3813        return result_api_;
3814      }
3815
3816      // Add a Bezier surface in the OpenCASCADE CAD representation, with
3817      // `pointTags' control points given as a single vector [Pu1v1, ...
3818      // Pu`numPointsU'v1, Pu1v2, ...]. If `tag' is positive, set the tag
3819      // explicitly; otherwise a new tag is selected automatically. If `wireTags'
3820      // is provided, trim the Bezier patch using the provided wires: the first
3821      // wire defines the external contour, the others define holes. If `wire3D' is
3822      // set, consider wire curves as 3D curves and project them on the Bezier
3823      // surface; otherwise consider the wire curves as defined in the parametric
3824      // space of the surface. Return the tag of the Bezier surface.
3825      inline int addBezierSurface(const std::vector<int> & pointTags,
3826                                  const int numPointsU,
3827                                  const int tag = -1,
3828                                  const std::vector<int> & wireTags = std::vector<int>(),
3829                                  const bool wire3D = false)
3830      {
3831        int ierr = 0;
3832        int *api_pointTags_; size_t api_pointTags_n_; vector2ptr(pointTags, &api_pointTags_, &api_pointTags_n_);
3833        int *api_wireTags_; size_t api_wireTags_n_; vector2ptr(wireTags, &api_wireTags_, &api_wireTags_n_);
3834        int result_api_ = gmshModelOccAddBezierSurface(api_pointTags_, api_pointTags_n_, numPointsU, tag, api_wireTags_, api_wireTags_n_, (int)wire3D, &ierr);
3835        if(ierr) throwLastError();
3836        gmshFree(api_pointTags_);
3837        gmshFree(api_wireTags_);
3838        return result_api_;
3839      }
3840
3841      // Trim the surface `surfaceTag' with the wires `wireTags', replacing any
3842      // existing trimming curves. The first wire defines the external contour, the
3843      // others define holes. If `wire3D' is set, consider wire curves as 3D curves
3844      // and project them on the surface; otherwise consider the wire curves as
3845      // defined in the parametric space of the surface. If `tag' is positive, set
3846      // the tag explicitly; otherwise a new tag is selected automatically. Return
3847      // the tag of the trimmed surface.
3848      inline int addTrimmedSurface(const int surfaceTag,
3849                                   const std::vector<int> & wireTags = std::vector<int>(),
3850                                   const bool wire3D = false,
3851                                   const int tag = -1)
3852      {
3853        int ierr = 0;
3854        int *api_wireTags_; size_t api_wireTags_n_; vector2ptr(wireTags, &api_wireTags_, &api_wireTags_n_);
3855        int result_api_ = gmshModelOccAddTrimmedSurface(surfaceTag, api_wireTags_, api_wireTags_n_, (int)wire3D, tag, &ierr);
3856        if(ierr) throwLastError();
3857        gmshFree(api_wireTags_);
3858        return result_api_;
3859      }
3860
3861      // Add a surface loop (a closed shell) in the OpenCASCADE CAD representation,
3862      // formed by `surfaceTags'.  If `tag' is positive, set the tag explicitly;
3863      // otherwise a new tag is selected automatically. Return the tag of the
3864      // surface loop. Setting `sewing' allows one to build a shell made of
3865      // surfaces that share geometrically identical (but topologically different)
3866      // curves.
3867      inline int addSurfaceLoop(const std::vector<int> & surfaceTags,
3868                                const int tag = -1,
3869                                const bool sewing = false)
3870      {
3871        int ierr = 0;
3872        int *api_surfaceTags_; size_t api_surfaceTags_n_; vector2ptr(surfaceTags, &api_surfaceTags_, &api_surfaceTags_n_);
3873        int result_api_ = gmshModelOccAddSurfaceLoop(api_surfaceTags_, api_surfaceTags_n_, tag, (int)sewing, &ierr);
3874        if(ierr) throwLastError();
3875        gmshFree(api_surfaceTags_);
3876        return result_api_;
3877      }
3878
3879      // Add a volume (a region) in the OpenCASCADE CAD representation, defined by
3880      // one or more surface loops `shellTags'. The first surface loop defines the
3881      // exterior boundary; additional surface loop define holes. If `tag' is
3882      // positive, set the tag explicitly; otherwise a new tag is selected
3883      // automatically. Return the tag of the volume.
3884      inline int addVolume(const std::vector<int> & shellTags,
3885                           const int tag = -1)
3886      {
3887        int ierr = 0;
3888        int *api_shellTags_; size_t api_shellTags_n_; vector2ptr(shellTags, &api_shellTags_, &api_shellTags_n_);
3889        int result_api_ = gmshModelOccAddVolume(api_shellTags_, api_shellTags_n_, tag, &ierr);
3890        if(ierr) throwLastError();
3891        gmshFree(api_shellTags_);
3892        return result_api_;
3893      }
3894
3895      // Add a sphere of center (`xc', `yc', `zc') and radius `r' in the
3896      // OpenCASCADE CAD representation. The optional `angle1' and `angle2'
3897      // arguments define the polar angle opening (from -Pi/2 to Pi/2). The
3898      // optional `angle3' argument defines the azimuthal opening (from 0 to 2*Pi).
3899      // If `tag' is positive, set the tag explicitly; otherwise a new tag is
3900      // selected automatically. Return the tag of the sphere.
3901      inline int addSphere(const double xc,
3902                           const double yc,
3903                           const double zc,
3904                           const double radius,
3905                           const int tag = -1,
3906                           const double angle1 = -M_PI/2,
3907                           const double angle2 = M_PI/2,
3908                           const double angle3 = 2*M_PI)
3909      {
3910        int ierr = 0;
3911        int result_api_ = gmshModelOccAddSphere(xc, yc, zc, radius, tag, angle1, angle2, angle3, &ierr);
3912        if(ierr) throwLastError();
3913        return result_api_;
3914      }
3915
3916      // Add a parallelepipedic box in the OpenCASCADE CAD representation, defined
3917      // by a point (`x', `y', `z') and the extents along the x-, y- and z-axes. If
3918      // `tag' is positive, set the tag explicitly; otherwise a new tag is selected
3919      // automatically. Return the tag of the box.
3920      inline int addBox(const double x,
3921                        const double y,
3922                        const double z,
3923                        const double dx,
3924                        const double dy,
3925                        const double dz,
3926                        const int tag = -1)
3927      {
3928        int ierr = 0;
3929        int result_api_ = gmshModelOccAddBox(x, y, z, dx, dy, dz, tag, &ierr);
3930        if(ierr) throwLastError();
3931        return result_api_;
3932      }
3933
3934      // Add a cylinder in the OpenCASCADE CAD representation, defined by the
3935      // center (`x', `y', `z') of its first circular face, the 3 components (`dx',
3936      // `dy', `dz') of the vector defining its axis and its radius `r'. The
3937      // optional `angle' argument defines the angular opening (from 0 to 2*Pi). If
3938      // `tag' is positive, set the tag explicitly; otherwise a new tag is selected
3939      // automatically. Return the tag of the cylinder.
3940      inline int addCylinder(const double x,
3941                             const double y,
3942                             const double z,
3943                             const double dx,
3944                             const double dy,
3945                             const double dz,
3946                             const double r,
3947                             const int tag = -1,
3948                             const double angle = 2*M_PI)
3949      {
3950        int ierr = 0;
3951        int result_api_ = gmshModelOccAddCylinder(x, y, z, dx, dy, dz, r, tag, angle, &ierr);
3952        if(ierr) throwLastError();
3953        return result_api_;
3954      }
3955
3956      // Add a cone in the OpenCASCADE CAD representation, defined by the center
3957      // (`x', `y', `z') of its first circular face, the 3 components of the vector
3958      // (`dx', `dy', `dz') defining its axis and the two radii `r1' and `r2' of
3959      // the faces (these radii can be zero). If `tag' is positive, set the tag
3960      // explicitly; otherwise a new tag is selected automatically. `angle' defines
3961      // the optional angular opening (from 0 to 2*Pi). Return the tag of the cone.
3962      inline int addCone(const double x,
3963                         const double y,
3964                         const double z,
3965                         const double dx,
3966                         const double dy,
3967                         const double dz,
3968                         const double r1,
3969                         const double r2,
3970                         const int tag = -1,
3971                         const double angle = 2*M_PI)
3972      {
3973        int ierr = 0;
3974        int result_api_ = gmshModelOccAddCone(x, y, z, dx, dy, dz, r1, r2, tag, angle, &ierr);
3975        if(ierr) throwLastError();
3976        return result_api_;
3977      }
3978
3979      // Add a right angular wedge in the OpenCASCADE CAD representation, defined
3980      // by the right-angle point (`x', `y', `z') and the 3 extends along the x-,
3981      // y- and z-axes (`dx', `dy', `dz'). If `tag' is positive, set the tag
3982      // explicitly; otherwise a new tag is selected automatically. The optional
3983      // argument `ltx' defines the top extent along the x-axis. Return the tag of
3984      // the wedge.
3985      inline int addWedge(const double x,
3986                          const double y,
3987                          const double z,
3988                          const double dx,
3989                          const double dy,
3990                          const double dz,
3991                          const int tag = -1,
3992                          const double ltx = 0.)
3993      {
3994        int ierr = 0;
3995        int result_api_ = gmshModelOccAddWedge(x, y, z, dx, dy, dz, tag, ltx, &ierr);
3996        if(ierr) throwLastError();
3997        return result_api_;
3998      }
3999
4000      // Add a torus in the OpenCASCADE CAD representation, defined by its center
4001      // (`x', `y', `z') and its 2 radii `r' and `r2'. If `tag' is positive, set
4002      // the tag explicitly; otherwise a new tag is selected automatically. The
4003      // optional argument `angle' defines the angular opening (from 0 to 2*Pi).
4004      // Return the tag of the wedge.
4005      inline int addTorus(const double x,
4006                          const double y,
4007                          const double z,
4008                          const double r1,
4009                          const double r2,
4010                          const int tag = -1,
4011                          const double angle = 2*M_PI)
4012      {
4013        int ierr = 0;
4014        int result_api_ = gmshModelOccAddTorus(x, y, z, r1, r2, tag, angle, &ierr);
4015        if(ierr) throwLastError();
4016        return result_api_;
4017      }
4018
4019      // Add a volume (if the optional argument `makeSolid' is set) or surfaces in
4020      // the OpenCASCADE CAD representation, defined through the open or closed
4021      // wires `wireTags'. If `tag' is positive, set the tag explicitly; otherwise
4022      // a new tag is selected automatically. The new entities are returned in
4023      // `outDimTags'. If the optional argument `makeRuled' is set, the surfaces
4024      // created on the boundary are forced to be ruled surfaces. If `maxDegree' is
4025      // positive, set the maximal degree of resulting surface.
4026      inline void addThruSections(const std::vector<int> & wireTags,
4027                                  gmsh::vectorpair & outDimTags,
4028                                  const int tag = -1,
4029                                  const bool makeSolid = true,
4030                                  const bool makeRuled = false,
4031                                  const int maxDegree = -1)
4032      {
4033        int ierr = 0;
4034        int *api_wireTags_; size_t api_wireTags_n_; vector2ptr(wireTags, &api_wireTags_, &api_wireTags_n_);
4035        int *api_outDimTags_; size_t api_outDimTags_n_;
4036        gmshModelOccAddThruSections(api_wireTags_, api_wireTags_n_, &api_outDimTags_, &api_outDimTags_n_, tag, (int)makeSolid, (int)makeRuled, maxDegree, &ierr);
4037        if(ierr) throwLastError();
4038        gmshFree(api_wireTags_);
4039        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
4040      }
4041
4042      // Add a hollowed volume in the OpenCASCADE CAD representation, built from an
4043      // initial volume `volumeTag' and a set of faces from this volume
4044      // `excludeSurfaceTags', which are to be removed. The remaining faces of the
4045      // volume become the walls of the hollowed solid, with thickness `offset'. If
4046      // `tag' is positive, set the tag explicitly; otherwise a new tag is selected
4047      // automatically.
4048      inline void addThickSolid(const int volumeTag,
4049                                const std::vector<int> & excludeSurfaceTags,
4050                                const double offset,
4051                                gmsh::vectorpair & outDimTags,
4052                                const int tag = -1)
4053      {
4054        int ierr = 0;
4055        int *api_excludeSurfaceTags_; size_t api_excludeSurfaceTags_n_; vector2ptr(excludeSurfaceTags, &api_excludeSurfaceTags_, &api_excludeSurfaceTags_n_);
4056        int *api_outDimTags_; size_t api_outDimTags_n_;
4057        gmshModelOccAddThickSolid(volumeTag, api_excludeSurfaceTags_, api_excludeSurfaceTags_n_, offset, &api_outDimTags_, &api_outDimTags_n_, tag, &ierr);
4058        if(ierr) throwLastError();
4059        gmshFree(api_excludeSurfaceTags_);
4060        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
4061      }
4062
4063      // Extrude the entities `dimTags' in the OpenCASCADE CAD representation,
4064      // using a translation along (`dx', `dy', `dz'). Return extruded entities in
4065      // `outDimTags'. If `numElements' is not empty, also extrude the mesh: the
4066      // entries in `numElements' give the number of elements in each layer. If
4067      // `height' is not empty, it provides the (cumulative) height of the
4068      // different layers, normalized to 1. If `recombine' is set, recombine the
4069      // mesh in the layers.
4070      inline void extrude(const gmsh::vectorpair & dimTags,
4071                          const double dx,
4072                          const double dy,
4073                          const double dz,
4074                          gmsh::vectorpair & outDimTags,
4075                          const std::vector<int> & numElements = std::vector<int>(),
4076                          const std::vector<double> & heights = std::vector<double>(),
4077                          const bool recombine = false)
4078      {
4079        int ierr = 0;
4080        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
4081        int *api_outDimTags_; size_t api_outDimTags_n_;
4082        int *api_numElements_; size_t api_numElements_n_; vector2ptr(numElements, &api_numElements_, &api_numElements_n_);
4083        double *api_heights_; size_t api_heights_n_; vector2ptr(heights, &api_heights_, &api_heights_n_);
4084        gmshModelOccExtrude(api_dimTags_, api_dimTags_n_, dx, dy, dz, &api_outDimTags_, &api_outDimTags_n_, api_numElements_, api_numElements_n_, api_heights_, api_heights_n_, (int)recombine, &ierr);
4085        if(ierr) throwLastError();
4086        gmshFree(api_dimTags_);
4087        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
4088        gmshFree(api_numElements_);
4089        gmshFree(api_heights_);
4090      }
4091
4092      // Extrude the entities `dimTags' in the OpenCASCADE CAD representation,
4093      // using a rotation of `angle' radians around the axis of revolution defined
4094      // by the point (`x', `y', `z') and the direction (`ax', `ay', `az'). Return
4095      // extruded entities in `outDimTags'. If `numElements' is not empty, also
4096      // extrude the mesh: the entries in `numElements' give the number of elements
4097      // in each layer. If `height' is not empty, it provides the (cumulative)
4098      // height of the different layers, normalized to 1. When the mesh is extruded
4099      // the angle should be strictly smaller than 2*Pi. If `recombine' is set,
4100      // recombine the mesh in the layers.
4101      inline void revolve(const gmsh::vectorpair & dimTags,
4102                          const double x,
4103                          const double y,
4104                          const double z,
4105                          const double ax,
4106                          const double ay,
4107                          const double az,
4108                          const double angle,
4109                          gmsh::vectorpair & outDimTags,
4110                          const std::vector<int> & numElements = std::vector<int>(),
4111                          const std::vector<double> & heights = std::vector<double>(),
4112                          const bool recombine = false)
4113      {
4114        int ierr = 0;
4115        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
4116        int *api_outDimTags_; size_t api_outDimTags_n_;
4117        int *api_numElements_; size_t api_numElements_n_; vector2ptr(numElements, &api_numElements_, &api_numElements_n_);
4118        double *api_heights_; size_t api_heights_n_; vector2ptr(heights, &api_heights_, &api_heights_n_);
4119        gmshModelOccRevolve(api_dimTags_, api_dimTags_n_, x, y, z, ax, ay, az, angle, &api_outDimTags_, &api_outDimTags_n_, api_numElements_, api_numElements_n_, api_heights_, api_heights_n_, (int)recombine, &ierr);
4120        if(ierr) throwLastError();
4121        gmshFree(api_dimTags_);
4122        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
4123        gmshFree(api_numElements_);
4124        gmshFree(api_heights_);
4125      }
4126
4127      // Add a pipe in the OpenCASCADE CAD representation, by extruding the
4128      // entities `dimTags' along the wire `wireTag'. The type of sweep can be
4129      // specified with `trihedron' (possible values: "DiscreteTrihedron",
4130      // "CorrectedFrenet", "Fixed", "Frenet", "ConstantNormal", "Darboux",
4131      // "GuideAC", "GuidePlan", "GuideACWithContact", "GuidePlanWithContact"). If
4132      // `trihedron' is not provided, "DiscreteTrihedron" is assumed. Return the
4133      // pipe in `outDimTags'.
4134      inline void addPipe(const gmsh::vectorpair & dimTags,
4135                          const int wireTag,
4136                          gmsh::vectorpair & outDimTags,
4137                          const std::string & trihedron = "")
4138      {
4139        int ierr = 0;
4140        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
4141        int *api_outDimTags_; size_t api_outDimTags_n_;
4142        gmshModelOccAddPipe(api_dimTags_, api_dimTags_n_, wireTag, &api_outDimTags_, &api_outDimTags_n_, trihedron.c_str(), &ierr);
4143        if(ierr) throwLastError();
4144        gmshFree(api_dimTags_);
4145        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
4146      }
4147
4148      // Fillet the volumes `volumeTags' on the curves `curveTags' with radii
4149      // `radii'. The `radii' vector can either contain a single radius, as many
4150      // radii as `curveTags', or twice as many as `curveTags' (in which case
4151      // different radii are provided for the begin and end points of the curves).
4152      // Return the filleted entities in `outDimTags'. Remove the original volume
4153      // if `removeVolume' is set.
4154      inline void fillet(const std::vector<int> & volumeTags,
4155                         const std::vector<int> & curveTags,
4156                         const std::vector<double> & radii,
4157                         gmsh::vectorpair & outDimTags,
4158                         const bool removeVolume = true)
4159      {
4160        int ierr = 0;
4161        int *api_volumeTags_; size_t api_volumeTags_n_; vector2ptr(volumeTags, &api_volumeTags_, &api_volumeTags_n_);
4162        int *api_curveTags_; size_t api_curveTags_n_; vector2ptr(curveTags, &api_curveTags_, &api_curveTags_n_);
4163        double *api_radii_; size_t api_radii_n_; vector2ptr(radii, &api_radii_, &api_radii_n_);
4164        int *api_outDimTags_; size_t api_outDimTags_n_;
4165        gmshModelOccFillet(api_volumeTags_, api_volumeTags_n_, api_curveTags_, api_curveTags_n_, api_radii_, api_radii_n_, &api_outDimTags_, &api_outDimTags_n_, (int)removeVolume, &ierr);
4166        if(ierr) throwLastError();
4167        gmshFree(api_volumeTags_);
4168        gmshFree(api_curveTags_);
4169        gmshFree(api_radii_);
4170        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
4171      }
4172
4173      // Chamfer the volumes `volumeTags' on the curves `curveTags' with distances
4174      // `distances' measured on surfaces `surfaceTags'. The `distances' vector can
4175      // either contain a single distance, as many distances as `curveTags' and
4176      // `surfaceTags', or twice as many as `curveTags' and `surfaceTags' (in which
4177      // case the first in each pair is measured on the corresponding surface in
4178      // `surfaceTags', the other on the other adjacent surface). Return the
4179      // chamfered entities in `outDimTags'. Remove the original volume if
4180      // `removeVolume' is set.
4181      inline void chamfer(const std::vector<int> & volumeTags,
4182                          const std::vector<int> & curveTags,
4183                          const std::vector<int> & surfaceTags,
4184                          const std::vector<double> & distances,
4185                          gmsh::vectorpair & outDimTags,
4186                          const bool removeVolume = true)
4187      {
4188        int ierr = 0;
4189        int *api_volumeTags_; size_t api_volumeTags_n_; vector2ptr(volumeTags, &api_volumeTags_, &api_volumeTags_n_);
4190        int *api_curveTags_; size_t api_curveTags_n_; vector2ptr(curveTags, &api_curveTags_, &api_curveTags_n_);
4191        int *api_surfaceTags_; size_t api_surfaceTags_n_; vector2ptr(surfaceTags, &api_surfaceTags_, &api_surfaceTags_n_);
4192        double *api_distances_; size_t api_distances_n_; vector2ptr(distances, &api_distances_, &api_distances_n_);
4193        int *api_outDimTags_; size_t api_outDimTags_n_;
4194        gmshModelOccChamfer(api_volumeTags_, api_volumeTags_n_, api_curveTags_, api_curveTags_n_, api_surfaceTags_, api_surfaceTags_n_, api_distances_, api_distances_n_, &api_outDimTags_, &api_outDimTags_n_, (int)removeVolume, &ierr);
4195        if(ierr) throwLastError();
4196        gmshFree(api_volumeTags_);
4197        gmshFree(api_curveTags_);
4198        gmshFree(api_surfaceTags_);
4199        gmshFree(api_distances_);
4200        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
4201      }
4202
4203      // Compute the boolean union (the fusion) of the entities `objectDimTags' and
4204      // `toolDimTags' in the OpenCASCADE CAD representation. Return the resulting
4205      // entities in `outDimTags'. If `tag' is positive, try to set the tag
4206      // explicitly (only valid if the boolean operation results in a single
4207      // entity). Remove the object if `removeObject' is set. Remove the tool if
4208      // `removeTool' is set.
4209      inline void fuse(const gmsh::vectorpair & objectDimTags,
4210                       const gmsh::vectorpair & toolDimTags,
4211                       gmsh::vectorpair & outDimTags,
4212                       std::vector<gmsh::vectorpair> & outDimTagsMap,
4213                       const int tag = -1,
4214                       const bool removeObject = true,
4215                       const bool removeTool = true)
4216      {
4217        int ierr = 0;
4218        int *api_objectDimTags_; size_t api_objectDimTags_n_; vectorpair2intptr(objectDimTags, &api_objectDimTags_, &api_objectDimTags_n_);
4219        int *api_toolDimTags_; size_t api_toolDimTags_n_; vectorpair2intptr(toolDimTags, &api_toolDimTags_, &api_toolDimTags_n_);
4220        int *api_outDimTags_; size_t api_outDimTags_n_;
4221        int **api_outDimTagsMap_; size_t *api_outDimTagsMap_n_, api_outDimTagsMap_nn_;
4222        gmshModelOccFuse(api_objectDimTags_, api_objectDimTags_n_, api_toolDimTags_, api_toolDimTags_n_, &api_outDimTags_, &api_outDimTags_n_, &api_outDimTagsMap_, &api_outDimTagsMap_n_, &api_outDimTagsMap_nn_, tag, (int)removeObject, (int)removeTool, &ierr);
4223        if(ierr) throwLastError();
4224        gmshFree(api_objectDimTags_);
4225        gmshFree(api_toolDimTags_);
4226        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
4227        outDimTagsMap.resize(api_outDimTagsMap_nn_); for(size_t i = 0; i < api_outDimTagsMap_nn_; ++i){ outDimTagsMap[i].resize(api_outDimTagsMap_n_[i] / 2); for(size_t j = 0; j < api_outDimTagsMap_n_[i] / 2; ++j){ outDimTagsMap[i][j].first = api_outDimTagsMap_[i][j * 2 + 0]; outDimTagsMap[i][j].second = api_outDimTagsMap_[i][j * 2 + 1]; } gmshFree(api_outDimTagsMap_[i]); } gmshFree(api_outDimTagsMap_); gmshFree(api_outDimTagsMap_n_);
4228      }
4229
4230      // Compute the boolean intersection (the common parts) of the entities
4231      // `objectDimTags' and `toolDimTags' in the OpenCASCADE CAD representation.
4232      // Return the resulting entities in `outDimTags'. If `tag' is positive, try
4233      // to set the tag explicitly (only valid if the boolean operation results in
4234      // a single entity). Remove the object if `removeObject' is set. Remove the
4235      // tool if `removeTool' is set.
4236      inline void intersect(const gmsh::vectorpair & objectDimTags,
4237                            const gmsh::vectorpair & toolDimTags,
4238                            gmsh::vectorpair & outDimTags,
4239                            std::vector<gmsh::vectorpair> & outDimTagsMap,
4240                            const int tag = -1,
4241                            const bool removeObject = true,
4242                            const bool removeTool = true)
4243      {
4244        int ierr = 0;
4245        int *api_objectDimTags_; size_t api_objectDimTags_n_; vectorpair2intptr(objectDimTags, &api_objectDimTags_, &api_objectDimTags_n_);
4246        int *api_toolDimTags_; size_t api_toolDimTags_n_; vectorpair2intptr(toolDimTags, &api_toolDimTags_, &api_toolDimTags_n_);
4247        int *api_outDimTags_; size_t api_outDimTags_n_;
4248        int **api_outDimTagsMap_; size_t *api_outDimTagsMap_n_, api_outDimTagsMap_nn_;
4249        gmshModelOccIntersect(api_objectDimTags_, api_objectDimTags_n_, api_toolDimTags_, api_toolDimTags_n_, &api_outDimTags_, &api_outDimTags_n_, &api_outDimTagsMap_, &api_outDimTagsMap_n_, &api_outDimTagsMap_nn_, tag, (int)removeObject, (int)removeTool, &ierr);
4250        if(ierr) throwLastError();
4251        gmshFree(api_objectDimTags_);
4252        gmshFree(api_toolDimTags_);
4253        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
4254        outDimTagsMap.resize(api_outDimTagsMap_nn_); for(size_t i = 0; i < api_outDimTagsMap_nn_; ++i){ outDimTagsMap[i].resize(api_outDimTagsMap_n_[i] / 2); for(size_t j = 0; j < api_outDimTagsMap_n_[i] / 2; ++j){ outDimTagsMap[i][j].first = api_outDimTagsMap_[i][j * 2 + 0]; outDimTagsMap[i][j].second = api_outDimTagsMap_[i][j * 2 + 1]; } gmshFree(api_outDimTagsMap_[i]); } gmshFree(api_outDimTagsMap_); gmshFree(api_outDimTagsMap_n_);
4255      }
4256
4257      // Compute the boolean difference between the entities `objectDimTags' and
4258      // `toolDimTags' in the OpenCASCADE CAD representation. Return the resulting
4259      // entities in `outDimTags'. If `tag' is positive, try to set the tag
4260      // explicitly (only valid if the boolean operation results in a single
4261      // entity). Remove the object if `removeObject' is set. Remove the tool if
4262      // `removeTool' is set.
4263      inline void cut(const gmsh::vectorpair & objectDimTags,
4264                      const gmsh::vectorpair & toolDimTags,
4265                      gmsh::vectorpair & outDimTags,
4266                      std::vector<gmsh::vectorpair> & outDimTagsMap,
4267                      const int tag = -1,
4268                      const bool removeObject = true,
4269                      const bool removeTool = true)
4270      {
4271        int ierr = 0;
4272        int *api_objectDimTags_; size_t api_objectDimTags_n_; vectorpair2intptr(objectDimTags, &api_objectDimTags_, &api_objectDimTags_n_);
4273        int *api_toolDimTags_; size_t api_toolDimTags_n_; vectorpair2intptr(toolDimTags, &api_toolDimTags_, &api_toolDimTags_n_);
4274        int *api_outDimTags_; size_t api_outDimTags_n_;
4275        int **api_outDimTagsMap_; size_t *api_outDimTagsMap_n_, api_outDimTagsMap_nn_;
4276        gmshModelOccCut(api_objectDimTags_, api_objectDimTags_n_, api_toolDimTags_, api_toolDimTags_n_, &api_outDimTags_, &api_outDimTags_n_, &api_outDimTagsMap_, &api_outDimTagsMap_n_, &api_outDimTagsMap_nn_, tag, (int)removeObject, (int)removeTool, &ierr);
4277        if(ierr) throwLastError();
4278        gmshFree(api_objectDimTags_);
4279        gmshFree(api_toolDimTags_);
4280        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
4281        outDimTagsMap.resize(api_outDimTagsMap_nn_); for(size_t i = 0; i < api_outDimTagsMap_nn_; ++i){ outDimTagsMap[i].resize(api_outDimTagsMap_n_[i] / 2); for(size_t j = 0; j < api_outDimTagsMap_n_[i] / 2; ++j){ outDimTagsMap[i][j].first = api_outDimTagsMap_[i][j * 2 + 0]; outDimTagsMap[i][j].second = api_outDimTagsMap_[i][j * 2 + 1]; } gmshFree(api_outDimTagsMap_[i]); } gmshFree(api_outDimTagsMap_); gmshFree(api_outDimTagsMap_n_);
4282      }
4283
4284      // Compute the boolean fragments (general fuse) resulting from the
4285      // intersection of the entities `objectDimTags' and `toolDimTags' in the
4286      // OpenCASCADE CAD representation, making all iterfaces conformal. When
4287      // applied to entities of different dimensions, the lower dimensional
4288      // entities will be automatically embedded in the higher dimensional entities
4289      // if they are not on their boundary. Return the resulting entities in
4290      // `outDimTags'. If `tag' is positive, try to set the tag explicitly (only
4291      // valid if the boolean operation results in a single entity). Remove the
4292      // object if `removeObject' is set. Remove the tool if `removeTool' is set.
4293      inline void fragment(const gmsh::vectorpair & objectDimTags,
4294                           const gmsh::vectorpair & toolDimTags,
4295                           gmsh::vectorpair & outDimTags,
4296                           std::vector<gmsh::vectorpair> & outDimTagsMap,
4297                           const int tag = -1,
4298                           const bool removeObject = true,
4299                           const bool removeTool = true)
4300      {
4301        int ierr = 0;
4302        int *api_objectDimTags_; size_t api_objectDimTags_n_; vectorpair2intptr(objectDimTags, &api_objectDimTags_, &api_objectDimTags_n_);
4303        int *api_toolDimTags_; size_t api_toolDimTags_n_; vectorpair2intptr(toolDimTags, &api_toolDimTags_, &api_toolDimTags_n_);
4304        int *api_outDimTags_; size_t api_outDimTags_n_;
4305        int **api_outDimTagsMap_; size_t *api_outDimTagsMap_n_, api_outDimTagsMap_nn_;
4306        gmshModelOccFragment(api_objectDimTags_, api_objectDimTags_n_, api_toolDimTags_, api_toolDimTags_n_, &api_outDimTags_, &api_outDimTags_n_, &api_outDimTagsMap_, &api_outDimTagsMap_n_, &api_outDimTagsMap_nn_, tag, (int)removeObject, (int)removeTool, &ierr);
4307        if(ierr) throwLastError();
4308        gmshFree(api_objectDimTags_);
4309        gmshFree(api_toolDimTags_);
4310        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
4311        outDimTagsMap.resize(api_outDimTagsMap_nn_); for(size_t i = 0; i < api_outDimTagsMap_nn_; ++i){ outDimTagsMap[i].resize(api_outDimTagsMap_n_[i] / 2); for(size_t j = 0; j < api_outDimTagsMap_n_[i] / 2; ++j){ outDimTagsMap[i][j].first = api_outDimTagsMap_[i][j * 2 + 0]; outDimTagsMap[i][j].second = api_outDimTagsMap_[i][j * 2 + 1]; } gmshFree(api_outDimTagsMap_[i]); } gmshFree(api_outDimTagsMap_); gmshFree(api_outDimTagsMap_n_);
4312      }
4313
4314      // Translate the entities `dimTags' in the OpenCASCADE CAD representation
4315      // along (`dx', `dy', `dz').
4316      inline void translate(const gmsh::vectorpair & dimTags,
4317                            const double dx,
4318                            const double dy,
4319                            const double dz)
4320      {
4321        int ierr = 0;
4322        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
4323        gmshModelOccTranslate(api_dimTags_, api_dimTags_n_, dx, dy, dz, &ierr);
4324        if(ierr) throwLastError();
4325        gmshFree(api_dimTags_);
4326      }
4327
4328      // Rotate the entities `dimTags' in the OpenCASCADE CAD representation by
4329      // `angle' radians around the axis of revolution defined by the point (`x',
4330      // `y', `z') and the direction (`ax', `ay', `az').
4331      inline void rotate(const gmsh::vectorpair & dimTags,
4332                         const double x,
4333                         const double y,
4334                         const double z,
4335                         const double ax,
4336                         const double ay,
4337                         const double az,
4338                         const double angle)
4339      {
4340        int ierr = 0;
4341        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
4342        gmshModelOccRotate(api_dimTags_, api_dimTags_n_, x, y, z, ax, ay, az, angle, &ierr);
4343        if(ierr) throwLastError();
4344        gmshFree(api_dimTags_);
4345      }
4346
4347      // Scale the entities `dimTags' in the OpenCASCADE CAD representation by
4348      // factors `a', `b' and `c' along the three coordinate axes; use (`x', `y',
4349      // `z') as the center of the homothetic transformation.
4350      inline void dilate(const gmsh::vectorpair & dimTags,
4351                         const double x,
4352                         const double y,
4353                         const double z,
4354                         const double a,
4355                         const double b,
4356                         const double c)
4357      {
4358        int ierr = 0;
4359        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
4360        gmshModelOccDilate(api_dimTags_, api_dimTags_n_, x, y, z, a, b, c, &ierr);
4361        if(ierr) throwLastError();
4362        gmshFree(api_dimTags_);
4363      }
4364
4365      // Mirror the entities `dimTags' in the OpenCASCADE CAD representation, with
4366      // respect to the plane of equation `a' * x + `b' * y + `c' * z + `d' = 0.
4367      inline void mirror(const gmsh::vectorpair & dimTags,
4368                         const double a,
4369                         const double b,
4370                         const double c,
4371                         const double d)
4372      {
4373        int ierr = 0;
4374        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
4375        gmshModelOccMirror(api_dimTags_, api_dimTags_n_, a, b, c, d, &ierr);
4376        if(ierr) throwLastError();
4377        gmshFree(api_dimTags_);
4378      }
4379
4380      // Mirror the entities `dimTags' in the OpenCASCADE CAD representation, with
4381      // respect to the plane of equation `a' * x + `b' * y + `c' * z + `d' = 0.
4382      // (This is a deprecated synonym for `mirror'.)
4383      inline void symmetrize(const gmsh::vectorpair & dimTags,
4384                             const double a,
4385                             const double b,
4386                             const double c,
4387                             const double d)
4388      {
4389        int ierr = 0;
4390        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
4391        gmshModelOccSymmetrize(api_dimTags_, api_dimTags_n_, a, b, c, d, &ierr);
4392        if(ierr) throwLastError();
4393        gmshFree(api_dimTags_);
4394      }
4395
4396      // Apply a general affine transformation matrix `affineTransform' (16 entries
4397      // of a 4x4 matrix, by row; only the 12 first can be provided for
4398      // convenience) to the entities `dimTags' in the OpenCASCADE CAD
4399      // representation.
4400      inline void affineTransform(const gmsh::vectorpair & dimTags,
4401                                  const std::vector<double> & affineTransform)
4402      {
4403        int ierr = 0;
4404        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
4405        double *api_affineTransform_; size_t api_affineTransform_n_; vector2ptr(affineTransform, &api_affineTransform_, &api_affineTransform_n_);
4406        gmshModelOccAffineTransform(api_dimTags_, api_dimTags_n_, api_affineTransform_, api_affineTransform_n_, &ierr);
4407        if(ierr) throwLastError();
4408        gmshFree(api_dimTags_);
4409        gmshFree(api_affineTransform_);
4410      }
4411
4412      // Copy the entities `dimTags' in the OpenCASCADE CAD representation; the new
4413      // entities are returned in `outDimTags'.
4414      inline void copy(const gmsh::vectorpair & dimTags,
4415                       gmsh::vectorpair & outDimTags)
4416      {
4417        int ierr = 0;
4418        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
4419        int *api_outDimTags_; size_t api_outDimTags_n_;
4420        gmshModelOccCopy(api_dimTags_, api_dimTags_n_, &api_outDimTags_, &api_outDimTags_n_, &ierr);
4421        if(ierr) throwLastError();
4422        gmshFree(api_dimTags_);
4423        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
4424      }
4425
4426      // Remove the entities `dimTags' in the OpenCASCADE CAD representation,
4427      // provided that they are not on the boundary of higher-dimensional entities.
4428      // If `recursive' is true, remove all the entities on their boundaries, down
4429      // to dimension 0.
4430      inline void remove(const gmsh::vectorpair & dimTags,
4431                         const bool recursive = false)
4432      {
4433        int ierr = 0;
4434        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
4435        gmshModelOccRemove(api_dimTags_, api_dimTags_n_, (int)recursive, &ierr);
4436        if(ierr) throwLastError();
4437        gmshFree(api_dimTags_);
4438      }
4439
4440      // Remove all duplicate entities in the OpenCASCADE CAD representation
4441      // (different entities at the same geometrical location) after intersecting
4442      // (using boolean fragments) all highest dimensional entities.
4443      inline void removeAllDuplicates()
4444      {
4445        int ierr = 0;
4446        gmshModelOccRemoveAllDuplicates(&ierr);
4447        if(ierr) throwLastError();
4448      }
4449
4450      // Apply various healing procedures to the entities `dimTags' (or to all the
4451      // entities in the model if `dimTags' is empty) in the OpenCASCADE CAD
4452      // representation. Return the healed entities in `outDimTags'. Available
4453      // healing options are listed in the Gmsh reference manual.
4454      inline void healShapes(gmsh::vectorpair & outDimTags,
4455                             const gmsh::vectorpair & dimTags = gmsh::vectorpair(),
4456                             const double tolerance = 1e-8,
4457                             const bool fixDegenerated = true,
4458                             const bool fixSmallEdges = true,
4459                             const bool fixSmallFaces = true,
4460                             const bool sewFaces = true,
4461                             const bool makeSolids = true)
4462      {
4463        int ierr = 0;
4464        int *api_outDimTags_; size_t api_outDimTags_n_;
4465        int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
4466        gmshModelOccHealShapes(&api_outDimTags_, &api_outDimTags_n_, api_dimTags_, api_dimTags_n_, tolerance, (int)fixDegenerated, (int)fixSmallEdges, (int)fixSmallFaces, (int)sewFaces, (int)makeSolids, &ierr);
4467        if(ierr) throwLastError();
4468        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
4469        gmshFree(api_dimTags_);
4470      }
4471
4472      // Import BREP, STEP or IGES shapes from the file `fileName' in the
4473      // OpenCASCADE CAD representation. The imported entities are returned in
4474      // `outDimTags'. If the optional argument `highestDimOnly' is set, only
4475      // import the highest dimensional entities in the file. The optional argument
4476      // `format' can be used to force the format of the file (currently "brep",
4477      // "step" or "iges").
4478      inline void importShapes(const std::string & fileName,
4479                               gmsh::vectorpair & outDimTags,
4480                               const bool highestDimOnly = true,
4481                               const std::string & format = "")
4482      {
4483        int ierr = 0;
4484        int *api_outDimTags_; size_t api_outDimTags_n_;
4485        gmshModelOccImportShapes(fileName.c_str(), &api_outDimTags_, &api_outDimTags_n_, (int)highestDimOnly, format.c_str(), &ierr);
4486        if(ierr) throwLastError();
4487        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
4488      }
4489
4490      // Imports an OpenCASCADE `shape' by providing a pointer to a native
4491      // OpenCASCADE `TopoDS_Shape' object (passed as a pointer to void). The
4492      // imported entities are returned in `outDimTags'. If the optional argument
4493      // `highestDimOnly' is set, only import the highest dimensional entities in
4494      // `shape'. In Python, this function can be used for integration with
4495      // PythonOCC, in which the SwigPyObject pointer of `TopoDS_Shape' must be
4496      // passed as an int to `shape', i.e., `shape = int(pythonocc_shape.this)'.
4497      // Warning: this function is unsafe, as providing an invalid pointer will
4498      // lead to undefined behavior.
4499      inline void importShapesNativePointer(const void * shape,
4500                                            gmsh::vectorpair & outDimTags,
4501                                            const bool highestDimOnly = true)
4502      {
4503        int ierr = 0;
4504        int *api_outDimTags_; size_t api_outDimTags_n_;
4505        gmshModelOccImportShapesNativePointer(shape, &api_outDimTags_, &api_outDimTags_n_, (int)highestDimOnly, &ierr);
4506        if(ierr) throwLastError();
4507        outDimTags.resize(api_outDimTags_n_ / 2); for(size_t i = 0; i < api_outDimTags_n_ / 2; ++i){ outDimTags[i].first = api_outDimTags_[i * 2 + 0]; outDimTags[i].second = api_outDimTags_[i * 2 + 1]; } gmshFree(api_outDimTags_);
4508      }
4509
4510      // Get all the OpenCASCADE entities. If `dim' is >= 0, return only the
4511      // entities of the specified dimension (e.g. points if `dim' == 0). The
4512      // entities are returned as a vector of (dim, tag) integer pairs.
4513      inline void getEntities(gmsh::vectorpair & dimTags,
4514                              const int dim = -1)
4515      {
4516        int ierr = 0;
4517        int *api_dimTags_; size_t api_dimTags_n_;
4518        gmshModelOccGetEntities(&api_dimTags_, &api_dimTags_n_, dim, &ierr);
4519        if(ierr) throwLastError();
4520        dimTags.resize(api_dimTags_n_ / 2); for(size_t i = 0; i < api_dimTags_n_ / 2; ++i){ dimTags[i].first = api_dimTags_[i * 2 + 0]; dimTags[i].second = api_dimTags_[i * 2 + 1]; } gmshFree(api_dimTags_);
4521      }
4522
4523      // Get the OpenCASCADE entities in the bounding box defined by the two points
4524      // (`xmin', `ymin', `zmin') and (`xmax', `ymax', `zmax'). If `dim' is >= 0,
4525      // return only the entities of the specified dimension (e.g. points if `dim'
4526      // == 0).
4527      inline void getEntitiesInBoundingBox(const double xmin,
4528                                           const double ymin,
4529                                           const double zmin,
4530                                           const double xmax,
4531                                           const double ymax,
4532                                           const double zmax,
4533                                           gmsh::vectorpair & tags,
4534                                           const int dim = -1)
4535      {
4536        int ierr = 0;
4537        int *api_tags_; size_t api_tags_n_;
4538        gmshModelOccGetEntitiesInBoundingBox(xmin, ymin, zmin, xmax, ymax, zmax, &api_tags_, &api_tags_n_, dim, &ierr);
4539        if(ierr) throwLastError();
4540        tags.resize(api_tags_n_ / 2); for(size_t i = 0; i < api_tags_n_ / 2; ++i){ tags[i].first = api_tags_[i * 2 + 0]; tags[i].second = api_tags_[i * 2 + 1]; } gmshFree(api_tags_);
4541      }
4542
4543      // Get the bounding box (`xmin', `ymin', `zmin'), (`xmax', `ymax', `zmax') of
4544      // the OpenCASCADE entity of dimension `dim' and tag `tag'.
4545      inline void getBoundingBox(const int dim,
4546                                 const int tag,
4547                                 double & xmin,
4548                                 double & ymin,
4549                                 double & zmin,
4550                                 double & xmax,
4551                                 double & ymax,
4552                                 double & zmax)
4553      {
4554        int ierr = 0;
4555        gmshModelOccGetBoundingBox(dim, tag, &xmin, &ymin, &zmin, &xmax, &ymax, &zmax, &ierr);
4556        if(ierr) throwLastError();
4557      }
4558
4559      // Get the mass of the OpenCASCADE entity of dimension `dim' and tag `tag'.
4560      inline void getMass(const int dim,
4561                          const int tag,
4562                          double & mass)
4563      {
4564        int ierr = 0;
4565        gmshModelOccGetMass(dim, tag, &mass, &ierr);
4566        if(ierr) throwLastError();
4567      }
4568
4569      // Get the center of mass of the OpenCASCADE entity of dimension `dim' and
4570      // tag `tag'.
4571      inline void getCenterOfMass(const int dim,
4572                                  const int tag,
4573                                  double & x,
4574                                  double & y,
4575                                  double & z)
4576      {
4577        int ierr = 0;
4578        gmshModelOccGetCenterOfMass(dim, tag, &x, &y, &z, &ierr);
4579        if(ierr) throwLastError();
4580      }
4581
4582      // Get the matrix of inertia (by row) of the OpenCASCADE entity of dimension
4583      // `dim' and tag `tag'.
4584      inline void getMatrixOfInertia(const int dim,
4585                                     const int tag,
4586                                     std::vector<double> & mat)
4587      {
4588        int ierr = 0;
4589        double *api_mat_; size_t api_mat_n_;
4590        gmshModelOccGetMatrixOfInertia(dim, tag, &api_mat_, &api_mat_n_, &ierr);
4591        if(ierr) throwLastError();
4592        mat.assign(api_mat_, api_mat_ + api_mat_n_); gmshFree(api_mat_);
4593      }
4594
4595      // Get the maximum tag of entities of dimension `dim' in the OpenCASCADE CAD
4596      // representation.
4597      inline int getMaxTag(const int dim)
4598      {
4599        int ierr = 0;
4600        int result_api_ = gmshModelOccGetMaxTag(dim, &ierr);
4601        if(ierr) throwLastError();
4602        return result_api_;
4603      }
4604
4605      // Set the maximum tag `maxTag' for entities of dimension `dim' in the
4606      // OpenCASCADE CAD representation.
4607      inline void setMaxTag(const int dim,
4608                            const int maxTag)
4609      {
4610        int ierr = 0;
4611        gmshModelOccSetMaxTag(dim, maxTag, &ierr);
4612        if(ierr) throwLastError();
4613      }
4614
4615      // Synchronize the OpenCASCADE CAD representation with the current Gmsh
4616      // model. This can be called at any time, but since it involves a non trivial
4617      // amount of processing, the number of synchronization points should normally
4618      // be minimized. Without synchronization the entities in the OpenCASCADE CAD
4619      // representation are not available to any function outside of the
4620      // OpenCASCADE CAD kernel functions.
4621      inline void synchronize()
4622      {
4623        int ierr = 0;
4624        gmshModelOccSynchronize(&ierr);
4625        if(ierr) throwLastError();
4626      }
4627
4628      namespace mesh { // OpenCASCADE CAD kernel meshing constraints
4629
4630        // Set a mesh size constraint on the entities `dimTags' in the OpenCASCADE
4631        // CAD representation. Currently only entities of dimension 0 (points) are
4632        // handled.
4633        inline void setSize(const gmsh::vectorpair & dimTags,
4634                            const double size)
4635        {
4636          int ierr = 0;
4637          int *api_dimTags_; size_t api_dimTags_n_; vectorpair2intptr(dimTags, &api_dimTags_, &api_dimTags_n_);
4638          gmshModelOccMeshSetSize(api_dimTags_, api_dimTags_n_, size, &ierr);
4639          if(ierr) throwLastError();
4640          gmshFree(api_dimTags_);
4641        }
4642
4643      } // namespace mesh
4644
4645    } // namespace occ
4646
4647  } // namespace model
4648
4649  namespace view { // Post-processing view functions
4650
4651    // Add a new post-processing view, with name `name'. If `tag' is positive use
4652    // it (and remove the view with that tag if it already exists), otherwise
4653    // associate a new tag. Return the view tag.
4654    inline int add(const std::string & name,
4655                   const int tag = -1)
4656    {
4657      int ierr = 0;
4658      int result_api_ = gmshViewAdd(name.c_str(), tag, &ierr);
4659      if(ierr) throwLastError();
4660      return result_api_;
4661    }
4662
4663    // Remove the view with tag `tag'.
4664    inline void remove(const int tag)
4665    {
4666      int ierr = 0;
4667      gmshViewRemove(tag, &ierr);
4668      if(ierr) throwLastError();
4669    }
4670
4671    // Get the index of the view with tag `tag' in the list of currently loaded
4672    // views. This dynamic index (it can change when views are removed) is used to
4673    // access view options.
4674    inline int getIndex(const int tag)
4675    {
4676      int ierr = 0;
4677      int result_api_ = gmshViewGetIndex(tag, &ierr);
4678      if(ierr) throwLastError();
4679      return result_api_;
4680    }
4681
4682    // Get the tags of all views.
4683    inline void getTags(std::vector<int> & tags)
4684    {
4685      int ierr = 0;
4686      int *api_tags_; size_t api_tags_n_;
4687      gmshViewGetTags(&api_tags_, &api_tags_n_, &ierr);
4688      if(ierr) throwLastError();
4689      tags.assign(api_tags_, api_tags_ + api_tags_n_); gmshFree(api_tags_);
4690    }
4691
4692    // Add model-based post-processing data to the view with tag `tag'. `modelName'
4693    // identifies the model the data is attached to. `dataType' specifies the type
4694    // of data, currently either "NodeData", "ElementData" or "ElementNodeData".
4695    // `step' specifies the identifier (>= 0) of the data in a sequence. `tags'
4696    // gives the tags of the nodes or elements in the mesh to which the data is
4697    // associated. `data' is a vector of the same length as `tags': each entry is
4698    // the vector of double precision numbers representing the data associated with
4699    // the corresponding tag. The optional `time' argument associate a time value
4700    // with the data. `numComponents' gives the number of data components (1 for
4701    // scalar data, 3 for vector data, etc.) per entity; if negative, it is
4702    // automatically inferred (when possible) from the input data. `partition'
4703    // allows one to specify data in several sub-sets.
4704    inline void addModelData(const int tag,
4705                             const int step,
4706                             const std::string & modelName,
4707                             const std::string & dataType,
4708                             const std::vector<std::size_t> & tags,
4709                             const std::vector<std::vector<double> > & data,
4710                             const double time = 0.,
4711                             const int numComponents = -1,
4712                             const int partition = 0)
4713    {
4714      int ierr = 0;
4715      size_t *api_tags_; size_t api_tags_n_; vector2ptr(tags, &api_tags_, &api_tags_n_);
4716      double **api_data_; size_t *api_data_n_, api_data_nn_; vectorvector2ptrptr(data, &api_data_, &api_data_n_, &api_data_nn_);
4717      gmshViewAddModelData(tag, step, modelName.c_str(), dataType.c_str(), api_tags_, api_tags_n_, (const double **)api_data_, api_data_n_, api_data_nn_, time, numComponents, partition, &ierr);
4718      if(ierr) throwLastError();
4719      gmshFree(api_tags_);
4720      for(size_t i = 0; i < api_data_nn_; ++i){ gmshFree(api_data_[i]); } gmshFree(api_data_); gmshFree(api_data_n_);
4721    }
4722
4723    // Add homogeneous model-based post-processing data to the view with tag `tag'.
4724    // The arguments have the same meaning as in `addModelData', except that `data'
4725    // is supposed to be homogeneous and is thus flattened in a single vector. For
4726    // data types that can lead to different data sizes per tag (like
4727    // "ElementNodeData"), the data should be padded.
4728    inline void addHomogeneousModelData(const int tag,
4729                                        const int step,
4730                                        const std::string & modelName,
4731                                        const std::string & dataType,
4732                                        const std::vector<std::size_t> & tags,
4733                                        const std::vector<double> & data,
4734                                        const double time = 0.,
4735                                        const int numComponents = -1,
4736                                        const int partition = 0)
4737    {
4738      int ierr = 0;
4739      size_t *api_tags_; size_t api_tags_n_; vector2ptr(tags, &api_tags_, &api_tags_n_);
4740      double *api_data_; size_t api_data_n_; vector2ptr(data, &api_data_, &api_data_n_);
4741      gmshViewAddHomogeneousModelData(tag, step, modelName.c_str(), dataType.c_str(), api_tags_, api_tags_n_, api_data_, api_data_n_, time, numComponents, partition, &ierr);
4742      if(ierr) throwLastError();
4743      gmshFree(api_tags_);
4744      gmshFree(api_data_);
4745    }
4746
4747    // Get model-based post-processing data from the view with tag `tag' at step
4748    // `step'. Return the `data' associated to the nodes or the elements with tags
4749    // `tags', as well as the `dataType' and the number of components
4750    // `numComponents'.
4751    inline void getModelData(const int tag,
4752                             const int step,
4753                             std::string & dataType,
4754                             std::vector<std::size_t> & tags,
4755                             std::vector<std::vector<double> > & data,
4756                             double & time,
4757                             int & numComponents)
4758    {
4759      int ierr = 0;
4760      char *api_dataType_;
4761      size_t *api_tags_; size_t api_tags_n_;
4762      double **api_data_; size_t *api_data_n_, api_data_nn_;
4763      gmshViewGetModelData(tag, step, &api_dataType_, &api_tags_, &api_tags_n_, &api_data_, &api_data_n_, &api_data_nn_, &time, &numComponents, &ierr);
4764      if(ierr) throwLastError();
4765      dataType = std::string(api_dataType_); gmshFree(api_dataType_);
4766      tags.assign(api_tags_, api_tags_ + api_tags_n_); gmshFree(api_tags_);
4767      data.resize(api_data_nn_); for(size_t i = 0; i < api_data_nn_; ++i){ data[i].assign(api_data_[i], api_data_[i] + api_data_n_[i]); gmshFree(api_data_[i]); } gmshFree(api_data_); gmshFree(api_data_n_);
4768    }
4769
4770    // Get homogeneous model-based post-processing data from the view with tag
4771    // `tag' at step `step'. The arguments have the same meaning as in
4772    // `getModelData', except that `data' is returned flattened in a single vector,
4773    // with the appropriate padding if necessary.
4774    inline void getHomogeneousModelData(const int tag,
4775                                        const int step,
4776                                        std::string & dataType,
4777                                        std::vector<std::size_t> & tags,
4778                                        std::vector<double> & data,
4779                                        double & time,
4780                                        int & numComponents)
4781    {
4782      int ierr = 0;
4783      char *api_dataType_;
4784      size_t *api_tags_; size_t api_tags_n_;
4785      double *api_data_; size_t api_data_n_;
4786      gmshViewGetHomogeneousModelData(tag, step, &api_dataType_, &api_tags_, &api_tags_n_, &api_data_, &api_data_n_, &time, &numComponents, &ierr);
4787      if(ierr) throwLastError();
4788      dataType = std::string(api_dataType_); gmshFree(api_dataType_);
4789      tags.assign(api_tags_, api_tags_ + api_tags_n_); gmshFree(api_tags_);
4790      data.assign(api_data_, api_data_ + api_data_n_); gmshFree(api_data_);
4791    }
4792
4793    // Add list-based post-processing data to the view with tag `tag'. List-based
4794    // datasets are independent from any model and any mesh. `dataType' identifies
4795    // the data by concatenating the field type ("S" for scalar, "V" for vector,
4796    // "T" for tensor) and the element type ("P" for point, "L" for line, "T" for
4797    // triangle, "S" for tetrahedron, "I" for prism, "H" for hexaHedron, "Y" for
4798    // pyramid). For example `dataType' should be "ST" for a scalar field on
4799    // triangles. `numEle' gives the number of elements in the data. `data'
4800    // contains the data for the `numEle' elements, concatenated, with node
4801    // coordinates followed by values per node, repeated for each step: [e1x1, ...,
4802    // e1xn, e1y1, ..., e1yn, e1z1, ..., e1zn, e1v1..., e1vN, e2x1, ...].
4803    inline void addListData(const int tag,
4804                            const std::string & dataType,
4805                            const int numEle,
4806                            const std::vector<double> & data)
4807    {
4808      int ierr = 0;
4809      double *api_data_; size_t api_data_n_; vector2ptr(data, &api_data_, &api_data_n_);
4810      gmshViewAddListData(tag, dataType.c_str(), numEle, api_data_, api_data_n_, &ierr);
4811      if(ierr) throwLastError();
4812      gmshFree(api_data_);
4813    }
4814
4815    // Get list-based post-processing data from the view with tag `tag'. Return the
4816    // types `dataTypes', the number of elements `numElements' for each data type
4817    // and the `data' for each data type.
4818    inline void getListData(const int tag,
4819                            std::vector<std::string> & dataType,
4820                            std::vector<int> & numElements,
4821                            std::vector<std::vector<double> > & data)
4822    {
4823      int ierr = 0;
4824      char **api_dataType_; size_t api_dataType_n_;
4825      int *api_numElements_; size_t api_numElements_n_;
4826      double **api_data_; size_t *api_data_n_, api_data_nn_;
4827      gmshViewGetListData(tag, &api_dataType_, &api_dataType_n_, &api_numElements_, &api_numElements_n_, &api_data_, &api_data_n_, &api_data_nn_, &ierr);
4828      if(ierr) throwLastError();
4829      dataType.resize(api_dataType_n_); for(size_t i = 0; i < api_dataType_n_; ++i){ dataType[i] = std::string(api_dataType_[i]); gmshFree(api_dataType_[i]); } gmshFree(api_dataType_);
4830      numElements.assign(api_numElements_, api_numElements_ + api_numElements_n_); gmshFree(api_numElements_);
4831      data.resize(api_data_nn_); for(size_t i = 0; i < api_data_nn_; ++i){ data[i].assign(api_data_[i], api_data_[i] + api_data_n_[i]); gmshFree(api_data_[i]); } gmshFree(api_data_); gmshFree(api_data_n_);
4832    }
4833
4834    // Add a string to a list-based post-processing view with tag `tag'. If `coord'
4835    // contains 3 coordinates the string is positioned in the 3D model space ("3D
4836    // string"); if it contains 2 coordinates it is positioned in the 2D graphics
4837    // viewport ("2D string"). `data' contains one or more (for multistep views)
4838    // strings. `style' contains key-value pairs of styling parameters,
4839    // concatenated. Available keys are "Font" (possible values: "Times-Roman",
4840    // "Times-Bold", "Times-Italic", "Times-BoldItalic", "Helvetica", "Helvetica-
4841    // Bold", "Helvetica-Oblique", "Helvetica-BoldOblique", "Courier", "Courier-
4842    // Bold", "Courier-Oblique", "Courier-BoldOblique", "Symbol", "ZapfDingbats",
4843    // "Screen"), "FontSize" and "Align" (possible values: "Left" or "BottomLeft",
4844    // "Center" or "BottomCenter", "Right" or "BottomRight", "TopLeft",
4845    // "TopCenter", "TopRight", "CenterLeft", "CenterCenter", "CenterRight").
4846    inline void addListDataString(const int tag,
4847                                  const std::vector<double> & coord,
4848                                  const std::vector<std::string> & data,
4849                                  const std::vector<std::string> & style = std::vector<std::string>())
4850    {
4851      int ierr = 0;
4852      double *api_coord_; size_t api_coord_n_; vector2ptr(coord, &api_coord_, &api_coord_n_);
4853      char **api_data_; size_t api_data_n_; vectorstring2charptrptr(data, &api_data_, &api_data_n_);
4854      char **api_style_; size_t api_style_n_; vectorstring2charptrptr(style, &api_style_, &api_style_n_);
4855      gmshViewAddListDataString(tag, api_coord_, api_coord_n_, api_data_, api_data_n_, api_style_, api_style_n_, &ierr);
4856      if(ierr) throwLastError();
4857      gmshFree(api_coord_);
4858      for(size_t i = 0; i < api_data_n_; ++i){ gmshFree(api_data_[i]); } gmshFree(api_data_);
4859      for(size_t i = 0; i < api_style_n_; ++i){ gmshFree(api_style_[i]); } gmshFree(api_style_);
4860    }
4861
4862    // Get list-based post-processing data strings (2D strings if `dim' = 2, 3D
4863    // strings if `dim' = 3) from the view with tag `tag'. Return the coordinates
4864    // in `coord', the strings in `data' and the styles in `style'.
4865    inline void getListDataStrings(const int tag,
4866                                   const int dim,
4867                                   std::vector<double> & coord,
4868                                   std::vector<std::string> & data,
4869                                   std::vector<std::string> & style)
4870    {
4871      int ierr = 0;
4872      double *api_coord_; size_t api_coord_n_;
4873      char **api_data_; size_t api_data_n_;
4874      char **api_style_; size_t api_style_n_;
4875      gmshViewGetListDataStrings(tag, dim, &api_coord_, &api_coord_n_, &api_data_, &api_data_n_, &api_style_, &api_style_n_, &ierr);
4876      if(ierr) throwLastError();
4877      coord.assign(api_coord_, api_coord_ + api_coord_n_); gmshFree(api_coord_);
4878      data.resize(api_data_n_); for(size_t i = 0; i < api_data_n_; ++i){ data[i] = std::string(api_data_[i]); gmshFree(api_data_[i]); } gmshFree(api_data_);
4879      style.resize(api_style_n_); for(size_t i = 0; i < api_style_n_; ++i){ style[i] = std::string(api_style_[i]); gmshFree(api_style_[i]); } gmshFree(api_style_);
4880    }
4881
4882    // Set interpolation matrices for the element family `type' ("Line",
4883    // "Triangle", "Quadrangle", "Tetrahedron", "Hexahedron", "Prism", "Pyramid")
4884    // in the view `tag'. The approximation of the values over an element is
4885    // written as a linear combination of `d' basis functions f_i(u, v, w) = sum_(j
4886    // = 0, ..., `d' - 1) `coef'[i][j] u^`exp'[j][0] v^`exp'[j][1] w^`exp'[j][2], i
4887    // = 0, ..., `d'-1, with u, v, w the coordinates in the reference element. The
4888    // `coef' matrix (of size `d' x `d') and the `exp' matrix (of size `d' x 3) are
4889    // stored as vectors, by row. If `dGeo' is positive, use `coefGeo' and `expGeo'
4890    // to define the interpolation of the x, y, z coordinates of the element in
4891    // terms of the u, v, w coordinates, in exactly the same way. If `d' < 0,
4892    // remove the interpolation matrices.
4893    inline void setInterpolationMatrices(const int tag,
4894                                         const std::string & type,
4895                                         const int d,
4896                                         const std::vector<double> & coef,
4897                                         const std::vector<double> & exp,
4898                                         const int dGeo = 0,
4899                                         const std::vector<double> & coefGeo = std::vector<double>(),
4900                                         const std::vector<double> & expGeo = std::vector<double>())
4901    {
4902      int ierr = 0;
4903      double *api_coef_; size_t api_coef_n_; vector2ptr(coef, &api_coef_, &api_coef_n_);
4904      double *api_exp_; size_t api_exp_n_; vector2ptr(exp, &api_exp_, &api_exp_n_);
4905      double *api_coefGeo_; size_t api_coefGeo_n_; vector2ptr(coefGeo, &api_coefGeo_, &api_coefGeo_n_);
4906      double *api_expGeo_; size_t api_expGeo_n_; vector2ptr(expGeo, &api_expGeo_, &api_expGeo_n_);
4907      gmshViewSetInterpolationMatrices(tag, type.c_str(), d, api_coef_, api_coef_n_, api_exp_, api_exp_n_, dGeo, api_coefGeo_, api_coefGeo_n_, api_expGeo_, api_expGeo_n_, &ierr);
4908      if(ierr) throwLastError();
4909      gmshFree(api_coef_);
4910      gmshFree(api_exp_);
4911      gmshFree(api_coefGeo_);
4912      gmshFree(api_expGeo_);
4913    }
4914
4915    // Add a post-processing view as an `alias' of the reference view with tag
4916    // `refTag'. If `copyOptions' is set, copy the options of the reference view.
4917    // If `tag' is positive use it (and remove the view with that tag if it already
4918    // exists), otherwise associate a new tag. Return the view tag.
4919    inline int addAlias(const int refTag,
4920                        const bool copyOptions = false,
4921                        const int tag = -1)
4922    {
4923      int ierr = 0;
4924      int result_api_ = gmshViewAddAlias(refTag, (int)copyOptions, tag, &ierr);
4925      if(ierr) throwLastError();
4926      return result_api_;
4927    }
4928
4929    // Combine elements (if `what' == "elements") or steps (if `what' == "steps")
4930    // of all views (`how' == "all"), all visible views (`how' == "visible") or all
4931    // views having the same name (`how' == "name"). Remove original views if
4932    // `remove' is set.
4933    inline void combine(const std::string & what,
4934                        const std::string & how,
4935                        const bool remove = true,
4936                        const bool copyOptions = true)
4937    {
4938      int ierr = 0;
4939      gmshViewCombine(what.c_str(), how.c_str(), (int)remove, (int)copyOptions, &ierr);
4940      if(ierr) throwLastError();
4941    }
4942
4943    // Probe the view `tag' for its `value' at point (`x', `y', `z'). If no match
4944    // is found, `value' is returned empty. Return only the value at step `step' is
4945    // `step' is positive. Return only values with `numComp' if `numComp' is
4946    // positive. Return the gradient of the `value' if `gradient' is set. If
4947    // `distanceMax' is zero, only return a result if an exact match inside an
4948    // element in the view is found; if `distanceMax' is positive and an exact
4949    // match is not found, return the value at the closest node if it is closer
4950    // than `distanceMax'; if `distanceMax' is negative and an exact match is not
4951    // found, always return the value at the closest node. The distance to the
4952    // match is returned in `distance'. Return the result from the element
4953    // described by its coordinates if `xElementCoord', `yElementCoord' and
4954    // `zElementCoord' are provided. If `dim' is >= 0, return only matches from
4955    // elements of the specified dimension.
4956    inline void probe(const int tag,
4957                      const double x,
4958                      const double y,
4959                      const double z,
4960                      std::vector<double> & value,
4961                      double & distance,
4962                      const int step = -1,
4963                      const int numComp = -1,
4964                      const bool gradient = false,
4965                      const double distanceMax = 0.,
4966                      const std::vector<double> & xElemCoord = std::vector<double>(),
4967                      const std::vector<double> & yElemCoord = std::vector<double>(),
4968                      const std::vector<double> & zElemCoord = std::vector<double>(),
4969                      const int dim = -1)
4970    {
4971      int ierr = 0;
4972      double *api_value_; size_t api_value_n_;
4973      double *api_xElemCoord_; size_t api_xElemCoord_n_; vector2ptr(xElemCoord, &api_xElemCoord_, &api_xElemCoord_n_);
4974      double *api_yElemCoord_; size_t api_yElemCoord_n_; vector2ptr(yElemCoord, &api_yElemCoord_, &api_yElemCoord_n_);
4975      double *api_zElemCoord_; size_t api_zElemCoord_n_; vector2ptr(zElemCoord, &api_zElemCoord_, &api_zElemCoord_n_);
4976      gmshViewProbe(tag, x, y, z, &api_value_, &api_value_n_, &distance, step, numComp, (int)gradient, distanceMax, api_xElemCoord_, api_xElemCoord_n_, api_yElemCoord_, api_yElemCoord_n_, api_zElemCoord_, api_zElemCoord_n_, dim, &ierr);
4977      if(ierr) throwLastError();
4978      value.assign(api_value_, api_value_ + api_value_n_); gmshFree(api_value_);
4979      gmshFree(api_xElemCoord_);
4980      gmshFree(api_yElemCoord_);
4981      gmshFree(api_zElemCoord_);
4982    }
4983
4984    // Write the view to a file `fileName'. The export format is determined by the
4985    // file extension. Append to the file if `append' is set.
4986    inline void write(const int tag,
4987                      const std::string & fileName,
4988                      const bool append = false)
4989    {
4990      int ierr = 0;
4991      gmshViewWrite(tag, fileName.c_str(), (int)append, &ierr);
4992      if(ierr) throwLastError();
4993    }
4994
4995    // Set the global visibility of the view `tag' per window to `value', where
4996    // `windowIndex' identifies the window in the window list.
4997    inline void setVisibilityPerWindow(const int tag,
4998                                       const int value,
4999                                       const int windowIndex = 0)
5000    {
5001      int ierr = 0;
5002      gmshViewSetVisibilityPerWindow(tag, value, windowIndex, &ierr);
5003      if(ierr) throwLastError();
5004    }
5005
5006    namespace option { // View option handling functions
5007
5008      // Set the numerical option `name' to value `value' for the view with tag
5009      // `tag'.
5010      inline void setNumber(const int tag,
5011                            const std::string & name,
5012                            const double value)
5013      {
5014        int ierr = 0;
5015        gmshViewOptionSetNumber(tag, name.c_str(), value, &ierr);
5016        if(ierr) throwLastError();
5017      }
5018
5019      // Get the `value' of the numerical option `name' for the view with tag
5020      // `tag'.
5021      inline void getNumber(const int tag,
5022                            const std::string & name,
5023                            double & value)
5024      {
5025        int ierr = 0;
5026        gmshViewOptionGetNumber(tag, name.c_str(), &value, &ierr);
5027        if(ierr) throwLastError();
5028      }
5029
5030      // Set the string option `name' to value `value' for the view with tag `tag'.
5031      inline void setString(const int tag,
5032                            const std::string & name,
5033                            const std::string & value)
5034      {
5035        int ierr = 0;
5036        gmshViewOptionSetString(tag, name.c_str(), value.c_str(), &ierr);
5037        if(ierr) throwLastError();
5038      }
5039
5040      // Get the `value' of the string option `name' for the view with tag `tag'.
5041      inline void getString(const int tag,
5042                            const std::string & name,
5043                            std::string & value)
5044      {
5045        int ierr = 0;
5046        char *api_value_;
5047        gmshViewOptionGetString(tag, name.c_str(), &api_value_, &ierr);
5048        if(ierr) throwLastError();
5049        value = std::string(api_value_); gmshFree(api_value_);
5050      }
5051
5052      // Set the color option `name' to the RGBA value (`r', `g', `b', `a') for the
5053      // view with tag `tag', where where `r', `g', `b' and `a' should be integers
5054      // between 0 and 255.
5055      inline void setColor(const int tag,
5056                           const std::string & name,
5057                           const int r,
5058                           const int g,
5059                           const int b,
5060                           const int a = 255)
5061      {
5062        int ierr = 0;
5063        gmshViewOptionSetColor(tag, name.c_str(), r, g, b, a, &ierr);
5064        if(ierr) throwLastError();
5065      }
5066
5067      // Get the `r', `g', `b', `a' value of the color option `name' for the view
5068      // with tag `tag'.
5069      inline void getColor(const int tag,
5070                           const std::string & name,
5071                           int & r,
5072                           int & g,
5073                           int & b,
5074                           int & a)
5075      {
5076        int ierr = 0;
5077        gmshViewOptionGetColor(tag, name.c_str(), &r, &g, &b, &a, &ierr);
5078        if(ierr) throwLastError();
5079      }
5080
5081      // Copy the options from the view with tag `refTag' to the view with tag
5082      // `tag'.
5083      inline void copy(const int refTag,
5084                       const int tag)
5085      {
5086        int ierr = 0;
5087        gmshViewOptionCopy(refTag, tag, &ierr);
5088        if(ierr) throwLastError();
5089      }
5090
5091    } // namespace option
5092
5093  } // namespace view
5094
5095  namespace plugin { // Plugin functions
5096
5097    // Set the numerical option `option' to the value `value' for plugin `name'.
5098    inline void setNumber(const std::string & name,
5099                          const std::string & option,
5100                          const double value)
5101    {
5102      int ierr = 0;
5103      gmshPluginSetNumber(name.c_str(), option.c_str(), value, &ierr);
5104      if(ierr) throwLastError();
5105    }
5106
5107    // Set the string option `option' to the value `value' for plugin `name'.
5108    inline void setString(const std::string & name,
5109                          const std::string & option,
5110                          const std::string & value)
5111    {
5112      int ierr = 0;
5113      gmshPluginSetString(name.c_str(), option.c_str(), value.c_str(), &ierr);
5114      if(ierr) throwLastError();
5115    }
5116
5117    // Run the plugin `name'. Return the tag of the created view (if any).
5118    inline int run(const std::string & name)
5119    {
5120      int ierr = 0;
5121      int result_api_ = gmshPluginRun(name.c_str(), &ierr);
5122      if(ierr) throwLastError();
5123      return result_api_;
5124    }
5125
5126  } // namespace plugin
5127
5128  namespace graphics { // Graphics functions
5129
5130    // Draw all the OpenGL scenes.
5131    inline void draw()
5132    {
5133      int ierr = 0;
5134      gmshGraphicsDraw(&ierr);
5135      if(ierr) throwLastError();
5136    }
5137
5138  } // namespace graphics
5139
5140  namespace fltk { // FLTK graphical user interface functions
5141
5142    // Create the FLTK graphical user interface. Can only be called in the main
5143    // thread.
5144    inline void initialize()
5145    {
5146      int ierr = 0;
5147      gmshFltkInitialize(&ierr);
5148      if(ierr) throwLastError();
5149    }
5150
5151    // Wait at most `time' seconds for user interface events and return. If `time'
5152    // < 0, wait indefinitely. First automatically create the user interface if it
5153    // has not yet been initialized. Can only be called in the main thread.
5154    inline void wait(const double time = -1.)
5155    {
5156      int ierr = 0;
5157      gmshFltkWait(time, &ierr);
5158      if(ierr) throwLastError();
5159    }
5160
5161    // Update the user interface (potentially creating new widgets and windows).
5162    // First automatically create the user interface if it has not yet been
5163    // initialized. Can only be called in the main thread: use `awake("update")' to
5164    // trigger an update of the user interface from another thread.
5165    inline void update()
5166    {
5167      int ierr = 0;
5168      gmshFltkUpdate(&ierr);
5169      if(ierr) throwLastError();
5170    }
5171
5172    // Awake the main user interface thread and process pending events, and
5173    // optionally perform an action (currently the only `action' allowed is
5174    // "update").
5175    inline void awake(const std::string & action = "")
5176    {
5177      int ierr = 0;
5178      gmshFltkAwake(action.c_str(), &ierr);
5179      if(ierr) throwLastError();
5180    }
5181
5182    // Block the current thread until it can safely modify the user interface.
5183    inline void lock()
5184    {
5185      int ierr = 0;
5186      gmshFltkLock(&ierr);
5187      if(ierr) throwLastError();
5188    }
5189
5190    // Release the lock that was set using lock.
5191    inline void unlock()
5192    {
5193      int ierr = 0;
5194      gmshFltkUnlock(&ierr);
5195      if(ierr) throwLastError();
5196    }
5197
5198    // Run the event loop of the graphical user interface, i.e. repeatedly call
5199    // `wait()'. First automatically create the user interface if it has not yet
5200    // been initialized. Can only be called in the main thread.
5201    inline void run()
5202    {
5203      int ierr = 0;
5204      gmshFltkRun(&ierr);
5205      if(ierr) throwLastError();
5206    }
5207
5208    // Check if the user interface is available (e.g. to detect if it has been
5209    // closed).
5210    inline int isAvailable()
5211    {
5212      int ierr = 0;
5213      int result_api_ = gmshFltkIsAvailable(&ierr);
5214      if(ierr) throwLastError();
5215      return result_api_;
5216    }
5217
5218    // Select entities in the user interface. If `dim' is >= 0, return only the
5219    // entities of the specified dimension (e.g. points if `dim' == 0).
5220    inline int selectEntities(gmsh::vectorpair & dimTags,
5221                              const int dim = -1)
5222    {
5223      int ierr = 0;
5224      int *api_dimTags_; size_t api_dimTags_n_;
5225      int result_api_ = gmshFltkSelectEntities(&api_dimTags_, &api_dimTags_n_, dim, &ierr);
5226      if(ierr) throwLastError();
5227      dimTags.resize(api_dimTags_n_ / 2); for(size_t i = 0; i < api_dimTags_n_ / 2; ++i){ dimTags[i].first = api_dimTags_[i * 2 + 0]; dimTags[i].second = api_dimTags_[i * 2 + 1]; } gmshFree(api_dimTags_);
5228      return result_api_;
5229    }
5230
5231    // Select elements in the user interface.
5232    inline int selectElements(std::vector<std::size_t> & elementTags)
5233    {
5234      int ierr = 0;
5235      size_t *api_elementTags_; size_t api_elementTags_n_;
5236      int result_api_ = gmshFltkSelectElements(&api_elementTags_, &api_elementTags_n_, &ierr);
5237      if(ierr) throwLastError();
5238      elementTags.assign(api_elementTags_, api_elementTags_ + api_elementTags_n_); gmshFree(api_elementTags_);
5239      return result_api_;
5240    }
5241
5242    // Select views in the user interface.
5243    inline int selectViews(std::vector<int> & viewTags)
5244    {
5245      int ierr = 0;
5246      int *api_viewTags_; size_t api_viewTags_n_;
5247      int result_api_ = gmshFltkSelectViews(&api_viewTags_, &api_viewTags_n_, &ierr);
5248      if(ierr) throwLastError();
5249      viewTags.assign(api_viewTags_, api_viewTags_ + api_viewTags_n_); gmshFree(api_viewTags_);
5250      return result_api_;
5251    }
5252
5253    // Split the current window horizontally (if `how' = "h") or vertically (if
5254    // `how' = "v"), using ratio `ratio'. If `how' = "u", restore a single window.
5255    inline void splitCurrentWindow(const std::string & how = "v",
5256                                   const double ratio = 0.5)
5257    {
5258      int ierr = 0;
5259      gmshFltkSplitCurrentWindow(how.c_str(), ratio, &ierr);
5260      if(ierr) throwLastError();
5261    }
5262
5263    // Set the current window by speficying its index (starting at 0) in the list
5264    // of all windows. When new windows are created by splits, new windows are
5265    // appended at the end of the list.
5266    inline void setCurrentWindow(const int windowIndex = 0)
5267    {
5268      int ierr = 0;
5269      gmshFltkSetCurrentWindow(windowIndex, &ierr);
5270      if(ierr) throwLastError();
5271    }
5272
5273    // Set a status message in the current window. If `graphics' is set, display
5274    // the message inside the graphic window instead of the status bar.
5275    inline void setStatusMessage(const std::string & message,
5276                                 const bool graphics = false)
5277    {
5278      int ierr = 0;
5279      gmshFltkSetStatusMessage(message.c_str(), (int)graphics, &ierr);
5280      if(ierr) throwLastError();
5281    }
5282
5283    // Show context window for the entity of dimension `dim' and tag `tag'.
5284    inline void showContextWindow(const int dim,
5285                                  const int tag)
5286    {
5287      int ierr = 0;
5288      gmshFltkShowContextWindow(dim, tag, &ierr);
5289      if(ierr) throwLastError();
5290    }
5291
5292    // Open the `name' item in the menu tree.
5293    inline void openTreeItem(const std::string & name)
5294    {
5295      int ierr = 0;
5296      gmshFltkOpenTreeItem(name.c_str(), &ierr);
5297      if(ierr) throwLastError();
5298    }
5299
5300    // Close the `name' item in the menu tree.
5301    inline void closeTreeItem(const std::string & name)
5302    {
5303      int ierr = 0;
5304      gmshFltkCloseTreeItem(name.c_str(), &ierr);
5305      if(ierr) throwLastError();
5306    }
5307
5308  } // namespace fltk
5309
5310  namespace onelab { // ONELAB server functions
5311
5312    // Set one or more parameters in the ONELAB database, encoded in `format'.
5313    inline void set(const std::string & data,
5314                    const std::string & format = "json")
5315    {
5316      int ierr = 0;
5317      gmshOnelabSet(data.c_str(), format.c_str(), &ierr);
5318      if(ierr) throwLastError();
5319    }
5320
5321    // Get all the parameters (or a single one if `name' is specified) from the
5322    // ONELAB database, encoded in `format'.
5323    inline void get(std::string & data,
5324                    const std::string & name = "",
5325                    const std::string & format = "json")
5326    {
5327      int ierr = 0;
5328      char *api_data_;
5329      gmshOnelabGet(&api_data_, name.c_str(), format.c_str(), &ierr);
5330      if(ierr) throwLastError();
5331      data = std::string(api_data_); gmshFree(api_data_);
5332    }
5333
5334    // Get the names of the parameters in the ONELAB database matching the `search'
5335    // regular expression. If `search' is empty, return all the names.
5336    inline void getNames(std::vector<std::string> & names,
5337                         const std::string & search = "")
5338    {
5339      int ierr = 0;
5340      char **api_names_; size_t api_names_n_;
5341      gmshOnelabGetNames(&api_names_, &api_names_n_, search.c_str(), &ierr);
5342      if(ierr) throwLastError();
5343      names.resize(api_names_n_); for(size_t i = 0; i < api_names_n_; ++i){ names[i] = std::string(api_names_[i]); gmshFree(api_names_[i]); } gmshFree(api_names_);
5344    }
5345
5346    // Set the value of the number parameter `name' in the ONELAB database. Create
5347    // the parameter if it does not exist; update the value if the parameter
5348    // exists.
5349    inline void setNumber(const std::string & name,
5350                          const std::vector<double> & value)
5351    {
5352      int ierr = 0;
5353      double *api_value_; size_t api_value_n_; vector2ptr(value, &api_value_, &api_value_n_);
5354      gmshOnelabSetNumber(name.c_str(), api_value_, api_value_n_, &ierr);
5355      if(ierr) throwLastError();
5356      gmshFree(api_value_);
5357    }
5358
5359    // Set the value of the string parameter `name' in the ONELAB database. Create
5360    // the parameter if it does not exist; update the value if the parameter
5361    // exists.
5362    inline void setString(const std::string & name,
5363                          const std::vector<std::string> & value)
5364    {
5365      int ierr = 0;
5366      char **api_value_; size_t api_value_n_; vectorstring2charptrptr(value, &api_value_, &api_value_n_);
5367      gmshOnelabSetString(name.c_str(), api_value_, api_value_n_, &ierr);
5368      if(ierr) throwLastError();
5369      for(size_t i = 0; i < api_value_n_; ++i){ gmshFree(api_value_[i]); } gmshFree(api_value_);
5370    }
5371
5372    // Get the value of the number parameter `name' from the ONELAB database.
5373    // Return an empty vector if the parameter does not exist.
5374    inline void getNumber(const std::string & name,
5375                          std::vector<double> & value)
5376    {
5377      int ierr = 0;
5378      double *api_value_; size_t api_value_n_;
5379      gmshOnelabGetNumber(name.c_str(), &api_value_, &api_value_n_, &ierr);
5380      if(ierr) throwLastError();
5381      value.assign(api_value_, api_value_ + api_value_n_); gmshFree(api_value_);
5382    }
5383
5384    // Get the value of the string parameter `name' from the ONELAB database.
5385    // Return an empty vector if the parameter does not exist.
5386    inline void getString(const std::string & name,
5387                          std::vector<std::string> & value)
5388    {
5389      int ierr = 0;
5390      char **api_value_; size_t api_value_n_;
5391      gmshOnelabGetString(name.c_str(), &api_value_, &api_value_n_, &ierr);
5392      if(ierr) throwLastError();
5393      value.resize(api_value_n_); for(size_t i = 0; i < api_value_n_; ++i){ value[i] = std::string(api_value_[i]); gmshFree(api_value_[i]); } gmshFree(api_value_);
5394    }
5395
5396    // Clear the ONELAB database, or remove a single parameter if `name' is given.
5397    inline void clear(const std::string & name = "")
5398    {
5399      int ierr = 0;
5400      gmshOnelabClear(name.c_str(), &ierr);
5401      if(ierr) throwLastError();
5402    }
5403
5404    // Run a ONELAB client. If `name' is provided, create a new ONELAB client with
5405    // name `name' and executes `command'. If not, try to run a client that might
5406    // be linked to the processed input files.
5407    inline void run(const std::string & name = "",
5408                    const std::string & command = "")
5409    {
5410      int ierr = 0;
5411      gmshOnelabRun(name.c_str(), command.c_str(), &ierr);
5412      if(ierr) throwLastError();
5413    }
5414
5415  } // namespace onelab
5416
5417  namespace logger { // Information logging functions
5418
5419    // Write a `message'. `level' can be "info", "warning" or "error".
5420    inline void write(const std::string & message,
5421                      const std::string & level = "info")
5422    {
5423      int ierr = 0;
5424      gmshLoggerWrite(message.c_str(), level.c_str(), &ierr);
5425      if(ierr) throwLastError();
5426    }
5427
5428    // Start logging messages.
5429    inline void start()
5430    {
5431      int ierr = 0;
5432      gmshLoggerStart(&ierr);
5433      if(ierr) throwLastError();
5434    }
5435
5436    // Get logged messages.
5437    inline void get(std::vector<std::string> & log)
5438    {
5439      int ierr = 0;
5440      char **api_log_; size_t api_log_n_;
5441      gmshLoggerGet(&api_log_, &api_log_n_, &ierr);
5442      if(ierr) throwLastError();
5443      log.resize(api_log_n_); for(size_t i = 0; i < api_log_n_; ++i){ log[i] = std::string(api_log_[i]); gmshFree(api_log_[i]); } gmshFree(api_log_);
5444    }
5445
5446    // Stop logging messages.
5447    inline void stop()
5448    {
5449      int ierr = 0;
5450      gmshLoggerStop(&ierr);
5451      if(ierr) throwLastError();
5452    }
5453
5454    // Return wall clock time.
5455    inline double getWallTime()
5456    {
5457      int ierr = 0;
5458      double result_api_ = gmshLoggerGetWallTime(&ierr);
5459      if(ierr) throwLastError();
5460      return result_api_;
5461    }
5462
5463    // Return CPU time.
5464    inline double getCpuTime()
5465    {
5466      int ierr = 0;
5467      double result_api_ = gmshLoggerGetCpuTime(&ierr);
5468      if(ierr) throwLastError();
5469      return result_api_;
5470    }
5471
5472    // Return last error message, if any.
5473    inline void getLastError(std::string & error)
5474    {
5475      int ierr = 0;
5476      char *api_error_;
5477      gmshLoggerGetLastError(&api_error_, &ierr);
5478      if(ierr) throw "Could not get last error";
5479      error = std::string(api_error_); gmshFree(api_error_);
5480    }
5481
5482  } // namespace logger
5483
5484} // namespace gmsh
5485
5486#endif
5487