29 #if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES) 30 # define _USE_MATH_DEFINES 36 #include <vtkCellIterator.h> 37 #include <vtkCompositeDataIterator.h> 38 #include <vtkEmptyCell.h> 39 #include <vtkExodusIIReader.h> 40 #include <vtkInformation.h> 41 #include <vtkMultiBlockDataSet.h> 42 #include <vtkTransform.h> 43 #include <vtkTransformFilter.h> 45 #include <unordered_set> 65 void checkExodusErr(
int errNum,
bool createOrOpen =
false) {
66 if (errNum < 0 || (!createOrOpen && errNum > 0)) {
69 ex_get_err(&msg, &func, &errNum);
70 ex_opts(EX_VERBOSE | EX_ABORT);
71 ex_err(func, msg, errNum);
75 const char *vtkCellType2exoType(VTKCellType vtkCellType) {
76 switch (vtkCellType) {
77 case VTK_TRIANGLE:
return "TRIANGLE";
78 case VTK_QUAD:
return "QUAD";
79 case VTK_TETRA:
return "TETRA";
80 case VTK_HEXAHEDRON:
return "HEX";
81 case VTK_WEDGE:
return "WEDGE";
82 default:
return "OTHER";
86 int exoSide2vtkSide(
int exoSide, VTKCellType vtkCellType) {
87 switch (vtkCellType) {
107 default:
return exoSide - 1;
111 int vtkSide2exoSide(
int vtkSide,
int vtkCellType) {
112 switch (vtkCellType) {
132 default:
return vtkSide + 1;
136 std::string getArrComponentName(vtkDataArray *arr,
int component) {
137 auto componentName = arr->GetComponentName(component);
139 return std::string{componentName};
141 if (!arr->GetName()) {
142 return std::string{};
144 std::string varName = arr->GetName();
145 if (arr->GetNumberOfComponents() == 2) {
146 if (component == 0) {
151 }
else if (arr->GetNumberOfComponents() == 3) {
152 if (component == 0) {
154 }
else if (component == 1) {
159 }
else if (arr->GetNumberOfComponents() == 6) {
160 if (component == 0) {
162 }
else if (component == 1) {
164 }
else if (component == 2) {
166 }
else if (component == 3) {
168 }
else if (component == 4) {
173 }
else if (arr->GetNumberOfComponents() > 1) {
174 varName += std::to_string(component);
191 std::pair<vtkSmartPointer<vtkIdTypeArray>, vtkSmartPointer<vtkIdTypeArray>>
192 mergeMeshes(vtkUnstructuredGrid *mesh1, vtkUnstructuredGrid *mesh2,
193 vtkUnstructuredGrid *outMesh,
float tol) {
194 if (mesh1->GetCellData()->GetGlobalIds()) {
195 mesh1->GetCellData()->RemoveArray(
196 mesh1->GetCellData()->GetGlobalIds()->GetName());
198 if (mesh1->GetCellData()->GetPedigreeIds()) {
199 mesh1->GetCellData()->RemoveArray(
200 mesh1->GetCellData()->GetPedigreeIds()->GetName());
204 merge->SetUnstructuredGrid(outMesh);
205 merge->SetTotalNumberOfDataSets(2);
206 merge->SetTotalNumberOfPoints(mesh1->GetNumberOfPoints() +
207 mesh2->GetNumberOfPoints());
208 merge->SetTotalNumberOfCells(mesh1->GetNumberOfCells() +
209 mesh2->GetNumberOfCells());
210 merge->SetPointMergeTolerance(tol);
211 auto nodeMap1 = merge->MergeDataSet(mesh1);
212 auto nodeMap2 = merge->MergeDataSet(mesh2);
214 for (
int i = outMesh->GetCellData()->GetNumberOfArrays() - 1; i >= 0; --i) {
215 if (outMesh->GetCellData()->GetArray(i)->GetNumberOfTuples() !=
216 outMesh->GetNumberOfCells()) {
217 outMesh->GetCellData()->RemoveArray(i);
220 for (
int i = outMesh->GetPointData()->GetNumberOfArrays() - 1; i >= 0; --i) {
221 if (outMesh->GetPointData()->GetArray(i)->GetNumberOfTuples() !=
222 outMesh->GetNumberOfPoints()) {
223 outMesh->GetPointData()->RemoveArray(i);
226 return {nodeMap1, nodeMap2};
229 void resetSideSetPoints(vtkUnstructuredGrid *
mesh, vtkPolyData *sideSet,
230 vtkIdTypeArray *nodeMap) {
232 sideSet->SetPoints(mesh->GetPoints());
233 for (vtkIdType i = 0; i < sideSet->GetNumberOfCells(); ++i) {
234 auto oldCell = sideSet->GetCell(i);
235 auto numPoints = oldCell->GetNumberOfPoints();
236 auto oldPoints = oldCell->GetPointIds();
237 for (
int j = 0; j < numPoints; ++j) {
238 oldPoints->SetId(j, nodeMap->GetValue(oldPoints->GetId(j)));
240 sideSet->ReplaceCell(i, numPoints, oldPoints->GetPointer(0));
254 return vtkExodusIIReader::GetObjectIdArrayName();
261 if (reader && reader->GetOutput() &&
262 reader->GetOutput()->GetNumberOfBlocks() == 8) {
263 auto mbds = reader->GetOutput();
264 _title = reader->GetTitle();
265 auto elemBlocks = vtkMultiBlockDataSet::SafeDownCast(mbds->GetBlock(0));
266 for (
unsigned int i = 0; i < elemBlocks->GetNumberOfBlocks(); ++i) {
267 std::string elemBlockName =
268 elemBlocks->GetMetaData(i)->Get(vtkMultiBlockDataSet::NAME());
270 vtkUnstructuredGrid::SafeDownCast(elemBlocks->GetBlock(i));
275 vtkIntArray::FastDownCast(
278 cellType =
static_cast<VTKCellType
>(
elemBlock->GetCellType(0));
281 vtkIntArray::FastDownCast(
282 elemBlock->GetFieldData()->GetAbstractArray(
"ElementBlockIds"))
284 cellType = VTK_EMPTY_CELL;
288 auto sideSets = vtkMultiBlockDataSet::SafeDownCast(mbds->GetBlock(4));
289 if (sideSets->GetNumberOfBlocks() >= 1) {
290 for (
int i = 0; i < sideSets->GetNumberOfBlocks(); ++i) {
291 auto sideSetName = reader->GetSideSetArrayName(i);
292 auto sideSetId = reader->GetObjectId(vtkExodusIIReader::SIDE_SET, i);
298 std::map<vtkIdType, vtkIdType> globalNodeId2meshIdx;
299 auto globalNodeIdArr =
300 vtkIdTypeArray::FastDownCast(mesh->GetPointData()->GetAbstractArray(
301 reader->GetGlobalNodeIdArrayName()));
302 for (vtkIdType i = 0; i < mesh->GetNumberOfPoints(); ++i) {
303 globalNodeId2meshIdx[globalNodeIdArr->GetValue(i)] = i;
305 mesh->GetPointData()->RemoveArray(reader->GetGlobalNodeIdArrayName());
306 mesh->GetPointData()->RemoveArray(reader->GetPedigreeNodeIdArrayName());
307 auto nodeSets = vtkMultiBlockDataSet::SafeDownCast(mbds->GetBlock(7));
308 for (
unsigned int i = 0; i <
nodeSets->GetNumberOfBlocks(); ++i) {
309 std::string nodeSetName =
310 nodeSets->GetMetaData(i)->Get(vtkMultiBlockDataSet::NAME());
311 auto nodeSet = vtkUnstructuredGrid::SafeDownCast(
nodeSets->GetBlock(i));
313 vtkIntArray::FastDownCast(
316 std::vector<vtkIdType>
nodes;
317 nodes.reserve(
nodeSet->GetNumberOfCells());
318 auto nodeSetGlobalNodeIdArr = vtkIdTypeArray::FastDownCast(
319 nodeSet->GetPointData()->GetAbstractArray(
320 reader->GetGlobalNodeIdArrayName()));
321 for (vtkIdType j = 0; j <
nodeSet->GetNumberOfCells(); ++j) {
322 auto nodeGlobalId = nodeSetGlobalNodeIdArr->GetValue(
323 nodeSet->GetCell(j)->GetPointId(0));
324 auto find = globalNodeId2meshIdx.find(nodeGlobalId);
325 if (find != globalNodeId2meshIdx.end()) {
326 nodes.emplace_back(find->second);
329 _nodeSets[nodeSetId] = {nodeSetName, nodes};
333 int comp_ws =
sizeof(double);
337 ex_open(reader->GetFileName(), EX_READ, &comp_ws, &io_ws, &version);
338 checkExodusErr(exoid,
true);
341 std::vector<int> elemBlockIds;
343 auto err = ex_get_ids(exoid, EX_ELEM_BLOCK, elemBlockIds.data());
345 int numProps = ex_inquire_int(exoid, EX_INQ_EB_PROP);
346 std::vector<std::string> propNames;
347 propNames.resize(numProps);
348 std::vector<const char *> propNamesPtr;
349 propNamesPtr.reserve(numProps);
350 for (
int i = 0; i < numProps; ++i) {
351 propNames[i].resize(MAX_NAME_LENGTH);
352 propNamesPtr.emplace_back(propNames[i].c_str());
354 err = ex_get_prop_names(exoid, EX_ELEM_BLOCK,
355 const_cast<char **>(propNamesPtr.data()));
357 for (
int i = 0; i < numProps; ++i) {
358 if (strcmp(propNamesPtr[i],
"ID") != 0) {
359 std::vector<int> propVals;
361 err = ex_get_prop_array(exoid, EX_ELEM_BLOCK, propNamesPtr[i],
365 for (std::size_t j = 0; j <
_elemBlocks.size(); ++j) {
366 _elemBlocks[elemBlockIds[j]].properties[propNamesPtr[i]] =
371 err = ex_close(exoid);
374 std::cout <<
"exoGeoMesh constructed" << std::endl;
384 if (fileExt ==
".exo" || fileExt ==
".e" || fileExt ==
".gen" ||
386 int comp_ws =
sizeof(double);
387 int io_ws =
sizeof(double);
388 int exoid = ex_create(fileName.c_str(), EX_CLOBBER, &comp_ws, &io_ws);
389 checkExodusErr(exoid,
true);
392 auto mesh = geoMesh.mesh;
393 auto sideSet = geoMesh.sideSet;
394 if (!mesh || mesh->GetNumberOfCells() == 0) {
395 std::cerr <<
"No mesh information to write." << std::endl;
400 std::map<int, std::vector<vtkIdType>> elemBlocks;
402 auto meshEntities = vtkIntArray::FastDownCast(
407 for (vtkIdType i = 0; i < mesh->GetNumberOfCells(); ++i) {
408 auto entity = meshEntities->GetValue(i);
409 elemBlocks.at(entity).emplace_back(i);
411 for (
auto it = elemBlocks.begin(); it != elemBlocks.end();) {
412 if (it->second.empty()) {
413 it = elemBlocks.erase(it);
424 int numGlobalVars = 0;
425 std::vector<bool> cellDataWriteFlag;
426 std::vector<bool> pointDataWriteFlag;
427 std::vector<bool> fieldDataWriteFlag;
431 auto globalIds = mesh->GetCellData()->GetGlobalIds();
432 const char *globalIdName;
434 globalIdName = globalIds->GetName();
436 globalIdName =
"GlobalElementId";
438 auto pedigreeIds = mesh->GetCellData()->GetPedigreeIds();
439 const char *pedgreeIdName;
441 pedgreeIdName = pedigreeIds->GetName();
443 pedgreeIdName =
"PedigreeElementId";
445 auto numCells = mesh->GetNumberOfCells();
446 cellDataWriteFlag.resize(mesh->GetCellData()->GetNumberOfArrays(),
false);
447 for (
int i = 0; i < mesh->GetCellData()->GetNumberOfArrays(); ++i) {
449 auto arr = mesh->GetCellData()->GetArray(i);
451 auto arrName = arr->GetName();
452 if (strcmp(arrName, globalIdName) != 0 &&
453 strcmp(arrName, pedgreeIdName) != 0 &&
455 arr->GetNumberOfTuples() == numCells) {
456 auto numComponents = arr->GetNumberOfComponents();
457 cellDataWriteFlag[i] = (numComponents > 0);
458 numElemVars += numComponents;
463 globalIds = mesh->GetPointData()->GetGlobalIds();
465 globalIdName = globalIds->GetName();
467 globalIdName =
"GlobalNodeId";
469 pedigreeIds = mesh->GetPointData()->GetPedigreeIds();
471 pedgreeIdName = pedigreeIds->GetName();
473 pedgreeIdName =
"PedigreeNodeId";
475 auto numNodes = mesh->GetNumberOfPoints();
476 pointDataWriteFlag.resize(mesh->GetPointData()->GetNumberOfArrays(),
478 for (
int i = 0; i < mesh->GetPointData()->GetNumberOfArrays(); ++i) {
480 auto arr = mesh->GetPointData()->GetArray(i);
482 auto arrName = arr->GetName();
483 if (strcmp(arrName, globalIdName) != 0 &&
484 strcmp(arrName, pedgreeIdName) != 0 &&
485 arr->GetNumberOfTuples() == numNodes) {
486 auto numComponents = arr->GetNumberOfComponents();
487 pointDataWriteFlag[i] = (numComponents > 0);
488 numNodeVars += numComponents;
493 fieldDataWriteFlag.resize(mesh->GetFieldData()->GetNumberOfArrays(),
495 for (
int i = 0; i < mesh->GetFieldData()->GetNumberOfArrays(); ++i) {
497 auto arr = mesh->GetFieldData()->GetArray(i);
498 if (arr && arr->GetNumberOfTuples() == 1) {
499 auto numComponents = arr->GetNumberOfComponents();
500 fieldDataWriteFlag[i] = (numComponents > 0);
501 numGlobalVars += numComponents;
508 std::map<int, std::vector<vtkIdType>> exoSideSets;
510 auto sideSetExoId = vtkIntArray::FastDownCast(
512 for (vtkIdType i = 0; i < sideSet.sides->GetNumberOfCells(); ++i) {
513 auto entity = sideSetExoId->GetValue(i);
514 exoSideSets[entity].emplace_back(i);
520 int numNodeSets = std::accumulate(
522 [](
const int &a,
const std::pair<const int, nodeSet> &b) {
523 return a + (!b.second.nodes.empty());
526 auto err = ex_put_init(exoid,
_title.c_str(), geoMesh.getDimension(),
527 mesh->GetNumberOfPoints(), mesh->GetNumberOfCells(),
528 elemBlocks.size(), numNodeSets, exoSideSets.size());
530 if (numElemVars > 0) {
531 err = ex_put_variable_param(exoid, EX_ELEM_BLOCK, numElemVars);
534 if (numNodeVars > 0) {
535 err = ex_put_variable_param(exoid, EX_NODAL, numNodeVars);
538 if (numGlobalVars > 0) {
539 err = ex_put_variable_param(exoid, EX_GLOBAL, numGlobalVars);
542 if (numElemVars > 0 || numNodeVars > 0 || numGlobalVars > 0) {
544 err = ex_put_time(exoid, timeStep, &time);
548 std::vector<double> x_coord;
549 std::vector<double> y_coord;
550 std::vector<double> z_coord;
551 x_coord.resize(mesh->GetNumberOfPoints(), 0);
552 y_coord.resize(mesh->GetNumberOfPoints(), 0);
553 z_coord.resize(mesh->GetNumberOfPoints(), 0);
554 auto coord = mesh->GetPoints()->GetData();
555 for (vtkIdType i = 0; i < mesh->GetNumberOfPoints(); ++i) {
556 x_coord[i] = coord->GetComponent(i, 0);
557 y_coord[i] = coord->GetComponent(i, 1);
558 z_coord[i] = coord->GetComponent(i, 2);
560 err = ex_put_coord(exoid, x_coord.data(), y_coord.data(), z_coord.data());
564 std::vector<vtkIdType> vtkIdMap(mesh->GetNumberOfCells(), -1);
566 for (
const auto &
elemBlock : elemBlocks) {
567 auto firstCell = mesh->GetCell(
elemBlock.second[0]);
568 auto cellType =
static_cast<VTKCellType
>(firstCell->GetCellType());
569 err = ex_put_block(exoid, EX_ELEM_BLOCK,
elemBlock.first,
571 firstCell->GetNumberOfPoints(), 0, 0, 0);
573 std::vector<int> conn;
574 conn.reserve(
elemBlock.second.size() * firstCell->GetNumberOfPoints());
576 auto cell = mesh->GetCell(elem);
577 vtkIdMap[elem] = ++lastElemIdx;
578 for (
int i = 0; i < cell->GetNumberOfPoints(); ++i) {
580 conn.emplace_back(cell->GetPointId(i) + 1);
583 err = ex_put_conn(exoid, EX_ELEM_BLOCK,
elemBlock.first, conn.data(),
587 err = ex_put_name(exoid, EX_ELEM_BLOCK,
elemBlock.first,
594 auto sideSetOrigCellId = geoMesh.sideSet.getOrigCellArr();
595 auto sideSetCellFaceId = geoMesh.sideSet.getCellFaceArr();
596 for (
const auto &exoSideSet : exoSideSets) {
597 err = ex_put_set_param(exoid, EX_SIDE_SET, exoSideSet.first,
598 exoSideSet.second.size(), 0);
600 std::vector<int> sideSetElem, sideSetSide;
601 sideSetElem.reserve(exoSideSet.second.size());
602 sideSetSide.reserve(exoSideSet.second.size());
603 for (
auto sideIdx : exoSideSet.second) {
604 auto parentCellIdx = sideSetOrigCellId->GetTypedComponent(sideIdx, 0);
605 sideSetElem.emplace_back(vtkIdMap[parentCellIdx]);
606 sideSetSide.emplace_back(
607 vtkSide2exoSide(sideSetCellFaceId->GetTypedComponent(sideIdx, 0),
608 mesh->GetCell(parentCellIdx)->GetCellType()));
610 err = ex_put_set(exoid, EX_SIDE_SET, exoSideSet.first,
611 sideSetElem.data(), sideSetSide.data());
615 err = ex_put_name(exoid, EX_SIDE_SET, foundName->first,
616 foundName->second.c_str());
624 err = ex_put_set_param(exoid, EX_NODE_SET,
nodeSet.first,
627 std::vector<int>
nodes;
630 std::back_inserter(nodes), [](
int x) {
return x + 1; });
631 err = ex_put_set(exoid, EX_NODE_SET,
nodeSet.first, nodes.data(),
635 err = ex_put_name(exoid, EX_NODE_SET,
nodeSet.first,
642 if (numElemVars > 0) {
644 std::vector<double> vals(mesh->GetNumberOfCells());
645 for (
int i = 0; i < mesh->GetCellData()->GetNumberOfArrays(); ++i) {
646 if (cellDataWriteFlag[i]) {
647 auto arr = mesh->GetCellData()->GetArray(i);
648 for (
int j = 0; j < arr->GetNumberOfComponents(); ++j) {
649 for (vtkIdType k = 0; k < mesh->GetNumberOfCells(); ++k) {
650 vals[vtkIdMap[k] - 1] = arr->GetComponent(k, j);
652 auto name = getArrComponentName(arr, j);
654 name =
"ElemBlockVar" + std::to_string(var_index);
656 err = ex_put_variable_name(exoid, EX_ELEM_BLOCK, var_index,
659 std::size_t varOffset = 0;
660 for (
const auto &
elemBlock : elemBlocks) {
661 err = ex_put_var(exoid, timeStep, EX_ELEM_BLOCK, var_index,
663 vals.data() + varOffset);
673 if (numNodeVars > 0) {
675 std::vector<double> vals(mesh->GetNumberOfPoints());
676 for (
int i = 0; i < mesh->GetPointData()->GetNumberOfArrays(); ++i) {
677 if (pointDataWriteFlag[i]) {
678 auto arr = mesh->GetPointData()->GetArray(i);
679 for (
int j = 0; j < arr->GetNumberOfComponents(); ++j) {
680 auto name = getArrComponentName(arr, j);
682 name =
"NodalVar" + std::to_string(var_index);
685 ex_put_variable_name(exoid, EX_NODAL, var_index, name.c_str());
687 for (vtkIdType k = 0; k < mesh->GetNumberOfPoints(); ++k) {
688 vals[k] = arr->GetComponent(k, j);
690 err = ex_put_var(exoid, timeStep, EX_NODAL, var_index, 1,
691 mesh->GetNumberOfPoints(), vals.data());
698 if (numGlobalVars > 0) {
700 std::vector<double> vals;
701 for (
int i = 0; i < mesh->GetFieldData()->GetNumberOfArrays(); ++i) {
702 if (fieldDataWriteFlag[i]) {
703 auto arr = mesh->GetFieldData()->GetArray(i);
704 for (
int j = 0; j < arr->GetNumberOfComponents(); ++j) {
705 vals.emplace_back(arr->GetComponent(0, j));
706 auto name = getArrComponentName(arr, j);
708 err = ex_put_variable_name(exoid, EX_GLOBAL, var_index,
716 err = ex_put_var(exoid, timeStep, EX_GLOBAL, 1, 0, numGlobalVars,
723 std::vector<const char *> propNames;
725 std::vector<std::vector<int>> propVals;
728 propNames.emplace_back(elemBlockProp.c_str());
730 err = ex_put_prop_names(exoid, EX_ELEM_BLOCK, _elemBlockPropNames.size(),
731 const_cast<char **
>(propNames.data()));
734 auto nonEmptyIt = elemBlocks.begin();
736 while (nonEmptyIt != elemBlocks.end()) {
737 if (it->first == nonEmptyIt->first) {
738 std::size_t propValsIdx = 0;
739 auto propNamesIt = propNames.begin();
740 auto propValsIt = it->second.properties.begin();
741 while (propNamesIt != propNames.end()) {
742 if (propValsIt != it->second.properties.end() &&
743 *propNamesIt == propValsIt->first) {
744 propVals[propValsIdx].emplace_back(propValsIt->second);
747 propVals[propValsIdx].emplace_back(0);
756 for (std::size_t i = 0; i < propNames.size(); ++i) {
757 err = ex_put_prop_array(exoid, EX_ELEM_BLOCK, propNames[i],
762 err = ex_close(exoid);
765 std::cerr <<
"For exoGeoMesh, " << fileExt
766 <<
" format not currently supported." << std::endl;
772 out <<
"Title:\t" <<
_title <<
'\n';
773 out <<
"Element Blocks:\t" <<
_elemBlocks.size() <<
'\n';
775 out <<
"Node Sets:\t" <<
_nodeSets.size() <<
'\n';
779 auto otherExoGM =
dynamic_cast<exoGeoMesh *
>(otherGeoMesh);
782 otherExoGM->setGeoMesh(
784 _title = std::move(otherExoGM->_title);
787 _nodeSets = std::move(otherExoGM->_nodeSets);
790 otherExoGM->resetNative();
800 vtkSmartPointer<vtkDataArray> linkArr =
801 mesh->GetCellData()->GetArray(link.c_str());
804 linkArr->SetName(link.c_str());
805 linkArr->SetNumberOfTuples(mesh->GetNumberOfCells());
806 mesh->GetCellData()->AddArray(linkArr);
808 auto elemBlockIdArr = vtkIntArray::FastDownCast(
810 for (vtkIdType i = 0; i < mesh->GetNumberOfCells(); ++i) {
811 auto physGroup = elemBlockIdArr->GetValue(i);
815 linkArr->SetComponent(i, 0, physGroup);
830 std::map<int, std::string> names;
832 std::inserter(names, names.begin()),
834 -> decltype(names)::value_type {
835 return {block.first, block.second.name};
843 std::cerr <<
"No block found with id: " <<
id << std::endl;
846 return it->second.name;
853 std::cerr <<
"No block found with id: " <<
id << std::endl;
856 it->second.name = name;
861 std::vector<int> ids;
872 std::cerr <<
"No block found with id: " << blockId << std::endl;
875 std::vector<vtkIdType> cellIdxList;
876 auto elemBlockIdArr = vtkIntArray::FastDownCast(
878 for (vtkIdType i = 0; i <
getGeoMesh().
mesh->GetNumberOfCells(); ++i) {
879 if (elemBlockIdArr->GetValue(i) == blockId) {
880 cellIdxList.emplace_back(i);
888 if (!mesh || mesh->GetNumberOfCells() == 0) {
889 std::cerr <<
"Mesh is empty. No cells to find" << std::endl;
892 if (cellIdx < 0 || cellIdx >= mesh->GetNumberOfCells()) {
893 std::cerr <<
"No cell found with index: " << cellIdx << std::endl;
896 auto elemBlockIdArr = vtkIntArray::FastDownCast(
898 return elemBlockIdArr->GetValue(cellIdx);
902 const std::string &name,
float tol) {
903 if (elements && elements->GetNumberOfCells() > 0) {
905 elements->GetCellTypes(types);
906 if (types->GetNumberOfTypes() > 1) {
907 std::cerr <<
"Single element block cannot have multiple cell types" 912 if (mesh->GetNumberOfCells() == 0) {
913 mesh->DeepCopy(elements);
917 gmsh::model::remove();
930 return newElemBlockId;
933 std::cerr <<
"No elements to add." << std::endl;
940 if (elements && elements->GetNumberOfCells() > 0) {
942 elements->GetCellTypes(types);
943 if (types->GetNumberOfTypes() > 1) {
944 std::cerr <<
"Single element block cannot have multiple cell types" 949 if (
getGeoMesh().mesh->GetNumberOfCells() == 0) {
951 std::cerr <<
"No existing element blocks." << std::endl;
955 std::cerr <<
"No existing element block with id: " << blockId
961 <<
"Cell type does not match cell type of existing element block." 965 vtkSmartPointer<vtkAbstractArray> oldBlockIdArr =
971 auto newBlockIdArr = vtkSmartPointer<vtkIntArray>::Take(
972 vtkIntArray::FastDownCast(mesh->GetCellData()
976 newBlockIdArr->SetNumberOfValues(elements->GetNumberOfCells());
977 newBlockIdArr->FillComponent(0, blockId);
978 elements->GetCellData()->AddArray(newBlockIdArr);
982 gmsh::model::remove();
987 auto nodeMaps = mergeMeshes(mesh, elements, newMesh, tol);
991 resetSideSetPoints(newMesh,
getGeoMesh().sideSet.sides, nodeMaps.first);
994 elements->GetCellData()->AddArray(oldBlockIdArr);
997 std::cerr <<
"No elements to add." << std::endl;
1002 int blockId,
const std::string &elemBlockName) {
1003 if (!cells.empty()) {
1006 static_cast<VTKCellType
>(mesh->GetCellType(cells.front()));
1007 for (
const auto &cell : cells) {
1008 if (mesh->GetCellType(cell) !=
cellType) {
1009 std::cerr <<
"Single element block cannot have multiple cell types" 1021 auto elemBlockIdArr = vtkIntArray::FastDownCast(
1023 for (
const auto &cell : cells) {
1024 elemBlockIdArr->SetValue(cell, blockId);
1029 gmsh::model::remove();
1035 std::cerr <<
"No cells to add." << std::endl;
1041 if (
getGeoMesh().mesh->GetNumberOfCells() == 0) {
1048 std::vector<std::string> names;
1054 int blockId)
const {
1056 std::cerr <<
"No property found with name: " << propName << std::endl;
1061 std::cerr <<
"No block found with id: " << blockId << std::endl;
1064 auto it = blockIt->second.properties.find(propName);
1065 if (it == blockIt->second.properties.end()) {
1076 std::cerr <<
"No property found with name: " << propName << std::endl;
1081 std::cerr <<
"No block found with id: " << blockId << std::endl;
1084 blockIt->second.properties[propName] = value;
1097 std::cerr <<
"No side set found with id: " <<
id << std::endl;
1107 std::cerr <<
"No side set found with id: " <<
id << std::endl;
1115 std::vector<int> ids;
1118 ids.emplace_back(sideSet.first);
1124 int sideSetId)
const {
1125 std::vector<vtkIdType> cellIdVec;
1126 std::vector<int> sideVec;
1128 std::cerr <<
"No side set found with id: " << sideSetId << std::endl;
1131 auto sideSet = geoMesh.sideSet;
1132 auto sideSetExoId = vtkIntArray::FastDownCast(
1134 auto sideSetOrigCellId = geoMesh.sideSet.getOrigCellArr();
1135 auto sideSetCellFaceId = geoMesh.sideSet.getCellFaceArr();
1136 for (vtkIdType i = 0; i < sideSet.sides->GetNumberOfCells(); ++i) {
1137 if (sideSetExoId->GetValue(i) == sideSetId) {
1138 cellIdVec.emplace_back(sideSetOrigCellId->GetTypedComponent(i, 0));
1139 sideVec.emplace_back(sideSetCellFaceId->GetTypedComponent(i, 0));
1142 return {cellIdVec, sideVec};
1146 const std::vector<int> &
sides,
1147 const std::string &name) {
1148 if (!elements.empty() && elements.size() == sides.size()) {
1151 if (!gm.sideSet.sides) {
1153 sideSetPD->Allocate();
1154 sideSetPD->SetPoints(
getGeoMesh().mesh->GetPoints());
1157 sideSetPD->GetCellData()->AddArray(sideSetExoId);
1160 sideSetOrigCellId->SetNumberOfComponents(2);
1162 sideSetCellFaceId->SetNumberOfComponents(2);
1167 {sideSetPD, sideSetEntities, sideSetOrigCellId, sideSetCellFaceId}});
1170 auto sideSetExoId = vtkIntArray::FastDownCast(
1172 sideSetExoId->Resize(sideSet.sides->GetNumberOfCells() + elements.size());
1174 sideSetEntities->Resize(sideSet.sides->GetNumberOfCells() +
1176 auto sideSetOrigCellId = sideSet.getOrigCellArr();
1177 sideSetOrigCellId->Resize(sideSet.sides->GetNumberOfCells() +
1179 auto sideSetCellFaceId = sideSet.getCellFaceArr();
1180 sideSetCellFaceId->Resize(sideSet.sides->GetNumberOfCells() +
1184 auto elemIt = elements.begin();
1185 auto sidesIt = sides.begin();
1186 for (; elemIt != elements.end(); ++sidesIt, ++elemIt) {
1187 auto parent = mesh->GetCell(*elemIt);
1189 std::cerr <<
"No cell found with index " << *elemIt << std::endl;
1192 auto side = parent->GetCellDimension() == 2 ? parent->GetEdge(*sidesIt)
1193 : parent->GetFace(*sidesIt);
1194 sideSet.sides->InsertNextCell(side->GetCellType(), side->GetPointIds());
1195 sideSetExoId->InsertNextValue(newId);
1196 sideSetEntities->InsertNextValue(newId);
1197 sideSetOrigCellId->InsertNextTuple2(*elemIt, -1);
1198 sideSetCellFaceId->InsertNextTuple2(*sidesIt, -1);
1210 std::map<int, std::string> names;
1212 std::inserter(names, names.begin()),
1213 [](
const std::pair<int, nodeSet> &
set) {
1214 return std::make_pair(
set.first,
set.second.name);
1222 std::cerr <<
"No side set found with id: " <<
id << std::endl;
1225 return it->second.name;
1232 std::cerr <<
"No side set found with id: " <<
id << std::endl;
1235 it->second.name = name;
1240 std::vector<int> ids;
1243 ids.emplace_back(
nodeSet.first);
1251 std::cerr <<
"No node set found with id: " << nodeSetId << std::endl;
1254 return it->second.nodes;
1258 const std::string &name) {
1259 if (!nodes.empty()) {
1260 auto minmax = std::minmax_element(nodes.begin(), nodes.end());
1261 if (*minmax.first < 0) {
1262 std::cerr <<
"Unknown node " << *minmax.first << std::endl;
1264 }
else if (*minmax.second >=
getGeoMesh().
mesh->GetNumberOfPoints()) {
1265 std::cerr <<
"Unknown node " << *minmax.second << std::endl;
1281 std::cerr <<
"No property found with name " << physGrpName << std::endl;
1286 if (!link.empty()) {
1288 auto elemBlockIdArr = vtkIntArray::FastDownCast(
1290 auto linkArr = mesh->GetCellData()->GetArray(link.c_str());
1292 for (vtkIdType i = 0; i < mesh->GetNumberOfCells(); ++i) {
1293 linkArr->SetComponent(
1303 if (mesh->GetNumberOfCells() == 0) {
1304 std::cerr <<
"Current mesh is empty. Cannot stitch onto empty mesh." 1310 std::cerr <<
"Dimension of meshes does not match." << std::endl;
1313 auto numOrigCells = mesh->GetNumberOfCells();
1315 std::map<int, int> old2newElemBlock;
1317 std::set<std::string> propsToCopy;
1321 std::inserter(propsToCopy, propsToCopy.begin()));
1323 for (
const auto &otherElemBlock : otherGM.
_elemBlocks) {
1324 old2newElemBlock[otherElemBlock.first] = newBlockId;
1325 auto &newElemBlock = this->
_elemBlocks[newBlockId];
1326 newElemBlock.name = otherElemBlock.second.name;
1327 newElemBlock.cellType = otherElemBlock.second.cellType;
1328 for (
const auto &property : propsToCopy) {
1329 auto it = otherElemBlock.second.properties.find(property);
1330 if (it != otherElemBlock.second.properties.end()) {
1331 newElemBlock.properties[property] = it->second;
1336 auto oldOtherBlockIdArr =
1337 vtkSmartPointer<vtkIntArray>(vtkIntArray::FastDownCast(
1340 auto newOtherBlockIdArr = vtkSmartPointer<vtkIntArray>::Take(
1341 vtkIntArray::FastDownCast(mesh->GetCellData()
1345 newOtherBlockIdArr->SetNumberOfValues(otherMesh->GetNumberOfCells());
1346 for (vtkIdType i = 0; i < otherMesh->GetNumberOfCells(); ++i) {
1347 newOtherBlockIdArr->SetComponent(
1348 i, 0, old2newElemBlock.at(oldOtherBlockIdArr->GetValue(i)));
1350 otherMesh->GetCellData()->AddArray(newOtherBlockIdArr);
1354 gmsh::model::setCurrent(this->
getGeoMesh().geo);
1355 gmsh::model::remove();
1356 mesh->GetCellData()->RemoveArray(this->
getGeoMesh().link.c_str());
1361 auto nodeMaps = mergeMeshes(mesh, otherMesh, newMesh, tol);
1365 for (
const auto &otherNodeSet : otherGM.
_nodeSets) {
1368 nodeSet.
nodes.reserve(otherNodeSet.second.nodes.size());
1370 otherNodeSet.second.nodes.begin(), otherNodeSet.second.nodes.end(),
1372 [&nodeMaps](vtkIdType x) {
return nodeMaps.second->GetValue(x); });
1376 resetSideSetPoints(newMesh,
getGeoMesh().sideSet.sides, nodeMaps.first);
1380 if (otherGeoMesh.sideSet.sides) {
1381 auto otherSideSet = otherGeoMesh.
sideSet;
1382 auto otherExoIdArr = vtkIntArray::FastDownCast(
1383 otherSideSet.sides->GetCellData()->GetAbstractArray(
getExoIdArrName()));
1384 auto otherEntitiesArr = otherGeoMesh.sideSet.
getGeoEntArr();
1385 auto otherOrigCellIdArr = otherGeoMesh.sideSet.getOrigCellArr();
1386 auto otherCellFaceIdArr = otherGeoMesh.sideSet.getCellFaceArr();
1388 auto sideSet = geoMesh.sideSet;
1389 vtkSmartPointer<vtkIntArray> sideSetExoId;
1390 vtkSmartPointer<vtkIntArray> sideSetEntities;
1391 vtkSmartPointer<vtkIdTypeArray> sideSetOrigCellId;
1392 vtkSmartPointer<vtkIntArray> sideSetCellFaceId;
1393 if (sideSet.sides) {
1394 sideSetExoId = vtkIntArray::FastDownCast(
1396 sideSetEntities = geoMesh.sideSet.getGeoEntArr();
1397 sideSetOrigCellId = geoMesh.sideSet.getOrigCellArr();
1398 sideSetCellFaceId = geoMesh.sideSet.getCellFaceArr();
1401 sideSetPD->Allocate(otherSideSet.sides);
1404 sideSetExoId->Allocate(otherSideSet.sides->GetNumberOfCells());
1405 sideSet.sides->GetCellData()->AddArray(sideSetExoId);
1407 sideSetEntities->Allocate(otherSideSet.sides->GetNumberOfCells());
1409 sideSetOrigCellId->SetNumberOfComponents(2);
1410 sideSetOrigCellId->Allocate(otherSideSet.sides->GetNumberOfCells());
1412 sideSetCellFaceId->SetNumberOfComponents(2);
1413 sideSetCellFaceId->Allocate(otherSideSet.sides->GetNumberOfCells());
1414 sideSet = {sideSetPD, sideSetEntities, sideSetOrigCellId,
1419 std::map<int, int> old2newSideSet;
1422 old2newSideSet[otherSet.first] = newSideSetId;
1426 std::map<int, int> old2newGeoEnt;
1427 for (vtkIdType i = 0; i < sideSet.sides->GetNumberOfCells(); ++i) {
1428 old2newGeoEnt[sideSetEntities->GetValue(i)] = -1;
1431 for (vtkIdType i = 0; i < otherSideSet.sides->GetNumberOfCells(); ++i) {
1432 auto origCellId = otherOrigCellIdArr->GetTypedComponent(i, 0) + numOrigCells;
1433 auto cellFaceId = otherCellFaceIdArr->GetTypedComponent(i, 0);
1434 auto parent = newMesh->GetCell(origCellId);
1435 auto side = parent->GetCellDimension() == 2 ? parent->GetEdge(cellFaceId)
1436 : parent->GetFace(cellFaceId);
1437 sideSet.sides->InsertNextCell(side->GetCellType(), side->GetPointIds());
1438 int newEntId = otherEntitiesArr->GetValue(i);
1439 auto insertIter = old2newGeoEnt.insert({newEntId, nextSideSetEntId});
1440 if (insertIter.second || insertIter.first->second == -1) {
1441 if (insertIter.first->second == -1) {
1442 insertIter.first->second = nextSideSetEntId;
1447 sideSetExoId->InsertNextValue(old2newSideSet[otherExoIdArr->GetValue(i)]);
1448 sideSetEntities->InsertNextValue(insertIter.first->second);
1449 sideSetOrigCellId->InsertNextTuple2(origCellId, -1);
1450 sideSetCellFaceId->InsertNextTuple2(cellFaceId, -1);
1454 otherMesh->GetCellData()->AddArray(oldOtherBlockIdArr);
1459 transform->Scale(scale, scale, scale);
1461 transformFilter->SetTransform(transform);
1462 transformFilter->SetInputData(
getGeoMesh().mesh);
1463 transformFilter->Update();
1464 auto mesh = vtkUnstructuredGrid::SafeDownCast(transformFilter->GetOutput());
1466 if (sideSet.sides) {
1467 sideSet.
sides->SetPoints(mesh->GetPoints());
1473 vtkSmartPointer<vtkExodusIIReader> reader) {
1477 return {
mesh,
"",
"", {}};
1480 auto mbds = reader->GetOutput();
1481 if (mbds->GetNumberOfBlocks() != 8) {
1482 std::cerr <<
"Malformed output of vtkExodusIIReader. Check that file " 1483 "exists and is valid Exodus II file." 1489 std::map<vtkIdType, vtkIdType> elemId2MeshIdx;
1490 if (reader->GetNumberOfElementsInFile() > 0) {
1491 auto exoElemBlocks = vtkMultiBlockDataSet::SafeDownCast(mbds->GetBlock(0));
1493 merge->SetUnstructuredGrid(mesh);
1494 merge->SetTotalNumberOfDataSets(exoElemBlocks->GetNumberOfBlocks());
1495 merge->SetTotalNumberOfPoints(reader->GetNumberOfNodes());
1496 merge->SetTotalNumberOfCells(reader->GetTotalNumberOfElements());
1497 merge->SetUseGlobalIds(1);
1498 merge->SetUseGlobalCellIds(1);
1499 auto it = vtkSmartPointer<vtkCompositeDataIterator>::Take(
1500 exoElemBlocks->NewIterator());
1501 for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextItem()) {
1502 merge->MergeDataSet(vtkDataSet::SafeDownCast(it->GetCurrentDataObject()));
1505 for (
int i = mesh->GetCellData()->GetNumberOfArrays() - 1; i >= 0; --i) {
1506 if (mesh->GetCellData()->GetArray(i)->GetNumberOfTuples() !=
1507 mesh->GetNumberOfCells()) {
1508 mesh->GetCellData()->RemoveArray(i);
1511 for (
int i = mesh->GetPointData()->GetNumberOfArrays() - 1; i >= 0; --i) {
1512 if (mesh->GetPointData()->GetArray(i)->GetNumberOfTuples() !=
1513 mesh->GetNumberOfPoints()) {
1514 mesh->GetPointData()->RemoveArray(i);
1517 auto globalElemIdArr = vtkIdTypeArray::FastDownCast(
1518 mesh->GetCellData()->GetArray(reader->GetGlobalElementIdArrayName()));
1519 for (vtkIdType i = 0; i < mesh->GetNumberOfCells(); ++i) {
1520 elemId2MeshIdx[globalElemIdArr->GetValue(i)] = i;
1522 mesh->GetCellData()->RemoveArray(reader->GetPedigreeElementIdArrayName());
1523 mesh->GetCellData()->RemoveArray(reader->GetGlobalElementIdArrayName());
1525 if (reader->GetNumberOfSideSetArrays() > 0 &&
1526 reader->GetDimensionality() >= 2) {
1528 sideSetPD->SetPoints(mesh->GetPoints());
1529 sideSetPD->Allocate();
1534 sideSetOrigCellId->SetNumberOfComponents(2);
1536 sideSetCellFaceId->SetNumberOfComponents(2);
1538 int comp_ws =
sizeof(double);
1542 ex_open(reader->GetFileName(), EX_READ, &comp_ws, &io_ws, &version);
1543 checkExodusErr(exoid,
true);
1545 auto exoSideSets = vtkMultiBlockDataSet::SafeDownCast(mbds->GetBlock(4));
1546 for (
unsigned int i = 0; i < exoSideSets->GetNumberOfBlocks(); ++i) {
1548 vtkUnstructuredGrid::SafeDownCast(exoSideSets->GetBlock(i));
1551 auto sourceElemArr = vtkIdTypeArray::FastDownCast(
1552 exoSideSet->GetCellData()->GetAbstractArray(
1553 reader->GetSideSetSourceElementIdArrayName()));
1554 auto objectIdArr = exoSideSet->GetCellData()->GetArray(
getExoIdArrName());
1563 std::vector<int> sourceSideVec;
1564 sourceSideVec.resize(exoSideSet->GetNumberOfCells());
1565 auto err = ex_get_set(
1567 vtkIntArray::FastDownCast(
1570 nullptr, sourceSideVec.data());
1571 checkExodusErr(err);
1573 for (vtkIdType j = 0; j < exoSideSet->GetNumberOfCells(); ++j) {
1574 auto origCellId = elemId2MeshIdx.at(sourceElemArr->GetValue(j) + 1);
1575 auto parent = mesh->GetCell(origCellId);
1576 auto cellFaceId = exoSide2vtkSide(
1577 sourceSideVec[j], static_cast<VTKCellType>(parent->GetCellType()));
1578 if (reader->GetDimensionality() == parent->GetCellDimension()) {
1579 if (reader->GetDimensionality() == 2) {
1580 auto edge = parent->GetEdge(cellFaceId);
1581 sideSetPD->InsertNextCell(edge->GetCellType(), edge->GetPointIds());
1582 }
else if (reader->GetDimensionality() == 3) {
1583 auto face = parent->GetFace(cellFaceId);
1584 sideSetPD->InsertNextCell(face->GetCellType(), face->GetPointIds());
1586 sideSetExoId->InsertNextValue(
1587 static_cast<int>(objectIdArr->GetComponent(j, 0)));
1588 sideSetEntities->InsertNextValue(
1589 static_cast<int>(objectIdArr->GetComponent(j, 0)));
1590 sideSetOrigCellId->InsertNextTuple2(origCellId, -1);
1591 sideSetCellFaceId->InsertNextTuple2(cellFaceId, -1);
1595 sideSetPD->GetCellData()->AddArray(sideSetExoId);
1596 sideSetPD->Squeeze();
1597 sideSet = {sideSetPD, sideSetEntities, sideSetOrigCellId,
1599 auto err = ex_close(exoid);
1600 checkExodusErr(err);
1602 return {
mesh,
"",
"", sideSet};
1606 const std::string &fileName,
int timeStep) {
1607 static constexpr std::array<vtkExodusIIReader::ObjectType, 8> objectTypes = {
1608 vtkExodusIIReader::ObjectType::ELEM_BLOCK_ELEM_CONN,
1609 vtkExodusIIReader::ObjectType::NODE_SET_CONN,
1610 vtkExodusIIReader::ObjectType::SIDE_SET_CONN,
1611 vtkExodusIIReader::ObjectType::NODAL,
1612 vtkExodusIIReader::ObjectType::GLOBAL,
1613 vtkExodusIIReader::ObjectType::ELEM_BLOCK,
1614 vtkExodusIIReader::ObjectType::NODE_SET,
1615 vtkExodusIIReader::ObjectType::SIDE_SET};
1616 if (fileName.empty()) {
1620 reader->SetFileName(fileName.c_str());
1622 reader->SetTimeStep(timeStep - 1);
1623 reader->UpdateInformation();
1624 for (
const auto &objectType : objectTypes) {
1625 reader->SetAllArrayStatus(objectType, 1);
1627 for (
int i = 0; i < reader->GetNumberOfNodeMapArrays(); ++i) {
1628 reader->SetNodeMapArrayStatus(reader->GetNodeMapArrayName(i), 0);
1630 for (
int i = 0; i < reader->GetNumberOfElementMapArrays(); ++i) {
1631 reader->SetElementMapArrayStatus(reader->GetElementMapArrayName(i), 0);
1633 reader->GenerateGlobalElementIdArrayOn();
1634 reader->GenerateGlobalNodeIdArrayOn();
1647 auto linkArr = mesh->GetCellData()->GetArray(link.c_str());
1648 if (!link.empty() && linkArr) {
1649 elemBlockIdArr->Allocate(mesh->GetNumberOfCells());
1650 for (vtkIdType i = 0; i < mesh->GetNumberOfCells(); ++i) {
1651 elemBlockIdArr->InsertNextValue(
1652 static_cast<int>(linkArr->GetComponent(i, 0)));
1655 elemBlockIdArr->SetNumberOfValues(mesh->GetNumberOfCells());
1656 elemBlockIdArr->FillComponent(0, 1);
1658 mesh->GetCellData()->AddArray(elemBlockIdArr);
1662 gm.findSide2OrigCell();
1673 std::map<std::pair<int, VTKCellType>,
int> old2newElemBlock;
1675 auto elemBlockIds = vtkIntArray::SafeDownCast(
1680 vtkSmartPointer<vtkCellIterator>::Take(mesh->NewCellIterator());
1681 !it->IsDoneWithTraversal(); it->GoToNextCell()) {
1682 auto oldElemBlockId = elemBlockIds->GetValue(i);
1683 auto cellType =
static_cast<VTKCellType
>(it->GetCellType());
1685 old2newElemBlock.insert({{oldElemBlockId,
cellType}, nextElemBlockId});
1686 if (inserted.second) {
1694 elemBlockIds->SetValue(i, inserted.first->second);
1701 std::unordered_set<vtkIdType>
set;
1703 set.insert(nodeMap ? nodeMap->GetValue(node) : node);
1712 auto mesh = gm.mesh;
1713 auto link = gm.link;
1714 auto sideSet = gm.sideSet;
1715 if (sideSet.sides) {
1716 auto sideSetObjId = vtkIntArray::FastDownCast(
1719 for (vtkIdType i = 0; i < sideSet.sides->GetNumberOfCells(); ++i) {
1725 sideSetObjId->Allocate(sideSet.sides->GetNumberOfCells());
1726 sideSet.sides->GetCellData()->AddArray(sideSetObjId);
1727 auto sideSetEntities = gm.sideSet.getGeoEntArr();
1728 auto nameArr = sideSet.getSideSetNames();
1731 std::map<int, int> geoEnt2ExoId;
1732 int nextSideSetId = 1;
1733 for (vtkIdType i = 0; i < sideSet.sides->GetNumberOfCells(); ++i) {
1734 int geoEnt = sideSetEntities->GetValue(i);
1737 auto &exoID = geoEnt2ExoId[geoEnt];
1739 exoID = nextSideSetId;
1740 auto emplaceIter =
_sideSetNames.emplace(exoID, std::string{});
1741 if (emplaceIter.second && nameArr && geoEnt >= 0 &&
1742 geoEnt < nameArr->GetNumberOfValues()) {
1743 emplaceIter.first->second = nameArr->GetValue(geoEnt);
1747 sideSetObjId->InsertNextValue(exoID);
1749 sideSetObjId->Delete();
virtual void report(std::ostream &out) const =0
Print a report about the mesh.
std::set< std::string > _elemBlockPropNames
void setTitle(const std::string &title)
Set the title of the exoGeoMesh (used for writing out to EXODUS II file)
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::pair< std::vector< vtkIdType >, std::vector< int > > getSideSet(int sideSetId) const
Get sides in a side set.
int addSideSet(const std::vector< vtkIdType > &elements, const std::vector< int > &sides, const std::string &name="")
Add a new side set.
std::vector< std::pair< vtkIdType, std::vector< double > > > nodes
Each entry stores (node ID in .inp file, coordinates)
vtkSmartPointer< vtkUnstructuredGrid > mesh
int getNumSideSets() const
Get number of side sets.
geoMeshBase * Read(const std::string &fileName)
Read a mesh from file.
A leastUnusedKey(const std::map< A, B > &map, A min=1)
virtual void reconstructGeo()
Construct the geometry from the mesh alone.
int getElemBlockProperty(const std::string &propName, int blockId) const
Get the value of an element block property on a block.
static constexpr auto GEO_ENT_DEFAULT_NAME
std::map< int, std::string > _sideSetNames
std::map< std::string, std::vector< vtkIdType > > nodeSets
Map from NSET name to node ids (ids given by .inp file)
std::vector< int > getNodeSetIds() const
Get the IDs of all node sets.
geoMeshBase * New(MeshType meshType)
Create a new mesh object.
void scaleNodes(double scale)
Scale point locations.
void resetElemBlocks()
Clears element block names, element block properties.
void setSideSetName(int id, const std::string &name)
Set the name of a side set (used for writing out to EXODUS II file)
void resetNative() override
int getElemBlockId(vtkIdType cellIdx) const
Get the element block ID of a cell.
void write(const std::string &fileName) override
Write exoGeoMesh out to a file.
const std::string & getSideSetName(int id) const
Get the name of a side set (used for writing out to EXODUS II file)
const std::string & getPhysGrpPropertyName() const
Get the name of the element block property that maps element blocks to physical groups (if empty...
void setGeoMesh(const geoMeshBase::GeoMesh &geoMesh)
Set the underlying geometry object.
std::vector< std::string > getElemBlockPropertyNames() const
Get the names of all block properties.
const std::vector< vtkIdType > & getNodeSet(int nodeSetId) const
Get the nodes of a node set.
std::string find_ext(const std::string &fname)
std::map< int, elemBlock > _elemBlocks
const std::string & getElemBlockName(int id) const
Get the name of an element block (used for writing out to EXODUS II file)
int addElemBlock(vtkUnstructuredGrid *elements, const std::string &name="", float tol=1e-15f)
Add a new element block to the mesh.
std::map< int, nodeSet > _nodeSets
void setElemBlockProperty(const std::string &propName, int blockId, int value)
Set the value of an element block property on a block.
void addCellsToBlock(vtkUnstructuredGrid *elements, int blockId, float tol=1e-15f)
Add cells to an existing element block.
void setElemBlockName(int id, const std::string &name)
Set the name of an element block (used for writing out to EXODUS II file)
std::map< int, std::string > getElemBlockNames() const
Get all element block names.
bool addElemBlockProperty(const std::string &propName)
Add a property to element blocks (with default value 0 on all element blocks)
std::vector< int > getSideSetIds() const
Get all side set IDs.
void setSideSetObjId()
Sets the (Exodus) side set IDs of each cell in the GeoMesh.sideSet by creating a side set for each pa...
std::map< int, std::string > getNodeSetNames() const
Get all node set names.
const std::string & getTitle() const
Get the title of the exoGeoMesh (used for writing out to EXODUS II file)
vtkSmartPointer< vtkPolyData > sides
Cells represent edges/faces of some GeoMesh.
std::shared_ptr< meshBase > mesh
void setNodeSetName(int id, const std::string &name)
Set the name of a node set (used for writing out to EXODUS II file)
static GeoMesh exoReader2GM(vtkSmartPointer< vtkExodusIIReader > reader)
void setPhysGrpPropertyName(const std::string &physGrpName)
Sets the name of the element block property that maps element blocks to physical groups (if empty...
std::array< int, 2 > sides
vtkSmartPointer< vtkIntArray > getGeoEntArr() const
std::vector< vtkIdType > getElemBlock(int blockId) const
Get (0-based) indices of the cells that are in a specific element block.
int reassignCells(const std::vector< vtkIdType > &cells, int blockId=-1, const std::string &elemBlockName={})
Reassign cells to a different element block.
A concrete implementation of geoMeshBase representing an Exodus II mesh.
vtkStandardNewMacro(exoGeoMesh)
const std::map< int, std::string > & getSideSetNames() const
Get all side set names.
void stitch(const exoGeoMesh &otherGM, float tol=1e-15f)
Stitch another exoGeoMesh object onto this one.
std::vector< vtkIdType > nodes
int addNodeSet(const std::vector< vtkIdType > &nodes, const std::string &name="")
Add a new node set.
exoGeoMesh()
Reads an EXODUS II file into an exoGeoMesh object.
std::vector< int > getElemBlockIds() const
Get all element block IDs.
int getNumNodeSets() const
Get number of node sets.
static vtkSmartPointer< vtkExodusIIReader > getExoReader(const std::string &fileName, int timeStep=1)
void reconstructGeo() override
Construct the geometry from the mesh alone.
int getNumElemBlocks() const
Get number of element blocks.
std::map< std::string, int > properties
void resetNodeSetPoints(vtkIdTypeArray *nodeMap=nullptr)
Renumbers the nodes in all node sets based on nodeMap if provided.
void takeGeoMesh(geoMeshBase *otherGeoMesh) override
Take the GeoMesh of another geoMeshBase.
abstract class to specify geometry and mesh data
static const char * getExoIdArrName()
int getDimension() const
Get dimension of mesh.
const std::string & getNodeSetName(int id) const
Get the name of a node set (used for writing out to EXODUS II file)
const GeoMesh & getGeoMesh() const
Get the underlying geometry object.
void report(std::ostream &out) const override
Write a summary of this exoGeoMesh to out.
virtual void takeGeoMesh(geoMeshBase *otherGeoMesh)
Take the GeoMesh of another geoMeshBase.