29 #if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES) 30 # define _USE_MATH_DEFINES 44 #include <vtkDataArray.h> 45 #include <vtkDoubleArray.h> 46 #include <vtkIdList.h> 47 #include <vtkStringArray.h> 49 #include <IOobjectList.H> 51 #include <cellZoneSet.H> 53 #include <foamVtkVtuAdaptor.H> 54 #include <globalMeshData.H> 55 #include <timeSelector.H> 56 #include <topoSetSource.H> 66 const std::string &geoArrayName) {
68 Foam::word regionName;
70 if (fileName.empty()) {
71 regionName = Foam::fvMesh::defaultRegion;
73 regionName = fileName;
76 bool writeDicts =
false;
77 std::unique_ptr<getDicts> initFoam;
78 initFoam = std::unique_ptr<getDicts>(
new getDicts());
79 foamGM->controlDict_ = initFoam->createControlDict(writeDicts);
81 foamGM->runTime_ = std::unique_ptr<Foam::Time>(
82 new Foam::Time(foamGM->controlDict_.get(),
".",
"."));
84 foamGM->fmesh_.reset(
new Foam::fvMesh(
85 Foam::IOobject(regionName, foamGM->runTime_->timeName(),
86 *foamGM->runTime_, Foam::IOobject::MUST_READ)));
88 auto gmMesh =
foam2GM(foamGM->fmesh_.get());
90 foamGM->setGeoMesh(gmMesh);
98 const std::string &phyGrpArrayName)
100 std::cout <<
"foamGeoMesh Constructed" << std::endl;
104 std::cout <<
"foamGeoMesh destructed" << std::endl;
108 const std::string &phyGrpArrayName) {
110 vtkSmartPointer<vtkUnstructuredGrid> vtkdataSet =
115 return {vtkdataSet,
"",
"", {}};
117 const Foam::cellZoneMesh &cellZones =
118 foamMesh->cellZones();
119 Foam::label zoneI = cellZones.size();
125 std::cout <<
"Performing topological decomposition.\n";
126 auto objVfoam = Foam::vtk::vtuAdaptor();
127 vtkdataSet = objVfoam.internal(*foamMesh);
130 Foam::List<Foam::scalar> physGrps(foamMesh->nCells(), 0.0);
132 for (
int i = 0; i < zoneI; i++) {
133 const Foam::cellZone &cz = cellZones[i];
138 vtkSmartPointer<vtkDoubleArray> pg =
140 pg->SetName(phyGrpArrayName.c_str());
141 pg->SetNumberOfComponents(1);
142 for (
int i = 0; i < foamMesh->nCells(); i++)
143 pg->InsertNextTuple1(physGrps[i]);
144 vtkdataSet->GetCellData()->AddArray(pg);
148 const Foam::polyBoundaryMesh &patches = foamMesh->boundaryMesh();
149 Foam::wordList patchNames = patches.names();
150 Foam::wordList patchTypes = patches.types();
152 Foam::label patchSize = patches.size();
153 std::vector<int> face_patch_map;
154 Foam::label nFaces = foamMesh->nFaces();
155 for (
int i = 0; i < nFaces; i++)
156 face_patch_map.push_back(
int(patches.whichPatch(i)));
160 Foam::faceList allFaces = foamMesh->faces();
161 Foam::labelList faceOwners = foamMesh->faceOwner();
162 Foam::pointField allPoints = foamMesh->points();
165 int nonInternalFaces = 0;
166 for (
int i = 0; i < patchSize; i++) nonInternalFaces += patches[i].size();
167 Foam::faceList sideSetOnlyFaces(nonInternalFaces);
168 Foam::labelList sideSetOnlyFaceLabels(nonInternalFaces);
169 Foam::labelList sideSetOnlyOwners(nonInternalFaces);
171 for (
int i = 0; i < static_cast<int>(face_patch_map.size()); i++) {
172 if (face_patch_map[i] != -1) {
173 sideSetOnlyFaces[indx] = allFaces[i];
174 sideSetOnlyOwners[indx] = faceOwners[i];
175 sideSetOnlyFaceLabels[indx] = i;
180 sideSet->SetPoints(vtkdataSet->GetPoints());
184 std::vector<int> facePntIds;
185 for (
int i = 0; i < sideSetOnlyFaces.size(); i++) {
186 if (sideSetOnlyFaces[i].size() == 3) {
188 vtkSmartPointer<vtkIdList> vtkCellIds =
190 vtkCellIds->SetNumberOfIds(sideSetOnlyFaces[i].size());
191 for (
int j = 0; j < sideSetOnlyFaces[i].size(); j++)
192 vtkCellIds->SetId(j, sideSetOnlyFaces[i][j]);
193 sideSet->InsertNextCell(5, vtkCellIds);
194 }
else if (sideSetOnlyFaces[i].size() == 4) {
196 vtkSmartPointer<vtkIdList> vtkCellIds =
198 vtkCellIds->SetNumberOfIds(sideSetOnlyFaces[i].size());
199 for (
int j = 0; j < sideSetOnlyFaces[i].size(); j++)
200 vtkCellIds->SetId(j, sideSetOnlyFaces[i][j]);
201 sideSet->InsertNextCell(9, vtkCellIds);
202 }
else if (sideSetOnlyFaces[i].size() > 4) {
204 vtkSmartPointer<vtkIdList> vtkCellIds =
206 vtkCellIds->SetNumberOfIds(sideSetOnlyFaces[i].size());
207 for (
int j = 0; j < sideSetOnlyFaces[i].size(); j++)
208 vtkCellIds->SetId(j, sideSetOnlyFaces[i][j]);
209 sideSet->InsertNextCell(7, vtkCellIds);
211 Foam::Info <<
"Face type not supported yet!" << Foam::nl;
216 sideSetEntities->SetName(
"GeoEnt");
219 sideSetOrigCellId->SetName(
"OrigCellIds");
220 sideSetOrigCellId->SetNumberOfComponents(2);
223 sideSetCellFaceId->SetName(
"CellFaceIds");
224 sideSetCellFaceId->SetNumberOfComponents(2);
227 sideSetPatchId->SetName(
"PatchIds");
230 sideSetPatchName->SetName(
"PatchNames");
232 for (
int i = 0; i < sideSetOnlyFaces.size(); i++) {
233 sideSetEntities->InsertNextValue(
234 static_cast<int>(physGrps[sideSetOnlyOwners[i]]));
235 sideSetOrigCellId->InsertNextTuple2(sideSetOnlyOwners[i],-1);
238 for (
int i = 0; i < sideSetOnlyOwners.size(); i++) {
239 const Foam::cell& facesCell = foamMesh->cells()[sideSetOnlyOwners[i]];
240 for (
int j = 0; j < facesCell.size(); j++) {
241 if (foamMesh->faces()[facesCell[j]] == sideSetOnlyFaces[i]) {
242 sideSetCellFaceId->InsertNextTuple2(j,-1);
247 for (
int i = 0; i < sideSetOnlyFaces.size(); i++) {
248 sideSetPatchId->InsertNextValue(face_patch_map[sideSetOnlyFaceLabels[i]]);
249 sideSetPatchName->InsertNextValue(
250 patchNames[face_patch_map[sideSetOnlyFaceLabels[i]]]);
254 sideSet->GetCellData()->AddArray(sideSetPatchId);
255 sideSet->GetFieldData()->AddArray(sideSetPatchName);
259 SideSet(sideSet, sideSetEntities, sideSetOrigCellId, sideSetCellFaceId);
264 gmsh::model::add(gmshMesh);
265 gmsh::model::setCurrent(gmshMesh);
268 std::set<std::pair<int, int>> dim_phyGrp;
270 auto phyGrpArray = vtkArrayDownCast<vtkDataArray>(
271 vtkdataSet->GetCellData()->GetArray(phyGrpArrayName.c_str(), idx));
272 vtkSmartPointer<vtkGenericCell> vtkGC =
277 for (vtkIdType i = 0; i < vtkdataSet->GetNumberOfCells(); ++i) {
278 vtkGC->SetCellType(vtkdataSet->GetCellType(i));
279 int dim = vtkGC->GetCellDimension();
280 int phyGrp =
static_cast<int>(phyGrpArray->GetComponent(i, 0));
282 dim_phyGrp.insert({dim, phyGrp});
286 for (
const auto &dp : dim_phyGrp) {
287 gmsh::model::addDiscreteEntity(dp.first, dp.second);
288 gmsh::model::addPhysicalGroup(dp.first, {dp.second}, dp.second);
293 return {vtkdataSet, gmshMesh, phyGrpArrayName, sideSetStruct};
298 const GeoMesh &geoMesh, Foam::Time *runTime,
299 const std::string &phyGrpArrayName) {
300 int numPoints =
static_cast<int>(geoMesh.
mesh->GetNumberOfPoints());
301 int numCells =
static_cast<int>(geoMesh.
mesh->GetNumberOfCells());
303 Foam::pointField pointData(numPoints);
304 Foam::pointField pointData2(numPoints);
305 Foam::cellShapeList cellShapeData(numCells);
306 Foam::cellShapeList cellShapeData2(numCells);
310 std::vector<std::vector<double>> verts;
311 verts.resize(numPoints);
312 for (
int ipt = 0; ipt < numPoints; ipt++) {
313 std::vector<double> getPt = std::vector<double>(3);
314 geoMesh.
mesh->GetPoint(ipt, &getPt[0]);
315 verts[ipt].resize(3);
316 verts[ipt][0] = getPt[0];
317 verts[ipt][1] = getPt[1];
318 verts[ipt][2] = getPt[2];
322 std::vector<std::vector<int>> cellIds;
323 cellIds.resize(numCells);
326 std::vector<int> typeCell;
327 typeCell.resize(numCells);
329 for (
int i = 0; i < numPoints; i++) {
330 pointData[i] = Foam::vector(verts[i][0], verts[i][1], verts[i][2]);
331 pointData2[i] = Foam::vector(verts[i][0], verts[i][1], verts[i][2]);
334 for (
int i = 0; i < numCells; i++) {
336 geoMesh.
mesh->GetCellPoints(i, ptIds);
337 int numIds =
static_cast<int>(ptIds->GetNumberOfIds());
338 cellIds[i].resize(numIds);
339 for (
int j = 0; j < numIds; j++) cellIds[i][j] = static_cast<int>(ptIds->GetId(j));
340 Foam::labelList meshPoints(numIds);
341 for (
int k = 0; k < numIds; k++) meshPoints[k] = cellIds[i][k];
342 typeCell[i] = geoMesh.
mesh->GetCellType(i);
343 if (typeCell[i] == 12) {
344 cellShapeData[i] = Foam::cellShape(
"hex", meshPoints,
true);
345 cellShapeData2[i] = Foam::cellShape(
"hex", meshPoints,
true);
346 }
else if (typeCell[i] == 14) {
347 cellShapeData[i] = Foam::cellShape(
"pyr", meshPoints,
true);
348 cellShapeData2[i] = Foam::cellShape(
"pyr", meshPoints,
true);
349 }
else if (typeCell[i] == 10) {
350 cellShapeData[i] = Foam::cellShape(
"tet", meshPoints,
true);
351 cellShapeData2[i] = Foam::cellShape(
"tet", meshPoints,
true);
353 std::cerr <<
"Only Hexahedral, Tetrahedral," 354 <<
" and Pyramid cells are supported in foamGeoMesh!" 364 Foam::word regName =
"";
369 std::map<int, std::string> ptchNameIDMap;
370 Foam::faceListList bndryFaces(0);
371 Foam::wordList BndryPatchNames(0);
372 Foam::wordList BndryPatchTypes(0);
373 Foam::wordList boundaryPatchPhysicalTypes(0);
375 std::vector<int> startIds;
376 std::vector<int> nFacesInPatch;
377 Foam::PtrList<Foam::polyPatch> patchPtrList(0);
378 Foam::cellList cellLst2(0);
379 Foam::faceList faceLst2(0);
382 auto ptchIds = vtkIntArray::FastDownCast(
383 geoMesh.
sideSet.
sides->GetCellData()->GetArray(
"PatchIds", idx1));
384 auto ptchNms = vtkStringArray::SafeDownCast(
385 geoMesh.
sideSet.
sides->GetFieldData()->GetAbstractArray(
"PatchNames",
388 if (idx1 != -1 && idx2 != -1) {
390 for (
int i = 0; i < ptchIds->GetNumberOfTuples(); ++i) {
392 auto cc = ptchIds->GetTypedComponent(i, 0);
396 std::string nm = ptchNms->GetValue(i);
399 ptchNameIDMap[id_p] = nm;
402 totalPatches =
static_cast<int>(ptchNameIDMap.size());
403 std::vector<int> faceCounts(totalPatches,
405 std::vector<std::vector<int>> facePatchIds;
406 facePatchIds.resize(totalPatches);
407 for (
int i = 0; i < ptchIds->GetNumberOfTuples(); ++i) {
409 auto cc = ptchIds->GetTypedComponent(i, 0);
411 faceCounts[id_p] += 1;
412 facePatchIds[id_p].push_back(i);
415 BndryPatchNames.setSize(totalPatches);
416 BndryPatchTypes.setSize(totalPatches);
418 auto iter = ptchNameIDMap.begin();
420 while (iter != ptchNameIDMap.end()) {
421 BndryPatchNames[r_indx] = iter->second;
422 BndryPatchTypes[r_indx] =
"patch";
430 for (
int i = 0; i < totalPatches; i++) {
431 Foam::faceList thisPatch(0);
433 for (
int j : facePatchIds[i]) {
436 int numIds =
static_cast<int>(ptIds->GetNumberOfIds());
437 Foam::labelList lstLbl(0);
439 for (
int k = 0; k < numIds; k++) {
440 lstLbl.append(static_cast<int>(ptIds->GetId(k)));
442 if (!lstLbl.empty()) thisPatch.append(Foam::face(lstLbl));
444 bndryFaces.append(thisPatch);
445 nFacesInPatch.push_back(thisPatch.size());
447 boundaryPatchPhysicalTypes.resize(totalPatches,
448 Foam::polyPatch::typeName);
453 Foam::polyMesh tmpfm(
454 Foam::IOobject(regName, runTime->timeName(), *runTime,
455 Foam::IOobject::NO_READ, Foam::IOobject::AUTO_WRITE),
456 std::move(pointData),
462 Foam::polyPatch::typeName,
465 const Foam::polyBoundaryMesh &patches2 = tmpfm.boundaryMesh();
467 for (
int i = 0; i < patches2.size(); i++) {
468 auto *tmpPtch =
new Foam::polyPatch(patches2[i]);
469 patchPtrList.append(tmpPtch);
473 const Foam::cellList &cellLst = tmpfm.cells();
475 const Foam::faceList &faceLst = tmpfm.faces();
479 auto fm = std::unique_ptr<Foam::fvMesh>(
new Foam::fvMesh(
480 Foam::IOobject(regName, runTime->timeName(), *runTime,
481 Foam::IOobject::NO_READ, Foam::IOobject::AUTO_WRITE),
482 std::move(pointData2), std::move(faceLst2), std::move(cellLst2)));
485 fm->addFvPatches(patchPtrList,
true);
488 std::vector<double> allGroups;
490 vtkSmartPointer<vtkDataArray> cd =
491 geoMesh.
mesh->GetCellData()->GetArray(phyGrpArrayName.c_str(), idx);
495 for (
nemId_t i = 0; i < cd->GetNumberOfTuples(); ++i) {
497 allGroups.push_back(x[0]);
501 std::vector<double> scratchVec = allGroups;
502 std::sort(scratchVec.begin(), scratchVec.end());
503 scratchVec.erase(unique(scratchVec.begin(), scratchVec.end()),
505 int totalGroups =
static_cast<int>(scratchVec.size());
509 for (
int i = 0; i < totalGroups; i++) {
510 Foam::labelList currentGroupList;
512 for (
int j = 0; j < static_cast<int>(allGroups.size()); j++) {
513 if (static_cast<int>(allGroups[j]) == i) currentGroupList.append(j);
516 const Foam::cellZoneMesh &cellZones = fm->cellZones();
517 zoneI = cellZones.size();
518 fm->cellZones().setSize(zoneI + 1);
519 Foam::word nameSet =
"pg_" + std::to_string(i);
521 new Foam::cellZone(nameSet, currentGroupList, zoneI, cellZones);
522 fm->cellZones().set(zoneI, clzn);
524 fm->cellZones().writeOpt() = Foam::IOobject::AUTO_WRITE;
531 Foam::word w =
"system";
532 if (!Foam::isDir(w)) Foam::mkDir(w);
535 Foam::fileName fcontrolDict =
"system/controlDict";
536 if (!Foam::exists(fcontrolDict)) {
537 Foam::OFstream outcontrolDict(fcontrolDict);
538 Foam::IOobject::writeBanner(outcontrolDict);
543 Foam::fileName ffvSchemes =
"system/fvSchemes";
544 if (!Foam::exists(ffvSchemes)) {
545 Foam::OFstream outfvSchemes(ffvSchemes);
546 Foam::IOobject::writeBanner(outfvSchemes);
551 Foam::fileName ffvSolution =
"system/fvSolution";
552 if (!Foam::exists(ffvSolution)) {
553 Foam::OFstream outfvSolution(ffvSolution);
554 Foam::IOobject::writeBanner(outfvSolution);
559 Foam::fileName newReg =
"";
560 if (fileName.empty())
566 if (!Foam::isDir(
"system/" + newReg)) Foam::mkDir(
"system/" + newReg);
568 Foam::fileName fcontrolDict_2 =
"system/" + newReg +
"/controlDict";
569 if (!Foam::exists(fcontrolDict_2)) { Foam::cp(fcontrolDict, fcontrolDict_2); }
572 Foam::fileName ffvSchemes_2 =
"system/" + newReg +
"/fvSchemes";
573 if (!Foam::exists(ffvSchemes_2)) { Foam::cp(ffvSchemes, ffvSchemes_2); }
576 Foam::fileName ffvSolution_2 =
"system/" + newReg +
"/fvSolution";
577 if (!Foam::exists(ffvSolution_2)) { Foam::cp(ffvSolution, ffvSolution_2); }
580 if (!Foam::isDir(
"0")) Foam::mkDir(
"0");
583 const Foam::cellZoneMesh &czMesh =
fmesh_->cellZones();
584 Foam::label numZones = czMesh.size();
590 for (
int i = 0; i < numZones; i++) {
591 const Foam::cellZone &cz = czMesh[i];
596 Foam::fileName currentDir =
"0";
597 Foam::fileName currentReg =
fmesh_->dbDir();
598 Foam::fileName newDir =
"constant";
599 Foam::fileName finalMesh =
"";
601 if (currentReg.empty()) {
602 if (!Foam::isDir(currentDir +
"/" + newReg))
603 Foam::mkDir(currentDir +
"/" + newReg);
604 if (!newReg.empty()) {
605 Foam::mv(currentDir +
"/polyMesh",
606 currentDir +
"/" + newReg +
"/polyMesh");
607 finalMesh = currentDir +
"/" + newReg;
609 finalMesh = currentDir +
"/polyMesh";
612 if (!newReg.empty()) {
613 Foam::mv(currentDir +
"/" + currentReg, currentDir +
"/" + newReg);
614 finalMesh = currentDir +
"/" + newReg;
616 Foam::mv(currentDir +
"/" + currentReg, currentDir +
"/");
617 finalMesh = currentDir +
"/polyMesh";
621 if (!Foam::isDir(newDir +
"/" + newReg)) {
622 if (!newReg.empty()) {
623 Foam::mkDir(newDir +
"/" + newReg);
624 Foam::mv(finalMesh, newDir +
"/" + newReg);
626 Foam::mkDir(newDir +
"/polyMesh");
627 Foam::mv(finalMesh, newDir +
"/polyMesh");
631 if (!newReg.empty()) {
632 if (!Foam::isDir(newDir +
"/" + newReg)) {
633 Foam::mkDir(newDir +
"/" + newReg);
634 Foam::mv(finalMesh, newDir +
"/" + newReg);
637 if (!Foam::isDir(newDir +
"/polyMesh")) Foam::mkDir(newDir +
"/polyMesh");
638 Foam::mv(finalMesh, newDir +
"/polyMesh");
646 fmesh_ = std::unique_ptr<Foam::fvMesh>(foamMesh.get());
668 bool writeDicts =
false;
669 std::unique_ptr<getDicts> initFoam;
670 initFoam = std::unique_ptr<getDicts>(
new getDicts());
672 fvSchemes_ = initFoam->createFvSchemes(writeDicts);
673 fvSolution_ = initFoam->createFvSolution(writeDicts);
677 std::unique_ptr<Foam::Time>(
new Foam::Time(controlDict_.get(),
".",
"."));
678 Foam::argList::noParallel();
virtual void report(std::ostream &out) const =0
Print a report about the mesh.
void write(const std::string &fileName) override
Writes foam mesh into current directory.
vtkSmartPointer< vtkUnstructuredGrid > mesh
geoMeshBase * Read(const std::string &fileName)
Read a mesh from file.
geoMeshBase * New(MeshType meshType)
Create a new mesh object.
~foamGeoMesh() override
foamGeoMesh destructor
static GeoMesh foam2GM(Foam::fvMesh *foamMesh, const std::string &phyGrpArrayName=std::string())
Create a GeoMesh from a fvMesh.
void setGeoMesh(const geoMeshBase::GeoMesh &geoMesh)
Set the underlying geometry object.
static void Initialize()
Initialize Gmsh.
static std::unique_ptr< Foam::fvMesh > GM2foam(const GeoMesh &geoMesh, Foam::Time *runTime, const std::string &phyGrpArrayName=std::string())
Create a fvMesh from geoMeshBase.
void report(std::ostream &out) const override
Reports data about mesh.
std::unique_ptr< Foam::dictionary > controlDict_
foamGeoMesh()
Create a foamMesh from mesh in current directory.
std::string getRandomString(int length)
std::unique_ptr< Foam::dictionary > fvSolution_
void setFoamMesh(std::unique_ptr< Foam::fvMesh > foamMesh)
Set the foamGeoMesh's mesh to foamMesh.
vtkSmartPointer< vtkPolyData > sides
Cells represent edges/faces of some GeoMesh.
void InitializeFoam()
Initializes arguments and runtime objects.
std::unique_ptr< Foam::fvMesh > fmesh_
vtkStandardNewMacro(exoGeoMesh)
A concrete implementation of geoMeshBase representing a mesh in a fvMesh.
std::unique_ptr< Foam::dictionary > fvSchemes_
abstract class to specify geometry and mesh data
void resetNative() override
Resets the class members and initiates an empty foam mesh.
std::unique_ptr< Foam::Time > runTime_
const GeoMesh & getGeoMesh() const
Get the underlying geometry object.