refactor(med): rewrite field writing to support multi-timestep and group by base name#16
Open
fznoussi wants to merge 6 commits into
Open
refactor(med): rewrite field writing to support multi-timestep and group by base name#16fznoussi wants to merge 6 commits into
fznoussi wants to merge 6 commits into
Conversation
…oup by base name
The previous write() implementation iterated over mesh.point_data and
mesh.cell_data entries one by one and called _write_data() for each.
This had two major problems:
1. Multi-timestep fields (stored as 'Temperature[0] - 0.0',
'Temperature[1] - 1.0', etc. after read) were written as separate
independent MED fields instead of being grouped under a single
field group with multiple timestep subgroups, which is the correct
MED structure.
2. The tracker.notify() call for nodal fields was using hardcoded
'MED_POINT1' regardless of the actual field support, causing
incorrect bitmask metadata in the output file.
Changes:
- Added _parse_med_field_name(name): parses 'FieldName[i] - t' into
(base_name, index, time) using a regex so multi-timestep fields can
be regrouped by their base name
- Added _write_field_step(): extracted the low-level HDF5 writing of a
single timestep (NOE/MAI group, profile subgroup, CO dataset) into a
dedicated helper to avoid code duplication between nodal and cell paths
- write(): replaced the flat loop over point_data/cell_data with two
defaultdict(list) accumulators (nodal_groups, cell_groups) that group
entries by base field name before writing
- write(): each base field name now creates exactly one HDF5 field group
with one timestep subgroup per entry, matching the MED spec
- write(): nodal tracker.notify() now uses 'MED_NODE'/'MED_NO_GEOTYPE'
and cell tracker.notify() uses med_type_to_entity[med_type] and
med_to_geo_type[med_type] for correct bitmask generation
- write(): added early return with f.close() when there are no fields to
write, avoiding creation of an empty CHA group
- _write_data(): kept as a compatibility shim for _medmulti.py with two
new optional parameters (tracker, step_name) so callers can override
the hardcoded step name and flush the tracker themselves
Why: without this fix, a MED file with multiple timesteps read and
re-written by meshio would produce a structurally invalid file where
each timestep appears as a separate field, which Code_Aster and Salome
refuse to load or silently misinterpret.
…uires both the geometric type (MED_TRIA3, MED_TETRA4, etc.) and the entity type (MED_CELL, MED_NODE_ELEMENT, etc.). Previously the entity type was hardcoded as a string in the write() call sites, which was incorrect for vertex elements (PO1 should be MED_NODE_ELEMENT, not MED_CELL). The new med_type_to_entity dict provides the correct entity type for every supported MED element type and is used in the cell data write loop.
…oup by base name
Previously, write() iterated over mesh.point_data and mesh.cell_data
entries one by one and called _write_data() for each. This had two
major problems:
1. Multi-timestep fields stored as 'Temperature[0] - 0.0',
'Temperature[1] - 1.0', etc. were written as separate independent
MED fields instead of being grouped under a single field group with
multiple timestep subgroups, which is the correct MED structure.
2. CHA group was always created even when there were no fields,
producing an unnecessary empty group.
Changes:
- Added _parse_med_field_name(): parses 'FieldName[i] - t' into
(base_name, index, time) using a regex so multi-timestep fields
can be regrouped by their base name
- write(): replaced flat loop with defaultdict(list) accumulators
(nodal_groups, cell_groups) that group entries by base field name
- write(): each base field name creates exactly one HDF5 field group
with one timestep subgroup per entry
- write(): added early return with f.close() when there are no fields
to write, avoiding creation of an empty CHA group
- write(): nodal tracker.notify() now uses MED_NODE/MED_NO_GEOTYPE
and cell tracker.notify() uses med_to_geo_type for correct bitmask
Add 5 tests to verify that the multi-timestep field write refactor
works correctly.
Tests added:
- test_parse_med_field_name_single:
Checks that a field name without timestep pattern returns
(name, None, None). Without PR16 this function did not exist.
- test_parse_med_field_name_multi:
Checks that 'Temperature[2] - 1.5' is correctly parsed into
('Temperature', 2, 1.5).
- test_multi_timestep_grouped_under_single_hdf5_field:
Checks that multiple timesteps of the same field are written under
a single HDF5 group in CHA. Without PR16 each 'Temperature[i] - t'
created a separate group.
- test_no_cha_group_when_no_fields:
Checks that CHA group is not created when there are no fields.
Without PR16 CHA was always created even when empty.
- test_multi_timestep_roundtrip_box:
Checks that a MED file with multiple timesteps survives a full
read→write cycle with correct values using box.med.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The previous write() implementation iterated over mesh.point_data and mesh.cell_data entries one by one and called _write_data() for each. This had two major problems:
Changes:
Why: without this fix, a MED file with multiple timesteps read and re-written by meshio would produce a structurally invalid file where each timestep appears as a separate field, which Code_Aster and Salome refuse to load or silently misinterpret.