7#include <vtkUnstructuredGrid.h>
8#include <vtkMultiBlockDataSet.h>
10#include <vtkInformation.h>
11#include <vtkModelMetadata.h>
13#include <vtkExodusIIWriter.h>
15#include <vtkPointData.h>
16#include <vtkCellData.h>
21#define scvtkid static_cast<vtkIdType>
27 bool suppress_node_sets,
28 bool suppress_side_sets)
const
30 const std::string fname =
"chi_mesh::MeshContinuum::ExportCellsToExodus";
31 Chi::log.
Log() <<
"Exporting mesh to Exodus file with base " << file_base_name;
34 throw std::logic_error(fname +
": Currently this routine is only allowed "
37 const auto& grid = *
this;
40 std::map<int, chi_mesh::CellType> block_id_map;
43 const int mat_id = cell.material_id_;
44 if (block_id_map.count(mat_id) == 0)
45 block_id_map[mat_id] = cell.SubType();
48 if (cell.SubType() != block_id_map.at(mat_id))
49 throw std::logic_error(fname +
": Material id " +
50 std::to_string(mat_id) +
" appearing for more "
51 "than one cell type.");
58 int max_dimension = 0;
63 points->SetDataType(VTK_DOUBLE);
66 global_node_id_list->SetName(
"GlobalNodeId");
69 global_elem_id_list->SetName(
"GlobalElementId");
72 block_id_list->SetName(
"BlockID");
75 std::vector<uint64_t> vertex_map(grid.GetGlobalVertexCount(), 0);
76 const size_t num_verts = grid.GetGlobalVertexCount();
77 for (
size_t v=0; v<num_verts; ++v)
80 const auto& vertex = grid.vertices[v];
81 points->InsertNextPoint(vertex.x,vertex.y,vertex.z);
85 global_node_id_list->InsertNextValue(
scvtkid(v+1));
89 for (
const auto& cell : grid.local_cells)
93 throw std::logic_error(fname +
": Cell-subtype \"" +
95 "supported by exodus.");
97 block_id_list->InsertNextValue(cell.material_id_);
103 global_elem_id_list->InsertNextValue(
scvtkid(cell.global_id_+1));
107 ugrid->SetPoints(points);
108 ugrid->GetPointData()->AddArray(global_node_id_list);
109 ugrid->GetCellData()->AddArray(global_elem_id_list);
110 ugrid->GetCellData()->AddArray(block_id_list);
112 ugrid->GetPointData()->SetActiveGlobalIds(
"GlobalNodeId");
113 ugrid->GetCellData()->SetActiveGlobalIds(
"GlobalElementId");
116 grid_blocks->SetBlock(0, ugrid);
119 <<
"Writing grid block "
120 <<
" Number of cells: " << ugrid->GetNumberOfCells()
121 <<
" Number of points: " << ugrid->GetNumberOfPoints();
129 uint64_t source_cell_id;
132 typedef std::vector<FaceInfo> ListOfFaces;
133 std::map<uint64_t, ListOfFaces> boundary_id_faces_map;
134 for (
const auto& cell : grid.local_cells)
143 const size_t num_faces = cell.faces_.size();
144 std::vector<int> face_mapping(num_faces, 0);
146 face_mapping = { 2, 3, 4, 0, 1 };
148 face_mapping = { 2, 1, 3, 0, 4, 5 };
151 for (
size_t f=0; f<cell.faces_.size(); ++f)
152 face_mapping[f] =
static_cast<int>(f);
159 for (
const auto& face : cell.faces_)
161 if (not face.has_neighbor_)
162 boundary_id_faces_map[face.neighbor_id_].push_back(
163 {&face,cell.global_id_,face_mapping[f]});
171 for (
const auto& [bndry_id, face_list] : boundary_id_faces_map)
173 const std::string block_name = grid.GetBoundaryIDMap().at(bndry_id);
175 " name=\"" + block_name +
"\"";
182 points->SetDataType(VTK_DOUBLE);
185 node_global_ids->SetName(
"GlobalNodeId");
188 std::set<uint64_t> vid_set;
189 for (
const auto& face_info : face_list)
190 for (uint64_t vid : face_info.face_ptr->vertex_ids_)
194 std::vector<uint64_t> vertex_map(grid.GetGlobalVertexCount(), 0);
196 uint64_t mapped_id = 0;
197 for (uint64_t vid : vid_set)
198 vertex_map[vid] = mapped_id++;
202 for (uint64_t vid : vid_set)
204 const auto& vertex = grid.vertices[vid];
205 points->InsertNextPoint(vertex.x,vertex.y,vertex.z);
209 node_global_ids->InsertNextValue(
scvtkid(vid+1));
213 for (uint64_t vid : vid_set)
215 std::vector<vtkIdType> cell_vids = {
scvtkid(vertex_map[vid])};
216 ugrid->InsertNextCell(VTK_VERTEX,
221 ugrid->SetPoints(points);
222 ugrid->GetPointData()->AddArray(node_global_ids);
224 ugrid->GetPointData()->SetActiveGlobalIds(
"GlobalNodeId");
226 nodesets_blocks->SetBlock(bndry_id, ugrid);
227 nodesets_blocks->GetMetaData(bndry_id)->
228 Set(vtkCompositeDataSet::NAME(), block_name);
231 <<
"Writing nodeset block " << block_name
232 <<
" Number of cells: " << ugrid->GetNumberOfCells()
233 <<
" Number of points: " << ugrid->GetNumberOfPoints();
241 points->SetDataType(VTK_DOUBLE);
245 src_cell_global_ids->SetName(
"SourceElementId");
246 src_cell_face_id->SetName(
"SourceElementSide");
249 std::set<uint64_t> vid_set;
250 for (
const auto& face_info : face_list)
251 for (uint64_t vid : face_info.face_ptr->vertex_ids_)
255 std::vector<uint64_t> vertex_map(grid.GetGlobalVertexCount(), 0);
257 uint64_t mapped_id = 0;
258 for (uint64_t vid : vid_set)
259 vertex_map[vid] = mapped_id++;
263 for (uint64_t vid : vid_set)
265 const auto& vertex = grid.vertices[vid];
266 points->InsertNextPoint(vertex.x,vertex.y,vertex.z);
270 for (
const auto& face_info : face_list)
273 src_cell_global_ids->InsertNextValue(
scvtkid(face_info.source_cell_id));
274 src_cell_face_id->InsertNextValue(face_info.source_face_id);
277 ugrid->SetPoints(points);
278 ugrid->GetCellData()->AddArray(src_cell_global_ids);
279 ugrid->GetCellData()->AddArray(src_cell_face_id);
281 sidesets_blocks->SetBlock(bndry_id, ugrid);
282 sidesets_blocks->GetMetaData(bndry_id)->
283 Set(vtkCompositeDataSet::NAME(), block_name);
286 <<
"Writing sideset block " << block_name
287 <<
" Number of cells: " << ugrid->GetNumberOfCells()
288 <<
" Number of points: " << ugrid->GetNumberOfPoints();
293 unsigned int next_block = 0;
295 main_block->SetBlock(next_block++, grid_blocks);
296 if (not suppress_node_sets)
299 main_block->SetBlock(next_block, nodesets_blocks);
300 main_block->GetMetaData(next_block++)->Set(vtkCompositeDataSet::NAME(),
"Node Sets");
302 if (not suppress_side_sets)
305 main_block->SetBlock(next_block, sidesets_blocks);
306 main_block->GetMetaData(next_block++)->Set(vtkCompositeDataSet::NAME(),
"Side Sets");
310 writer->SetBlockIdArrayName(
"BlockID");
312 writer->SetFileName((file_base_name +
".e").c_str());
313 writer->SetStoreDoubles(1);
315 writer->SetInputData(main_block);
317 writer->WriteOutGlobalNodeIdArrayOff();
318 writer->WriteOutGlobalElementIdArrayOff();
319 writer->WriteOutBlockIdArrayOff();
341 auto em = writer->GetModelMetadata();
343 Chi::log.
Log() <<
"Num Blocks : " << em->GetNumberOfBlocks();
344 Chi::log.
Log() <<
"Num Node Sets: " << em->GetNumberOfNodeSets();
345 Chi::log.
Log() <<
"Num Side Sets: " << em->GetNumberOfSideSets();
346 Chi::log.
Log() <<
"Dimension : " << em->GetDimension();
350 Chi::log.
Log() <<
"Done exporting mesh to exodus.";
static chi::MPI_Info & mpi
LogStream Log(LOG_LVL level=LOG_0)
void ExportCellsToExodus(const std::string &file_base_name, bool suppress_node_sets=false, bool suppress_side_sets=false) const
LocalCellHandler local_cells
static int GetCellDimension(const chi_mesh::Cell &cell)
void Set(VecDbl &x, const double &val)
void UploadFaceGeometry(const chi_mesh::CellFace &cell_face, const std::vector< uint64_t > &vertex_map, vtkNew< vtkUnstructuredGrid > &ugrid)
void UploadCellGeometryContinuous(const chi_mesh::Cell &cell, const std::vector< uint64_t > &vertex_map, vtkNew< vtkUnstructuredGrid > &ugrid)
std::string CellTypeName(CellType type)