Skip to content

Commit 5e76e96

Browse files
committed
Adding support for hex elements in the vtkhdf writer function
1 parent e5c7d0c commit 5e76e96

1 file changed

Lines changed: 39 additions & 45 deletions

File tree

openmc/mesh.py

Lines changed: 39 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2444,7 +2444,8 @@ class UnstructuredMesh(MeshBase):
24442444
_UNSUPPORTED_ELEM = -1
24452445
_LINEAR_TET = 0
24462446
_LINEAR_HEX = 1
2447-
_VTK_TETRA = 10
2447+
_VTK_TET = 10
2448+
_VTK_HEX = 12
24482449

24492450
def __init__(self, filename: PathLike, library: str, mesh_id: int | None = None,
24502451
name: str = '', length_multiplier: float = 1.0,
@@ -2814,29 +2815,33 @@ def append_dataset(dset, array):
28142815
dset.resize(origLen + array.shape[0], axis=0)
28152816
dset[origLen:] = array
28162817

2817-
if self.library != "moab":
2818-
raise NotImplementedError("VTKHDF output is only supported for MOAB meshes")
2819-
2820-
# the self.connectivity contains arrays of length 8 to support hex
2821-
# elements as well, in the case of tetrahedra mesh elements, the
2822-
# last 4 values are -1 and are removed
2823-
trimmed_connectivity = []
2824-
for cell in self.connectivity:
2825-
# Find the index of the first -1 value, if any
2826-
first_negative_index = np.where(cell == -1)[0]
2827-
if first_negative_index.size > 0:
2828-
# Slice the array up to the first -1 value
2829-
trimmed_connectivity.append(cell[: first_negative_index[0]])
2818+
# This writer supports linear tetrahedra and linear hexahedra elements
2819+
conn_list = [] # flattened connectivity ids
2820+
cell_sizes = [] # number of points per cell
2821+
vtk_types = [] # VTK cell types per cell (uint8)
2822+
2823+
for conn, etype in zip(self.connectivity, self.element_types):
2824+
if etype == self._LINEAR_TET:
2825+
ids = conn[:4]
2826+
vtk_types.append(self._VTK_TETRA)
2827+
elif etype == self._LINEAR_HEX:
2828+
ids = conn[:8]
2829+
vtk_types.append(self._VTK_HEXAHEDRON)
28302830
else:
2831-
# No -1 values, append the whole cell
2832-
trimmed_connectivity.append(cell)
2833-
trimmed_connectivity = np.array(trimmed_connectivity, dtype="int32").flatten()
2831+
raise RuntimeError(
2832+
f"Invalid element type {etype} found in mesh {self.id}"
2833+
)
2834+
conn_list.extend(ids.tolist())
2835+
cell_sizes.append(len(ids))
28342836

2835-
# MOAB meshes supports tet elements only so we know it has 4 points per cell
2836-
points_per_cell = 4
2837+
connectivity = np.asarray(conn_list, dtype=np.int64)
28372838

2838-
# offsets are the indices of the first point of each cell in the array of points
2839-
offsets = np.arange(0, self.n_elements * points_per_cell + 1, points_per_cell)
2839+
# Offsets must be length (numCells + 1) with a leading 0 and
2840+
# cumulative end-indices thereafter, per VTK's layout
2841+
cell_sizes_arr = np.asarray(cell_sizes, dtype=np.int64)
2842+
offsets = np.empty(cell_sizes_arr.size + 1, dtype=np.int64)
2843+
offsets[0] = 0
2844+
np.cumsum(cell_sizes_arr, out=offsets[1:])
28402845

28412846
for name, data in datasets.items():
28422847
if data.shape != self.dimension:
@@ -2858,30 +2863,19 @@ def append_dataset(dset, array):
28582863
dtype=h5py.string_dtype("ascii", len(ascii_type)),
28592864
)
28602865

2861-
# create hdf5 file structure
2862-
root.create_dataset("NumberOfPoints", (0,), maxshape=(None,), dtype="i8")
2863-
root.create_dataset("Types", (0,), maxshape=(None,), dtype="uint8")
2864-
root.create_dataset("Points", (0, 3), maxshape=(None, 3), dtype="f")
2865-
root.create_dataset(
2866-
"NumberOfConnectivityIds", (0,), maxshape=(None,), dtype="i8"
2867-
)
2868-
root.create_dataset("NumberOfCells", (0,), maxshape=(None,), dtype="i8")
2869-
root.create_dataset("Offsets", (0,), maxshape=(None,), dtype="i8")
2870-
root.create_dataset("Connectivity", (0,), maxshape=(None,), dtype="i8")
2871-
2872-
append_dataset(root["NumberOfPoints"], np.array([len(self.vertices)]))
2873-
append_dataset(root["Points"], self.vertices)
2874-
append_dataset(
2875-
root["NumberOfConnectivityIds"],
2876-
np.array([len(trimmed_connectivity)]),
2877-
)
2878-
append_dataset(root["Connectivity"], trimmed_connectivity)
2879-
append_dataset(root["NumberOfCells"], np.array([self.n_elements]))
2880-
append_dataset(root["Offsets"], offsets)
2881-
2882-
append_dataset(
2883-
root["Types"], np.full(self.n_elements, self._VTK_TETRA, dtype="uint8")
2884-
)
2866+
# Create HDF5 file structure compliant with VTKHDF UnstructuredGrid
2867+
n_points = int(len(self.vertices))
2868+
n_cells = int(len(cell_sizes))
2869+
n_conn_ids = int(len(connectivity))
2870+
2871+
root.create_dataset("NumberOfPoints", data=(n_points,), dtype="i8")
2872+
root.create_dataset("NumberOfCells", data=(n_cells,), dtype="i8")
2873+
root.create_dataset("NumberOfConnectivityIds", data=(n_conn_ids,), dtype="i8")
2874+
# VTK typically stores points as double precision
2875+
root.create_dataset("Points", data=self.vertices.astype(np.float64, copy=False), dtype="f8")
2876+
root.create_dataset("Types", data=np.asarray(vtk_types, dtype=np.uint8), dtype="uint8")
2877+
root.create_dataset("Offsets", data=offsets.astype("i8"), dtype="i8")
2878+
root.create_dataset("Connectivity", data=connectivity.astype("i8"), dtype="i8")
28852879

28862880
cell_data_group = root.create_group("CellData")
28872881

0 commit comments

Comments
 (0)