29 #if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES)    30 #define _USE_MATH_DEFINES    79   std::string file = fname;
    80   std::vector<std::pair<int, int>> imported;
    84     std::cerr << 
"Error: Input Geometry File " << file << 
" not found."    90   gmsh::model::occ::importShapes(file, imported, 
false);
    91   gmsh::model::occ::synchronize();
    97     gmsh::vectorpair volumes;
    98     gmsh::model::getEntities(volumes, 3);
   100     gmsh::vectorpair outTags;
   101     std::vector<gmsh::vectorpair> outDimTagsMap;
   102     gmsh::model::occ::fragment(volumes, {}, outTags, outDimTagsMap);
   103     gmsh::model::occ::synchronize();
   115   gmsh::model::mesh::generate(3);
   116   gmsh::model::mesh::removeDuplicateNodes();
   123   if (ext != 
".msh" && ext != 
".vtu") {
   125     auto pos = std::find(meshExtensions.begin(), meshExtensions.end(), ext);
   126     if (pos == meshExtensions.end()) {
   127       std::cerr << 
"Error: Output file extension " << ext
   128                 << 
" not supported in this mesh engine." << std::endl;
   129       std::cout << 
"Supported formats are ";
   130       for (
auto meshExtension : meshExtensions) {
   131         std::cout << meshExtension << 
" ";
   133       std::cout << 
"\n" << std::endl;
   136       if (ext == 
".inp" || ext == 
".unv") {
   137         gmsh::option::setNumber(
"Mesh.SaveGroupsOfElements", 1);
   138         gmsh::option::setNumber(
"Mesh.SaveGroupsOfNodes", 1);
   153   gmsh::option::setNumber(
"General.Terminal", 1);
   157   gmsh::option::setNumber(
"Geometry.OCCImportLabels", 1);
   161   gmsh::option::setNumber(
"Mesh.MshFileVersion", 2.2);
   165     gmsh::option::setNumber(
"Mesh.CharacteristicLengthExtendFromBoundary", 1);
   167     gmsh::option::setNumber(
"Mesh.CharacteristicLengthExtendFromBoundary", 0);
   169     gmsh::option::setNumber(
"Mesh.CharacteristicLengthFromCurvature", 1);
   171     gmsh::option::setNumber(
"Mesh.CharacteristicLengthFromCurvature", 0);
   172   gmsh::option::setNumber(
"Mesh.MinimumElementsPerTwoPi",
   175     gmsh::option::setNumber(
"Mesh.Optimize", 1);
   177     gmsh::option::setNumber(
"Mesh.Optimize", 0);
   178   gmsh::option::setNumber(
"Mesh.OptimizeThreshold",
   181   gmsh::option::setNumber(
"Mesh.RecombineAll", 0);
   182   gmsh::option::setNumber(
"Mesh.Smoothing", 1);
   183   gmsh::option::setNumber(
"Mesh.CharacteristicLengthFactor", 1);
   184   gmsh::option::setNumber(
"Mesh.CharacteristicLengthFromPoints", 1);
   185   gmsh::option::setNumber(
"Mesh.LcIntegrationPrecision", 1e-09);
   186   gmsh::option::setNumber(
"Mesh.MaxIterDelaunay3D", 0);
   187   gmsh::option::setNumber(
"Mesh.RandomFactor", 1e-09);
   188   gmsh::option::setNumber(
"Mesh.RandomFactor3D", 1e-12);
   189   gmsh::option::setNumber(
"Mesh.ElementOrder",
   191   gmsh::option::setNumber(
"Mesh.SubdivisionAlgorithm",
   196   if (algo == 
"Frontal")
   198   else if (algo == 
"MeshAdapt")
   200   else if (algo == 
"Automatic")
   202   else if (algo == 
"Delaunay")
   204   else if (algo == 
"Frontal Quads" || algo == 
"Frontal Quad")
   206   else if (algo == 
"Packing of Parallelograms")
   209     std::cerr << 
"Warning: Surface algorithm " << algo << 
" not supported. \n"   210               << 
"Using default Frontal algorithm." << std::endl;
   212   gmsh::option::setNumber(
"Mesh.Algorithm", a);
   216   if (algo == 
"Delaunay")
   218   else if (algo == 
"Frontal")
   220   else if (algo == 
"HXT")
   223     std::cerr << 
"Warning: Volume algorithm " << algo << 
" not supported. \n"   224               << 
"Using default Delaunay algorithm." << std::endl;
   226   gmsh::option::setNumber(
"Mesh.Algorithm3D", a);
   234   std::vector<std::pair<int, int>> 
surfaces;
   235   gmsh::model::getEntities(surfaces, 2);
   236   std::string name = 
"";
   237   for (
const std::pair<int, int> &s : surfaces) {
   240     gmsh::model::getEntityName(dim, tag, name);
   241     std::cout << 
"Surface " << tag << 
" name: " << name << std::endl;
   243   gmsh::model::getEntityName(3, 1, name);
   244   std::cout << 
"Volume " << 1 << 
" name: " << name << std::endl;
   252   std::vector<std::pair<int, int>> 
surfaces;
   253   gmsh::model::getEntities(surfaces, 2);
   254   for (
const std::pair<int, int> &s : surfaces) {
   258     gmsh::model::getColor(dim, tag, r, g, b, a);
   259     std::cout << 
"Surface " << tag << 
" color: " << r << 
"," << g << 
"," << b
   268   bool bgfAssigned = 
false;
   274     std::string type = sf.type;
   275     if (sf.type == 
"Frustum") {
   277       for (
auto &prm : sf.params) {
   278         if (prm.first == 
"Thickness") {
   280           std::cout << 
"thickness = " << thick << std::endl;
   284       for (
auto &prm : sf.params) {
   285         std::string key = prm.first;
   286         int val = 
static_cast<int>(prm.second);
   287         if (key == 
"IField") {
   289             if (sf2.type == 
"Cylinder" && sf2.id == val) {
   301               for (
auto &prm2 : sf2.params) {
   302                 if (prm2.first == 
"Radius") radius = prm2.second;
   304                 if (prm2.first == 
"VIn") vin = prm2.second;
   305                 if (prm2.first == 
"VOut") vout = prm2.second;
   306                 if (prm2.first == 
"XCenter") xc = prm2.second;
   307                 if (prm2.first == 
"YCenter") yc = prm2.second;
   308                 if (prm2.first == 
"ZCenter") zc = prm2.second;
   309                 if (prm2.first == 
"XAxis") xa = prm2.second;
   310                 if (prm2.first == 
"YAxis") ya = prm2.second;
   311                 if (prm2.first == 
"ZAxis") za = prm2.second;
   318               std::pair<std::string, double> p;
   319               p = {
"R1_inner", radius};
   320               sf.params.push_back(p);
   321               p = {
"R1_outer", radius + thick};
   322               sf.params.push_back(p);
   323               p = {
"R2_inner", radius};
   324               sf.params.push_back(p);
   325               p = {
"R2_outer", radius + thick};
   326               sf.params.push_back(p);
   328               p = {
"V1_inner", vin};
   329               sf.params.push_back(p);
   330               p = {
"V2_inner", vin};
   331               sf.params.push_back(p);
   332               p = {
"V1_outer", vout};
   333               sf.params.push_back(p);
   334               p = {
"V2_outer", vout};
   335               sf.params.push_back(p);
   337               double mag = sqrt(xa * xa + ya * ya + za * za);
   339               p = {
"X1", xc - xa / 2 - xa * (thick / mag)};
   340               sf.params.push_back(p);
   341               p = {
"Y1", yc - ya / 2 - ya * (thick / mag)};
   342               sf.params.push_back(p);
   343               p = {
"Z1", zc - za / 2 - za * (thick / mag)};
   344               sf.params.push_back(p);
   346               p = {
"X2", xc + xa / 2 + xa * (thick / mag)};
   347               sf.params.push_back(p);
   348               p = {
"Y2", yc + ya / 2 + ya * (thick / mag)};
   349               sf.params.push_back(p);
   350               p = {
"Z2", zc + za / 2 + za * (thick / mag)};
   351               sf.params.push_back(p);
   368     gmsh::model::mesh::field::add(sf->type, sf->id);
   369     for (
auto prm = (sf->params).begin(); prm != (sf->params).end(); prm++) {
   370       if (prm->first != 
"")
   371         gmsh::model::mesh::field::setNumber(sf->id, prm->first, prm->second);
   384     for (
auto prm = (sf->num_list_params).begin();
   385          prm != (sf->num_list_params).end(); prm++) {
   386       gmsh::model::mesh::field::setNumbers(sf->id, prm->first, prm->second);
   395     std::cout << 
"Using size field ID = " << 
id << std::endl;
   397     gmsh::model::mesh::field::setAsBackgroundMesh(highest_id);
   398     std::cout << 
"Warning: BackgroundField ID not found. "   399               << 
"Using size field with highest ID." << std::endl;
   401   gmsh::model::occ::synchronize();
   406   std::vector<std::pair<int, int>> volumes;
   407   gmsh::model::getEntities(volumes, 3);
   409   std::vector<int> volumeTags;
   410   for(
const std::pair<int,int> &v : volumes) {
   413     volumeTags.push_back(tag);
   415   gmsh::model::addPhysicalGroup(3, volumeTags);
   418   std::vector<std::pair<int, int>> 
surfaces;
   419   gmsh::model::getEntities(surfaces, 2);
   432     const auto &groupColor = iter->first;
   433     std::string groupColorStr = std::to_string(groupColor.at(0)) + 
"," +
   434                                 std::to_string(groupColor.at(1)) + 
"," +
   435                                 std::to_string(groupColor.at(2));
   436     std::string groupName = iter->second;
   437     std::vector<int> surfTags;
   440     for(
const std::pair<int,int> &s : surfaces) {
   444       gmsh::model::getColor(dim, tag, r, g, b, a);
   445       if (groupColor != std::array<int, 3>{r, g, b}) 
continue;
   446       std::string surfName = groupName + 
"_" + std::to_string(
id);
   447       gmsh::model::setEntityName(dim, tag, surfName);
   448       surfTags.push_back(tag);
   451     if(surfTags.size() == 0) {
   452       std::cout << 
"NO SURFACES WITH COLOR " << groupColorStr << 
" FOUND."   455       std::cout << 
"Found "   457                 << ((surfTags.size() == 1) ? 
" surface" : 
" surfaces")
   460                 << 
" mapped by color "   463       std::cout << 
"Adding physical group " << groupName << std::endl;
   464       int groupTag = gmsh::model::addPhysicalGroup(2, surfTags);
   465       gmsh::model::setPhysicalName(2, groupTag, groupName.c_str());
   468   gmsh::model::occ::synchronize();
   472   gmsh::vectorpair volumes;
   473   gmsh::model::getEntities(volumes, 3);
   475   for(
const std::pair<int,int> &v : volumes) {
   477     int volumeTag = v.second;
   480     auto blockIter = std::lower_bound(
   486         blockIter->id != volumeTag) {
   490     const auto &block = *blockIter;
   492     gmsh::vectorpair volume = { v };
   494     gmsh::vectorpair curves;
   496     gmsh::model::getBoundary(volume, surfaces, 
false, 
false, 
false);
   497     gmsh::model::getBoundary(surfaces, curves, 
false, 
false, 
false);
   500     gmsh::vectorpair uniqueCurves;
   501     for(
const std::pair<int,int> &c : curves) {
   502       auto iter = std::find(uniqueCurves.begin(), uniqueCurves.end(), c);
   503       if (iter == uniqueCurves.end()) {
   504         uniqueCurves.push_back(c);
   508     if(uniqueCurves.size() != 12) {
   509       std::cout << 
"Found " << uniqueCurves.size() << 
" unique curves in volume " << volumeTag <<
   510                 ". There should be 12." << std::endl;
   511       std::cout << 
"Error : only hexahedral transfinite volumes are supported." << std::endl;
   515     std::cout << 
"Found transfinite block : " << volumeTag << std::endl;
   519       std::pair<int,int> curve;
   523     std::vector<CurveData> orientedCurves;
   525     for(
const std::pair<int,int> &c : uniqueCurves) {
   527       gmsh::vectorpair curves = { c };
   529       gmsh::model::getBoundary(curves, points, 
false, 
true, 
true);
   531       std::pair<int,int> a = points[0];
   532       std::pair<int,int> b = points[1];
   534       std::vector<double> a_vert, b_vert;
   535       gmsh::model::getValue(a.first, a.second, {}, a_vert);
   536       gmsh::model::getValue(b.first, b.second, {}, b_vert);
   539       double ab[] = { b_vert[0]-a_vert[0],
   541                       b_vert[2]-a_vert[2] };
   542       double ab_den = std::sqrt(ab[0]*ab[0] + ab[1]*ab[1] + ab[2]*ab[2]);
   543       ab[0] = ab[0]/ab_den;
   544       ab[1] = ab[1]/ab_den;
   545       ab[2] = ab[2]/ab_den;
   551       for(
int axis = 0; axis < 3; ++axis) {
   552         double dot = ab[0]*block.axis[axis][0] +
   553                      ab[1]*block.axis[axis][1] +
   554                      ab[2]*block.axis[axis][2];
   555         double theta = std::acos(dot);
   556         if(theta < M_PI/4 || theta > 3*M_PI/4) {
   557           bool reverse = theta >= M_PI / 4;
   561           data.reverse = reverse;
   562           orientedCurves.push_back(data);
   567     for(
auto &oc : orientedCurves) {
   569       std::pair<int,int> curve = oc.curve;
   570       bool reverse = oc.reverse;
   573       int vert = block.vert[oc.axis];
   574       double coef = block.coef[oc.axis];
   575       std::string type = block.type[oc.axis];
   577       if(type == 
"Progression") {
   579         coef = reverse ? 1/coef : coef;
   582       gmsh::model::mesh::setTransfiniteCurve(curve.second, vert, type, coef);
   585     std::cout << 
"Setting transfinite surfaces..." << std::endl;
   586     for(
const std::pair<int,int> &s : surfaces) {
   587       gmsh::model::mesh::setTransfiniteSurface(s.second);
   588       gmsh::model::mesh::setRecombine(s.first, s.second);
   591     std::cout << 
"Setting transfinite volume..." << std::endl;
   592     gmsh::model::mesh::setTransfiniteVolume(v.second);
 double maxSize
Maximum global mesh size. 
~gmshGen()
gmshGen standard destructor 
data_type data
Edge/face with sorted point ids (a, b, c, ...) is located at some index i in data[b], with data[b][i].first == [a, c] (for edges, third point id treated as -1). 
std::string mshFname
Name of .msh file output by gmsh. 
int elementOrder
Element order. 
static const std::array< const char *, 6 > & getMeshExtensions()
Get list of file extensions supported by gmsh. 
bool sizeFromCurvature
Mesh size based on curvature option. 
void globalOptions()
Sets the global geometry and meshing options. 
int bgField
Size field ID to use as background field. 
A struct for defining hexahedral transfinite volumes. 
std::string find_ext(const std::string &fname)
int createMeshFromSTL(const char *fname) override
Creates mesh from input STEP file. 
gmshGen()
gmshGen default constructor 
std::set< TransfiniteBlock > transfiniteBlocks
Map from volume id to transfinite hexahedron information. 
void meshSizeFields()
Applies mesh size fields. 
bool extSizeFromBoundary
Extend mesh size from boundary option. 
void getSurfaceColors()
Gets the surface colors of STEP geometry. 
double minSize
Minimum global mesh size. 
std::string trim_fname(const std::string &name, const std::string &ext)
std::string algo3D
Volume meshing algorithm. 
void applyTransfiniteVolumes()
Applies transfinite settings to prescribed hexahedral volumes. 
std::map< std::array< int, 3 >, std::string > color2groupMap
Map from RGB to physical name. 
gmshParams contains all parameters essential for mesh generation using gmshGen class methods...
bool saveAll
Save all elements. 
vtkIdType id
id in .inp file 
std::string ofname
Output mesh file name. 
std::vector< vtkIdType > points
points given by id in .inp file 
std::string algo2D
Surface meshing algorithm. 
std::map< std::string, std::vector< std::pair< vtkIdType, int > > > surfaces
Map from SURFACE name to (element id, side) (id and side both use .inp IDs) 
bool optimize
Whether to optimize mesh or not. 
bool fragmentAll
Whether to call boolean fragments on all volumes. 
double optimizeThreshold
Mesh optimization threshold, between 0 and 1. 
int minElePer2Pi
Minimum number of mesh elements per two Pi. 
int subdivisionAlg
Subdivision algorithm 0: none, 1: all quads, 2: all hexas. 
int createMeshFromSTEP(const char *fname)
void applyColorNames()
Applies physical names based on color. 
void getGeomNames()
Gets geometry entitiy names of STEP geometry. 
gmshParams * meshParams
gmshParams object Parameters 
std::vector< volSizeField > sizeFields
Vector for volSizeField struct.