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