Skip to content

Commit

Permalink
Merge pull request #1233 from nschloe/tags
Browse files Browse the repository at this point in the history
cellblock tags
  • Loading branch information
nschloe authored Dec 11, 2021
2 parents 514995f + 2d67f89 commit 184fb02
Show file tree
Hide file tree
Showing 39 changed files with 338 additions and 209 deletions.
24 changes: 23 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
<!--pytest-codeblocks:skipfile-->
# Changelog

This document only describes _breaking_ changes in meshio. If you are interested in bug
fixes, enhancements etc., best follow [the meshio project on
GitHub](https://github.com/nschloe/meshio).

## v5.1.0 (Dec 11, 2021)

- CellBlocks are no longer tuples, but classes. You can no longer iterate over them like
```python
for cell_type, cell_data in cells:
pass
```
Instead, use
```python
for cell_block in cells:
cell_block.type
cell_block.data
```

## v5.0.0 (Aug 06, 2021)

- meshio now only provides one command-line tool, `meshio`, with subcommands like
Expand All @@ -15,43 +30,50 @@ GitHub](https://github.com/nschloe/meshio).
number of nodes per polygon). One can simply retrieve the number of points via
`cellblock.data.shape[1]`.


## v4.0.0 (Feb 18, 2020)

- `mesh.cells` used to be a dictionary of the form

```python
{
"triangle": [[0, 1, 2], [0, 2, 3]],
"quad": [[0, 7, 1, 10], ...]
}
```

From 4.0.0 on, `mesh.cells` is a list of tuples,

```python
[
("triangle", [[0, 1, 2], [0, 2, 3]]),
("quad", [[0, 7, 1, 10], ...])
]
```

This has the advantage that multiple blocks of the same cell type can be accounted
for. Also, cell ordering can be preserved.

You can now use the method `mesh.get_cells_type("triangle")` to get all cells of
`"triangle"` type, or use `mesh.cells_dict` to build the old dictionary structure.

- `mesh.cell_data` used to be a dictionary of the form

```python
{
"triangle": {"a": [0.5, 1.3], "b": [2.17, 41.3]},
"quad": {"a": [1.1, -0.3, ...], "b": [3.14, 1.61, ...]},
}
```

From 4.0.0 on, `mesh.cell_data` is a dictionary of lists,

```python
{
"a": [[0.5, 1.3], [1.1, -0.3, ...]],
"b": [[2.17, 41.3], [3.14, 1.61, ...]],
}
```

Each data list, e.g., `mesh.cell_data["a"]`, can be `zip`ped with `mesh.cells`.

