added MFEM 3D export feature
Added feature to export MFEM mesh containing tetrahedra.
Small working example:
import gustaf as gus
import numpy as np
mesh = gus.Volumes(
vertices=[
[0.0, 0.0, 0.0],
[1.0, 0.0, 0.0],
[0.0, 1.0, 0.0],
[1.0, 1.0, 0.0],
[0.0, 0.0, 1.0],
[1.0, 0.0, 1.0],
[0.0, 1.0, 1.0],
[1.0, 1.0, 1.0],
],
volumes=[
[0, 2, 7, 3],
[0, 2, 6, 7],
[0, 6, 4, 7],
[5, 0, 4, 7],
[5, 0, 7, 1],
[7, 0, 3, 1],
],
)
tets = mesh.volumes
verts = mesh.vertices
faces = mesh.to_faces(False)
boundary_faces = faces.single_faces()
BC = {1: [], 2: [], 3: []}
for i in boundary_faces:
# mark boundaries at x = 0 with 1
if np.max(verts[faces.const_faces[i], 0]) < 0.1:
BC[1].append(i)
# mark boundaries at x = 1 with 2
elif np.min(verts[faces.const_faces[i], 0]) > 0.9:
BC[2].append(i)
# mark rest of the boundaries with 3
else:
BC[3].append(i)
gus.io.mfem.export("example_mfem.mesh", mesh, BC)
gus.io.mfem.export("example_mfem_no_bc.mesh", mesh, None)
Summary by CodeRabbit
-
New Features
- Expanded support for exporting 3D tetrahedral meshes alongside 2D triangle and quadrilateral meshes, including configurable boundary conditions.
-
Tests
- Implemented new test cases to validate the export functionality of various mesh data structures.
- Enhanced testing capabilities with new fixtures for comparing stripped lines and generating temporary file paths.
-
Data
- Introduced new mesh files defining structures for 3D tetrahedral and hexahedral elements, as well as 2D quadrilaterals and triangles.
[!IMPORTANT]
Review skipped
Auto reviews are disabled on base/target branches other than the default branch.
Please check the settings in the CodeRabbit UI or the
.coderabbit.yamlfile in this repository. To trigger a single review, invoke the@coderabbitai reviewcommand.You can disable this status message by setting the
reviews.review_statustofalsein the CodeRabbit configuration file.
Walkthrough
Refactors MFEM export in gustaf/io/mfem.py into dimension-specific routines with a shared array formatter; adds 2D/3D test fixtures, multiple MFEM ground-truth mesh files, and a parameterized test validating exported output against those files.
Changes
| Cohort / File(s) | Summary |
|---|---|
MFEM export code gustaf/io/mfem.py |
Split export into dimension dispatch and internal _export_2d / _export_3d; added format_array(array: np.ndarray) -> str; construct elements and boundary arrays per-dimension and mesh type (tri/quad/tet/hexa); raise on unsupported dims. |
Test fixtures & utilities tests/conftest.py |
Added 2D vertex/connectivity fixtures (vertices_2d, tri_connec_2d, quad_connec_2d), derived faces_* fixtures, volumes_hexa_222 3D fixture, helpers are_stripped_lines_same and to_tmpf; removed provide_data_to_unittest. |
MFEM ground-truth data (2D) tests/data/mfem_quadrilaterals_2d.mesh, tests/data/mfem_triangles_2d.mesh |
New MFEM files: quadrilateral and triangular 2D ground-truth meshes (elements, boundary, vertices). |
MFEM ground-truth data (3D) tests/data/mfem_hexahedra_3d.mesh, tests/data/mfem_hexahedra_3d_222.mesh, tests/data/mfem_tetrahedra_3d.mesh |
New MFEM files: single- and multi-element 3D hexahedral and tetrahedral ground-truth meshes (elements, boundary faces, vertices). |
Tests tests/test_export.py |
New parameterized test test_mfem_export that builds mesh.BC from edges/faces, calls gustaf.io.mfem.export, and compares the exported file to ground-truth using are_stripped_lines_same. |
Formatting / tooling / minor edits .pre-commit-config.yaml, pyproject.toml, gustaf/create/faces.py, gustaf/utils/tictoc.py, tests/test_vertices_and_element_updates.py |
Adjusted pre-commit hooks (removed Black, added/changed Ruff hooks), updated dev dependencies and Ruff config, minor string/format tweaks, and replaced volumes_hexa333 with volumes_hexa_222 in test parameters. |
Sequence Diagram(s)
sequenceDiagram
autonumber
participant Test as Test (pytest)
participant Mesh as Mesh (gus.*)
participant Export as gustaf.io.mfem.export
participant File as Output file
Test->>Mesh: obtain fixture (2D or 3D)
Test->>Mesh: build BC via edges/faces -> assign mesh.BC
Test->>Export: call export(fname, mesh)
Export->>Export: inspect vertex coordinates -> determine dim
alt dim == 2
Export->>Export: _export_2d(mesh) -> elementsStr, boundaryStr, verticesStr
else dim == 3
Export->>Export: _export_3d(mesh) -> elementsStr, boundaryStr, verticesStr
else
Export-->>Test: raise NotImplementedError
end
Export->>File: write MFEM header + dimension + elementsStr + boundaryStr + verticesStr
File-->>Test: file saved
Test->>Test: compare file to ground-truth (are_stripped_lines_same)
Estimated code review effort
🎯 3 (Moderate) | ⏱️ ~20–30 minutes
- Focus review on:
-
gustaf/io/mfem.py: index ordering, element attribute/geometry mapping, and BC geometry type selection. -
tests/test_export.py: BC classification thresholds and that fixture outputs match ground-truth expectations. - New MFEM data files: confirm counts and formatting match exporter output.
-
Poem
I stitched triangles and quads with care,
Tetrahedra and hexahedra — a solid affair.
Boundaries labeled, vertices in place,
Exported to MFEM with tidy grace.
A rabbit hops, tests pass — code in embrace. 🐇
Pre-merge checks and finishing touches
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | ⚠️ Warning | Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. | You can run @coderabbitai generate docstrings to improve docstring coverage. |
✅ Passed checks (2 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | The title 'added MFEM 3D export feature' accurately captures the main objective of the pull request, which adds support for exporting MFEM mesh files in 3D format. |
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.
This looks very nice. The automatic code adaptations seem to be straightforward and especially the documentation remarks are good. In addition to that, could you also add the example you have given up top to the test suite and the examples?
Thanks for your work.
Now that you have added the BC keyword to the function call, we need to think about how we need to include it for the other cases as well. Currently it is only implemented for the 3D case, which might produce unwanted/confusing behavior for users.
@j042 what is the status of the BC object variable? Could we not use that instead? I have no idea what the status of general BC in gustaf is, but I know that we talked about it previously...
Now that you have added the BC keyword to the function call, we need to think about how we need to include it for the other cases as well. Currently it is only implemented for the 3D case, which might produce unwanted/confusing behavior for users.
@j042 what is the status of the BC object variable? Could we not use that instead? I have no idea what the status of general BC in gustaf is, but I know that we talked about it previously...
We talked about having general helper class to handle subset of elements/subelements - no progress on that. However, Faces and Volumes have member called BC and we should use that interface instead of an additional argument
@mkofler96 after applying the last commit (removing print()) test fails. Can you please check / update?
@mkofler96 after applying the last commit (removing print()) test fails. Can you please check / update?
I don't know exactly what caused the issue, but it seems to be related to which mesh is used for testing. At some point we used to test on the hexa333 mesh, but I think we switched to the single element test. The other 3 tests are passing, so I don't think it is a bigger issue.
We could also think of adding the hexa333 as a test for this. The test fixtures are still a bit all over the place. @clemens-fricke should we maybe check the fixtures and see if we should refactor some?
I have not really changed much but the hexa 222 test case seems to work now for me.
I have update the pre-commit a little bit since it used the legacy ruff mode.
Removed black due to it being outdated and making problems and being replicated by ruff in most ways anyway.