New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improvements to skfem.io.meshio #680
Conversation
Good morning. Serialization #158 is back on the agenda, excellent: I believe this is an important long-term goal. Would this fix There's quite a history of efforts on that here and even more in meshio. I'll have to refresh myself on that to see what the status is. Prior to that, my impressions are that:
I do however routinely save meshes with subdomains and boundaries. I can outline my current practice, in case that's helpful, or share code—basically I write MSH 2.2 using meshio using While there may not be documentation for |
What I mean by this is that if just before scikit-fem/docs/examples/ex28.py Line 145 in 80e39e2
I put mesh = geom.generate_mesh(dim=2)
mesh.write(Path(__file__).with_suffix(".msh"), binary=False) and then in the script make_mesh(length, halfheight, thickness) I get
I'm pretty sure that this is a meshio issue. However, if I insert file_format="gmsh22", into the call to |
So I'm planning to write |
I might have now got it correctly. Pushing some more commits soon. |
O. K. The best way to see what |
tests/test_mesh.py
Outdated
from tempfile import NamedTemporaryFile | ||
with NamedTemporaryFile() as f: | ||
m.save(f.name + ".inp", write_boundaries=True) | ||
m2 = Mesh.load(f.name + ".inp") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is funny that Abaqus inp format works properly for write/read cycle but almost nothing else does without sorcery.
This allows now doing stuff like this: In [1]: from skfem import *
In [2]: m = MeshTri().with_boundaries({'left': lambda x: x[0] == 0})
In [3]: m.save('testing.msh', write_boundaries=True, sets_to_int_data=True, file_format='gmsh22')
WARNING:root:msh2 requires 3D points, but 2D points given. Appending 0 third component.
WARNING:root:Binary Gmsh needs 32-bit integers (got int64). Converting.
WARNING:root:Binary Gmsh needs 32-bit integers (got int64). Converting.
WARNING:root:Appending zeros to replace the missing physical tag data.
WARNING:root:Appending zeros to replace the missing geometrical tag data.
In [4]: M = MeshTri.load('testing.msh', int_data_to_sets=True)
In [5]: M.boundaries
Out[5]:
{'set-1.0': array([0, 3, 4]),
'set0.0': array([1]),
'gmsh:physical': array([0, 1, 3, 4]),
'gmsh:geometrical': array([0, 1, 3, 4])}
In [6]: m.boundaries
Out[6]: {'left': array([1])} As you can see, the tag names are lost due to the |
Fantastic!
I wonder whether the names can be stashed in That's weird and unfortunate about Abaqus .inp. Is that a viable format? Can one do anything with it without access to the Abaqus program? It might just be that better work has been done on that submodule of meshio. MSH 2.2 is not ideal, it's very slow. In my first industrial application of scikit-fem, reading MSH 2.2 was actually the bottleneck. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, no, I see that we've gone from having one named boundary
{'left': array([1])}
to four, all misnamed, and three spurious
{'set-1.0': array([0, 3, 4]), 'set0.0': array([1]), 'gmsh:physical': array([0, 1, 3, 4]), 'gmsh:geometrical': array([0, 1, 3, 4])}
Yeah, no, that's not so good. Hmm…Some further thoughts in #261.
MSH 4.1 will likely require some workaround, e.g., writing |
If I remove |
Personally i wouldn't see writing MSH 4.1 as a requirement. Is that needed for interoperation with Elmer? It might (for my purposes #261) be worth working out a format that meshio writes and reads reasonably quickly. It does read MSH 4.1 much faster than MSH 2.2; this is an intrinsic benefit of the redesign from the Gmsh tesm, avoiding mixed topologies. Unfortunately, the meshio speed tests don't test mixed topologies, and so while XDMF looks fast, that's only true if only one kind of cell is written. The current meshio XDMF writer, if given domain and boundary cells, will revert to a mixed topology which i fear will be slow to reread—each cell will have to be processed individually to see whst kind it is. This is not intrinsic to XDMF but a shortcoming of meshio; a fix for that is proposed in nschloe/meshio#622. This was part of the motivation for writing boundary facets as such in #681 rather than as lower-dimensional cells (besides the main motivation of that being a more direct representation). But neither of those are overriding considerations ; good interoperation is. I'm thinking that VTK will probably be a reasonable default for using this PR to fix #261 ; I.e. write and reread by skfem. If Elmer doesn't use meshio to read MSH 2.2 but rather has a C++ reader, it might not be slow, so that could be a workable procedure there. |
Now user can pass the optional parameter |
I noticed that in |
Note that I'm still planning to do #474 at some point, which will hopefully include stuff like how to use |
Yes, I noticed that too in ex28 and was puzzled. Thanks, it's better now. |
I have just fetched this branch and taken it for a spin. It's awesome. I wish we had done this years ago! So far everything just works, very easily, no surprises; very nice to use. One slight disappointment is that the new The pinked visualization of the boundaries is a bit zany, but it kind of makes sense, I think; I wonder what others will think of it. Is this ready for a review? Anyway, I'm going to begin using it for everything immediately. |
Yes, I think it's ready. |
I updated the first message in the PR with some examples. |
tests/test_mesh.py
Outdated
class Loading(TestCase): | ||
"""Check that Mesh.load works properly.""" | ||
|
||
def runTest(self): | ||
# submeshes | ||
path = Path(__file__).parents[1] / 'docs' / 'examples' / 'meshes' | ||
m = MeshTet.load(str(path / 'box.msh')) | ||
m = MeshTet.load(str(MESH_PATH / 'box.msh')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need to cast to str
; see, e.g.,
scikit-fem/docs/examples/ex21.py
Line 70 in 96fa97a
m = MeshTet.load(Path(__file__).parent / 'meshes' / 'beams.msh') |
scikit-fem/docs/examples/ex28.py
Line 147 in 96fa97a
mesh = from_file(Path(__file__).parent / 'meshes' / 'ex28.json') |
Fixes #158
Fixes #261
Fixes #271
Fixes #683
Example 1: Export boundaries to external formats.
Example 2: Load the exported boundaries
Example 3: Load raw data from meshio