An old-style `cell_data` dictionary can be retrieved via `mesh.cell_data_dict`.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.1173115.svg?style=flat-square)](https://doi.org/10.5281/zenodo.1173115)
[![GitHub stars](https://img.shields.io/github/stars/nschloe/meshio.svg?style=flat-square&logo=github&label=Stars&logoColor=white)](https://github.com/nschloe/meshio)
[![Downloads](https://pepy.tech/badge/meshio/month?style=flat-square)](https://pepy.tech/project/meshio)

<!--[![PyPi downloads](https://img.shields.io/pypi/dm/meshio.svg?style=flat-square)](https://pypistats.org/packages/meshio)-->

[![Discord](https://img.shields.io/static/v1?logo=discord&label=chat&message=on%20discord&color=7289da&style=flat-square)](https://discord.gg/Z6DMsJh4Hr)
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = meshio
version = 5.0.6
version = 5.1.0
author = Nico Schlömer et al.
author_email = [email protected]
description = I/O for many mesh formats
Expand Down
2 changes: 1 addition & 1 deletion src/meshio/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@


def cell_data_from_raw(cells, cell_data_raw):
cs = np.cumsum([len(c[1]) for c in cells])[:-1]
cs = np.cumsum([len(c) for c in cells])[:-1]
return {name: np.split(d, cs) for name, d in cell_data_raw.items()}


Expand Down
22 changes: 11 additions & 11 deletions src/meshio/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import pathlib

import numpy as np
from numpy.typing import ArrayLike

from ._common import num_nodes_per_cell
from ._exceptions import ReadError, WriteError
Expand Down Expand Up @@ -72,20 +73,17 @@ def read(filename, file_format: str | None = None):

def write_points_cells(
filename,
points,
cells,
point_data=None,
cell_data=None,
points: ArrayLike,
cells: dict[str, ArrayLike] | list[tuple[str, ArrayLike] | CellBlock],
point_data: dict[str, ArrayLike] | None = None,
cell_data: dict[str, list[ArrayLike]] | None = None,
field_data=None,
point_sets=None,
cell_sets=None,
file_format=None,
point_sets: dict[str, ArrayLike] | None = None,
cell_sets: dict[str, list[ArrayLike]] | None = None,
file_format: str | None = None,
**kwargs,
):
points = np.asarray(points)
if isinstance(cells, dict):
cells = [CellBlock(name, vals) for name, vals in cells.items()]
cells = [(key, np.asarray(value)) for key, value in cells]
mesh = Mesh(
points,
cells,
Expand Down Expand Up @@ -127,7 +125,9 @@ def write(filename, mesh: Mesh, file_format: str | None = None, **kwargs):
raise WriteError(f"Unknown format '{file_format}'. Pick one of {formats}")

# check cells for sanity
for key, value in mesh.cells:
for cell_block in mesh.cells:
key = cell_block.type
value = cell_block.data
if key in num_nodes_per_cell:
if value.shape[1] != num_nodes_per_cell[key]:
raise WriteError(
Expand Down
49 changes: 33 additions & 16 deletions src/meshio/_mesh.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from __future__ import annotations

import collections
import copy
import warnings

Expand All @@ -10,9 +9,27 @@
from ._common import num_nodes_per_cell


class CellBlock(collections.namedtuple("CellBlock", ["type", "data"])):
class CellBlock:
def __init__(
self,
type: str,
data: list | np.ndarray,
tags: list[str] | None = None,
):
self.type = type
self.data = data
if not type.startswith("polyhedron"):
self.data = np.asarray(self.data)
self.tags = [] if tags is None else tags

def __repr__(self):
return f"<meshio CellBlock, type: {self.type}, num cells: {len(self.data)}>"
items = [
"meshio CellBlock",
f"type: {self.type}",
f"num cells: {len(self.data)}",
f"tags: {self.tags}",
]
return "<" + ", ".join(items) + ">"

def __len__(self):
return len(self.data)
Expand Down Expand Up @@ -112,11 +129,11 @@ def __repr__(self):
]
if len(self.cells) > 0:
lines.append(" Number of cells:")
for cell_type, elems in self.cells:
string = cell_type
if cell_type in special_cells:
string += f"({elems.shape[1]})"
lines.append(f" {string}: {len(elems)}")
for cell_block in self.cells:
string = cell_block.type
if cell_block.type in special_cells:
string += f"({cell_block.data.shape[1]})"
lines.append(f" {string}: {len(cell_block)}")
else:
lines.append(" No cells.")

Expand Down Expand Up @@ -164,10 +181,10 @@ def get_cell_data(self, name: str, cell_type: str):
@property
def cells_dict(self):
cells_dict = {}
for cell_type, data in self.cells:
if cell_type not in cells_dict:
cells_dict[cell_type] = []
cells_dict[cell_type].append(data)
for cell_block in self.cells:
if cell_block.type not in cells_dict:
cells_dict[cell_block.type] = []
cells_dict[cell_block.type].append(cell_block.data)
# concatenate
for key, value in cells_dict.items():
cells_dict[key] = np.concatenate(value)
Expand All @@ -178,10 +195,10 @@ def cell_data_dict(self):
cell_data_dict = {}
for key, value_list in self.cell_data.items():
cell_data_dict[key] = {}
for value, (cell_type, _) in zip(value_list, self.cells):
if cell_type not in cell_data_dict[key]:
cell_data_dict[key][cell_type] = []
cell_data_dict[key][cell_type].append(value)
for value, cell_block in zip(value_list, self.cells):
if cell_block.type not in cell_data_dict[key]:
cell_data_dict[key][cell_block.type] = []
cell_data_dict[key][cell_block.type].append(value)

for cell_type, val in cell_data_dict[key].items():
cell_data_dict[key][cell_type] = np.concatenate(val)
Expand Down
8 changes: 6 additions & 2 deletions src/meshio/abaqus/_abaqus.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,9 @@ def _read_set(f, params_map):
return set_ids, set_names, line


def write(filename, mesh, float_fmt=".16e", translate_cell_names=True):
def write(
filename, mesh: Mesh, float_fmt: str = ".16e", translate_cell_names: bool = True
) -> None:
with open_file(filename, "wt") as f:
f.write("*HEADING\n")
f.write("Abaqus DataFile Version 6.14\n")
Expand All @@ -408,7 +410,9 @@ def write(filename, mesh, float_fmt=".16e", translate_cell_names=True):
for k, x in enumerate(mesh.points):
f.write(fmt.format(k + 1, *x))
eid = 0
for cell_type, node_idcs in mesh.cells:
for cell_block in mesh.cells:
cell_type = cell_block.type
node_idcs = cell_block.data
name = (
meshio_to_abaqus_type[cell_type] if translate_cell_names else cell_type
)
Expand Down
4 changes: 3 additions & 1 deletion src/meshio/ansys/_ansys.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,9 @@ def write(filename, mesh, binary=True):
np.dtype("int32"): "2012",
np.dtype("int64"): "3012",
}
for cell_type, values in mesh.cells:
for cell_block in mesh.cells:
cell_type = cell_block.type
values = cell_block.data
key = binary_dtypes[values.dtype] if binary else "12"
last_index = first_index + len(values) - 1
try:
Expand Down
14 changes: 8 additions & 6 deletions src/meshio/avsucd/_avsucd.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,20 +98,20 @@ def _read_cells(f, num_cells, point_ids):
cell_type = avsucd_to_meshio_type[line[2]]
corner = [point_ids[int(pid)] for pid in line[3:]]

if len(cells) > 0 and cells[-1].type == cell_type:
cells[-1].data.append(corner)
if len(cells) > 0 and cells[-1][0] == cell_type:
cells[-1][1].append(corner)
cell_data["avsucd:material"][-1].append(cell_mat)
else:
cells.append(CellBlock(cell_type, [corner]))
cells.append((cell_type, [corner]))
cell_data["avsucd:material"].append([cell_mat])

cell_ids[cell_id] = count
count += 1

# Convert to numpy arrays
for k, c in enumerate(cells):
for k, (cell_type, cdata) in enumerate(cells):
cells[k] = CellBlock(
c.type, np.array(c.data)[:, avsucd_to_meshio_order[c.type]]
cell_type, np.array(cdata)[:, avsucd_to_meshio_order[cell_type]]
)
cell_data["avsucd:material"][k] = np.array(cell_data["avsucd:material"][k])
return cell_ids, cells, cell_data
Expand Down Expand Up @@ -219,7 +219,9 @@ def _write_nodes(f, points):

def _write_cells(f, cells, material):
i = 0
for cell_type, v in cells:
for cell_block in cells:
cell_type = cell_block.type
v = cell_block.data
for cell in v[:, meshio_to_avsucd_order[cell_type]]:
cell_str = " ".join(str(c) for c in cell + 1)
f.write(
Expand Down
12 changes: 6 additions & 6 deletions src/meshio/cgns/_cgns.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,20 +78,20 @@ def write(filename, mesh, compression="gzip", compression_opts=4):
# TODO write cells other than tetra
elems = zone1.create_group("GridElements")
rnge = elems.create_group("ElementRange")
for cell_type, data in mesh.cells:
if cell_type == "tetra":
for cell_block in mesh.cells:
if cell_block.type == "tetra":
rnge.create_dataset(
" data",
data=[1, data.shape[0]],
data=[1, cell_block.data.shape[0]],
compression=compression,
compression_opts=compression_opts,
)
conn = elems.create_group("ElementConnectivity")
for cell_type, data in mesh.cells:
if cell_type == "tetra":
for cell_block in mesh.cells:
if cell_block.type == "tetra":
conn.create_dataset(
" data",
data=data.reshape(-1) + 1,
data=cell_block.data.reshape(-1) + 1,
compression=compression,
compression_opts=compression_opts,
)
Expand Down
6 changes: 3 additions & 3 deletions src/meshio/dolfin/_dolfin.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,9 @@ def _write_mesh(filename, points, cell_type, cells):

f.write(f' <cells size="{num_cells}">\n')
idx = 0
for ct, cls in stripped_cells:
type_string = meshio_to_dolfin_type[ct]
for cell in cls:
for cell_block in stripped_cells:
type_string = meshio_to_dolfin_type[cell_block.type]
for cell in cell_block.data:
s = " ".join(f'v{k}="{c}"' for k, c in enumerate(cell))
f.write(f' <{type_string} index="{idx}" {s} />\n')
idx += 1
Expand Down
12 changes: 6 additions & 6 deletions src/meshio/exodus/_exodus.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,16 +307,16 @@ def write(filename, mesh):
data = rootgrp.createVariable("eb_prop1", "i4", "num_el_blk")
for k in range(len(mesh.cells)):
data[k] = k
for k, (key, values) in enumerate(mesh.cells):
for k, cell_block in enumerate(mesh.cells):
dim1 = f"num_el_in_blk{k + 1}"
dim2 = f"num_nod_per_el{k + 1}"
rootgrp.createDimension(dim1, values.shape[0])
rootgrp.createDimension(dim2, values.shape[1])
dtype = numpy_to_exodus_dtype[values.dtype.name]
rootgrp.createDimension(dim1, cell_block.data.shape[0])
rootgrp.createDimension(dim2, cell_block.data.shape[1])
dtype = numpy_to_exodus_dtype[cell_block.data.dtype.name]
data = rootgrp.createVariable(f"connect{k + 1}", dtype, (dim1, dim2))
data.elem_type = meshio_to_exodus_type[key]
data.elem_type = meshio_to_exodus_type[cell_block.type]
# Exodus is 1-based
data[:] = values + 1
data[:] = cell_block.data + 1

# point data
# The variable `name_nod_var` holds the names and indices of the node variables, the
Expand Down
Loading

0 comments on commit 184fb02

Please sign in to comment.