NEMoSys  0.63.0
A modular, extensible resource with robust automated mesh generation, mesh quality analysis, adaptive mesh refinement, and data transfer between arbitrary meshes.
HexPackMeshDriver.C
Go to the documentation of this file.
1 /*******************************************************************************
2 * Promesh *
3 * Copyright (C) 2022, IllinoisRocstar LLC. All rights reserved. *
4 * *
5 * Promesh is the property of IllinoisRocstar LLC. *
6 * *
7 * IllinoisRocstar LLC *
8 * Champaign, IL *
9 * www.illinoisrocstar.com *
10 * promesh@illinoisrocstar.com *
11 *******************************************************************************/
12 /*******************************************************************************
13 * This file is part of Promesh *
14 * *
15 * This version of Promesh is free software: you can redistribute it and/or *
16 * modify it under the terms of the GNU Lesser General Public License as *
17 * published by the Free Software Foundation, either version 3 of the License, *
18 * or (at your option) any later version. *
19 * *
20 * Promesh is distributed in the hope that it will be useful, but WITHOUT ANY *
21 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more *
23 * details. *
24 * *
25 * You should have received a copy of the GNU Lesser General Public License *
26 * along with this program. If not, see <https://www.gnu.org/licenses/>. *
27 * *
28 *******************************************************************************/
30 
31 #include <boost/filesystem.hpp>
32 #include "AuxiliaryFunctions.H"
36 #ifdef HAVE_GMSH
37 #include "Geometry/rocPack.H"
38 #endif
39 
40 namespace NEM {
41 namespace DRV {
42 
43 HexPackMeshDriver::Files::Files(std::string inputFile, bool isRocpack,
44  std::string outPackMeshFile,
45  std::string outSurroundingFile)
46  : outPackMeshFile(std::move(outPackMeshFile)),
47  outSurroundingFile(std::move(outSurroundingFile)),
48  rocpackOrGeoFile(std::move(inputFile)),
49  useRocpack(isRocpack) {}
50 
51 void HexPackMeshDriver::Files::setRocpackFile(std::string rocpackFile) {
52  rocpackOrGeoFile = std::move(rocpackFile);
53  useRocpack = true;
54 }
55 
56 void HexPackMeshDriver::Files::setGeoFile(std::string geoFile) {
57  rocpackOrGeoFile = std::move(geoFile);
58  useRocpack = false;
59 }
60 
61 const std::string &HexPackMeshDriver::Files::getInputFile() const {
62  return rocpackOrGeoFile;
63 }
64 
66 
68  : files_(std::move(files)), opts_(std::move(opts)) {}
69 
71  : HexPackMeshDriver({{}, {}, {}, {}}, {}) {}
72 
74  return files_;
75 }
76 
78  const auto stlFile = files.isInputRocpackFile()
79  ? files.getInputFile() + ".stl"
80  : files.getInputFile();
81  this->opts_.smParams.geomFileName = stlFile;
82  if (auto box = dynamic_cast<bmBox *>(this->opts_.bmParams.shape.get())) {
83  if (box->autoGenerate.has_value()) {
84  box->autoGenerate.value().packFileName = stlFile;
85  }
86  }
87  this->files_ = std::move(files);
88 }
89 
91  return opts_;
92 }
93 
95  const auto stlFile = getFiles().isInputRocpackFile()
96  ? getFiles().getInputFile() + ".stl"
97  : getFiles().getInputFile();
98  if (auto box = dynamic_cast<bmBox *>(opts.bmParams.shape.get())) {
99  if (box->autoGenerate.has_value()) {
100  if (!box->autoGenerate.value().packFileName.empty()) {
101  std::cerr
102  << "opts.bmParams.shape.autoGenerate.packFileName is ignored. "
103  "Using getFiles().getInputFile() for geometry file"
104  << std::endl;
105  }
106  box->autoGenerate.value().packFileName = stlFile;
107  }
108  } else {
109  std::cerr << "HexPackMeshDriver only accepts box shape for blockmesh.\n";
110  exit(1);
111  }
112 
113  if (!opts.smParams.geomFileName.empty()) {
114  std::cerr << "opts.smParams.geomFileName is ignored. Using "
115  "getFiles().getInputFile() for geometry file"
116  << std::endl;
117  }
118  opts.smParams.geomFileName = stlFile;
119 
120  // Default values specific to this driver
121  if (opts.mmfMergeParams.masterCasePath.empty()) {
122  opts.mmfMergeParams.masterCasePath = ".";
123  }
124  if (opts.mmfMergeParams.addCasePath.empty()) {
125  opts.mmfMergeParams.addCasePath = ".";
126  }
127  if (opts.mmfCreatePatchParams.surroundingName.empty()) {
129  }
130  if (opts.mmfCreatePatchParams.packsName.empty()) {
131  opts.mmfCreatePatchParams.packsName = "Rocks";
132  }
133  if (opts.mmfCreatePatchParams.srrndngPatchType.empty()) {
135  }
136  if (opts.mmfCreatePatchParams.packsPatchType.empty()) {
137  opts.mmfCreatePatchParams.packsPatchType = "wall";
138  }
139  this->opts_ = std::move(opts);
140 }
141 
143  // Makes sure that constant and triSurface directories are present.
144  // If directories are already present, it will not do anything.
145  const char dir_path[] = "./constant";
146  boost::filesystem::path dir(dir_path);
147  try {
148  boost::filesystem::create_directory(dir);
149  } catch (boost::filesystem::filesystem_error &e) {
150  std::cerr << "Problem in creating triSurface directory"
151  << "for the snappyHexMesh"
152  << "\n";
153  std::cerr << e.what() << std::endl;
154  throw;
155  }
156 
157  const char dir_path1[] = "./constant/triSurface";
158  boost::filesystem::path dir1(dir_path1);
159  try {
160  boost::filesystem::create_directory(dir1);
161  } catch (boost::filesystem::filesystem_error &e) {
162  std::cerr << "Problem in creating triSurface directory"
163  << "for the snappyHexMesh"
164  << "\n";
165  std::cerr << e.what() << std::endl;
166  throw;
167  }
168 
169  // This object has access to all MeshManipulation utilities.
170  MeshManipulationFoamParams mmfParams; // should outlive objMsh
171  mmfParams.mergeMeshesParams = this->opts_.mmfMergeParams;
172  mmfParams.createPatchParams = this->opts_.mmfCreatePatchParams;
173  auto objMsh = std::unique_ptr<MeshManipulationFoam>(
174  new MeshManipulationFoam(&mmfParams));
175  const char *nameFile = "a"; // Dummy name for input
176 
177  // A rocpack method that creates stl and then moves it to triSurface using
178  // boost.
179  if (this->files_.isInputRocpackFile()) {
180 #ifdef HAVE_GMSH
181  std::string hexOutSTL = this->files_.getInputFile() + ".stl";
182  auto objrocPck = std::unique_ptr<NEM::GEO::rocPack>(
183  new NEM::GEO::rocPack(this->files_.getInputFile(), hexOutSTL));
184 
185  objrocPck->removeBoundaryVolumes();
186  objrocPck->rocPack2Surf();
187 
188  // const std::string dir_path11 = hexOutSTL;
189  boost::filesystem::path dir11(hexOutSTL);
190 
191  const std::string dir_path2 =
192  "./constant/triSurface/" + this->files_.getInputFile() + ".stl";
193  boost::filesystem::path dir2(dir_path2);
194 
195  boost::filesystem::copy_file(
196  dir11, dir2, boost::filesystem::copy_option::overwrite_if_exists);
197 #else
198  std::cerr << "Cannot process rocPack input file without gmsh.\n";
199  std::exit(1);
200 #endif
201  } else {
202  const std::string dir_path11 = this->files_.getInputFile();
203  boost::filesystem::path dir11(dir_path11);
204 
205  const std::string dir_path2 =
206  "./constant/triSurface/" + this->files_.getInputFile();
207  boost::filesystem::path dir2(dir_path2);
208 
209  boost::filesystem::copy_file(
210  dir11, dir2, boost::filesystem::copy_option::overwrite_if_exists);
211  }
212 
213  // blockMesh utility takes user input for surrounding box region and
214  // generates mesh block in constant/polyMesh folder. It will overwrite the
215  // previous mesh created by CfMesh. This mesh will be used as background mesh
216  // by snappyHexMesh later.
217  auto bmParamsCopy = this->opts_.bmParams; // should outlive objBM
218  bmParamsCopy.isPackMesh = true;
219  auto objBM = std::unique_ptr<blockMeshGen>(new blockMeshGen(&bmParamsCopy));
220  objBM->createMeshFromSTL(nameFile);
221 
222  // Updating location for next process
223  auto adjust = this->opts_.locAdjust >= 0. ? this->opts_.locAdjust : 0.;
224  auto smParamsCopy = this->opts_.smParams; // should outlive objSHM
225  smParamsCopy.isPackMesh = true;
226  smParamsCopy.castMeshControls.locMesh[0] =
227  std::dynamic_pointer_cast<bmBox>(bmParamsCopy.shape)->coordsBox.first[0] +
228  0.001 + adjust;
229  smParamsCopy.castMeshControls.locMesh[1] =
230  std::dynamic_pointer_cast<bmBox>(bmParamsCopy.shape)->coordsBox.first[1] +
231  0.001 + adjust;
232  smParamsCopy.castMeshControls.locMesh[2] =
233  std::dynamic_pointer_cast<bmBox>(bmParamsCopy.shape)->coordsBox.first[2] +
234  0.001 + adjust;
235 
236  // snappyHexMesh reads background mesh created using blockMesh and takes
237  // surface file from foamToSurface utility to snap pack surface onto back-
238  // ground mesh and creates different cellZones (i.e different solids). These
239  // interfaces between pack and surrounding regions are completely conformal
240  // due to snappyHexMesh's unique snapping abilities.
241  auto objSHM =
242  std::unique_ptr<snappymeshGen>(new snappymeshGen(&smParamsCopy));
243  objSHM->createMeshFromSTL(nameFile);
244 
245  // splitMeshRegions reads mesh from constant/polyMesh directory and splits
246  // mesh into separate regions. Each region will represent one solid. It will
247  // write bunch of domain.* directories inside constant/ and system/ folders.
248  // This function does a random walking around mesh to identify different
249  // regions and in that process, while naming all domains as domain.*
250  // in constant folder, it skips one number for the disconnected region it
251  // encounters first. This number is taken out to provide as input to merge
252  // mesh.
253  std::pair<std::vector<int>, std::vector<std::string>> dirStat =
254  objMsh->splitMshRegions();
255 
256  std::string surroundingRegion = dirStat.second[0];
257  mmfParams.surfSplitParams.pckRegionNames = dirStat.second;
258 
259  /*std::pair<std::vector<int>, std::string> dirStat =
260  objMsh->splitMshRegions(); int skippedDir = dirStat.first[0]; int totalRegs =
261  dirStat.first[1] - 1; std::string surroundingRegion = dirStat.second;
262  */
263 
264  // *************** Merge meshes using geoMeshBase and write
265  // *******************// packRegNames is a vector containing all names of pack
266  // regions
267  mmfParams.surfSplitParams.pckRegionNames.erase(
268  mmfParams.surfSplitParams.pckRegionNames.begin());
269  std::vector<std::string> packRegNames =
271 
272  // FoamGeoMesh
273  auto fgm_ = NEM::MSH::Read(surroundingRegion + ".foam");
275  mesh->takeGeoMesh(fgm_);
276 
277  for (auto &packRegName : packRegNames) {
278  auto fgm_loop = NEM::MSH::Read(packRegName + ".foam");
279  mesh->mergeGeoMesh(fgm_loop);
280  }
281 
282  mesh->write(this->files_.outCombinedFile);
283 
284  mesh->Delete();
285  fgm_->Delete();
286 
287  // *************** Merge meshes using meshBase and write *******************//
288 
289  // bool readDB = false;
290  // // Create surrounding region database
291  // meshBase *fm = new FOAM::foamMesh(readDB);
292  // fm->read(surroundingRegion);
293  // std::vector<double> physId = std::vector<double>(fm->getNumberOfCells(),
294  // 0); auto *vm = new vtkMesh(fm->getDataSet(),
295  // this->files_.outCombinedFile); vm->setCellDataArray("PhysGrpId", physId);
296  //
297  // // Loop through all pack particles and merge their databases into main
298  // // database
299  // for (int i = 0; i < (int) packRegNames.size(); i++) {
300  // fm->read(packRegNames[i]);
301  // std::vector<double> physIdLoop =
302  // std::vector<double>(fm->getNumberOfCells(), i + 1);
303  // auto *vm2 =
304  // new vtkMesh(fm->getDataSet(), "pack" + std::to_string(i) + ".vtu");
305  // vm2->setCellDataArray("PhysGrpId", physIdLoop);
306  // // vm2->write();
307  // vm->merge(vm2->getDataSet());
308  // }
309  //
310  // // Write mesh and clean up objects
311  // vm->report();
312  // vm->write();
313  // delete vm;
314  // delete fm;
315 
316  // *************** Merge meshes using OF and write ************************ //
317  // Use this method for writing pack and surrounding meshes separately. This
318  // uses mergeMeshes method from "src/MeshManipulation/MeshManipulationFoam.C".
319  // It also writes merged mesh at the end. Use this as a replacement for the
320  // method directly above (Merge meshes using meshBase).
321 
322  // mergeMeshes will read master domain (defined by user) from constant folder
323  // and start merging other domain to it untill all slave domains are attached
324  // to master domain. It loops through all domains in sequential manner and
325  // skips the missing domain.* (also skipped by splitMeshRegions) to avoid
326  // runtime error.
327  // std::cout << "Total # of domains are = " << totalRegs << std::endl;
328  // if (totalRegs == 1) {
329  // // Nothing
330  // } else {
331  // objMsh->mergeMeshes(skippedDir, totalRegs);
332  // }
333 
334  // // Reads current mesh and write it to separate VTK/VTU files
335  // // Reads and converts pack mesh
336  // bool readDB = false;
337  // std::string regNme;
338  // if (skippedDir == 1)
339  // regNme = "domain2";
340  // else
341  // regNme = "domain1";
342 
343  // if (totalRegs == 1) regNme = _snappyparams->singleSolidPatch;
344 
345  // meshBase *fm = new FOAM::foamMesh(readDB);
346  // fm->read(regNme);
347  // vtkMesh *vm2 = new vtkMesh(fm->getDataSet(), ofname_pack);
348  // std::vector<double> physIdPack
349  // = std::vector<double>(fm->getNumberOfCells(),1);
350  // vm2->setCellDataArray("PhysGrpId",physIdPack);
351  // vm2->write();
352 
353  // // Reads and converts surronding mesh
354  // regNme = surroundingRegion;
355 
356  // if (totalRegs == 1) regNme = surroundingRegion;
357  // meshBase *fm2 = new FOAM::foamMesh(readDB);
358  // fm2->read(regNme);
359  // std::vector<double> physIdSurrounding
360  // = std::vector<double>(fm2->getNumberOfCells(),0);
361  // vtkMesh *vm3 = new vtkMesh(fm2->getDataSet(), ofname_surrndng);
362  // vm3->setCellDataArray("PhysGrpId",physIdSurrounding);
363  // vm3->write();
364 
365  // // Merge meshes and write
366  // vtkMesh *vm = new vtkMesh(vm2->getDataSet(),ofname_merged);
367  // vm->merge(vm3->getDataSet());
368  // vm->report();
369  // vm->write();
370  // if (vm) delete vm;
371  // if (fm) delete fm;
372  // if (vm2) delete vm2;
373  // if (fm2) delete fm2;
374  // if (vm3) delete vm3;
375 
376  // // Outputs useful mesh quality parameters for users
377  // std::string SurroundingName = "surroundingMeshQuality";
378  // std::string Surroundingmesh = "geom_surrounding_mesh.vtu";
379  // std::string PackName = "packMeshQuality";
380  // std::string Packmesh = "geom_pack_mesh.vtu";
381  // MeshQualityDriver *objSurrQ =
382  // new MeshQualityDriver(Surroundingmesh, SurroundingName);
383  // MeshQualityDriver *objPackQ = new MeshQualityDriver(Packmesh, PackName);
384  // if (objSurrQ) delete objSurrQ;
385  // if (objPackQ) delete objPackQ;
386  // *************** Merge meshes using OF and write ************************ //
387 
388  // End of workflow
389 }
390 
391 } // namespace DRV
392 } // namespace NEM
std::string masterCasePath
Specifies directory for master mesh.
snappymeshGen facilitates full-hexahedral/hex-dominent meshing of complex geometries with surface...
Definition: snappymeshGen.H:55
blockMeshGen <– meshGen <– meshBase This class incorporates mesh generating method of blockMesh uti...
Definition: blockMeshGen.H:54
void execute() const override
Run the workflow represented by the driver.
geoMeshBase * Read(const std::string &fileName)
Read a mesh from file.
This class converts Rockpack output file into periodic geometry and writes into STL, VTK, .MSH, and ExodusII file format.
Definition: rocPack.H:77
MeshManipulationFoamParams::CreatePatch mmfCreatePatchParams
geoMeshBase * New(MeshType meshType)
Create a new mesh object.
MeshManipulationFoamParams defines basic parameters needed for utilities in MeshManipulationFoam clas...
STL namespace.
std::string outCombinedFile
Combined mesh file name.
void setGeoFile(std::string geoFile)
std::string packsPatchType
Defines packs patch type for createPatch utility (this is specific to "Pack Mesh" workflow) ...
std::vector< std::string > pckRegionNames
A vector containing all region names for packs.
const Files & getFiles() const
bool isPackMesh
Boolean for packmesh.
std::string geomFileName
Input geometry STL name.
std::string addCasePath
Specifies directory for mesh to be merge with master mesh.
bool isPackMesh
Boolean for if the operation is packmesh.
MeshManipulation class contains several OpenFOAM utilities to perform various mesh manipulation opera...
SurfaceSplitByManifold surfSplitParams
double locAdjust
Perturb location in mesh if snappy fails.
std::shared_ptr< meshBase > mesh
std::shared_ptr< bmShape > shape
3D block, sphere, cylinder, or tapered cone
std::string srrndngPatchType
Defines surrounding patch type for createPatch utility (this is specific to "Pack Mesh" workflow) ...
std::pair< std::array< double, 3 >, std::array< double, 3 > > coordsBox
Pair of min and max box locations for autogenerate.
const Opts & getOpts() const
const std::string & getInputFile() const
std::string packsName
Defines packs patch name for createPatch utility (this is specific to "Pack Mesh" workflow) ...
void setRocpackFile(std::string rocpackFile)
std::string surroundingName
Defines surrounding patch name for createPatch utility (this is specific to "Pack Mesh" workflow) ...
MeshManipulationFoamParams::MergeMeshes mmfMergeParams