cardiac-geometriesx 0.1.2__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of cardiac-geometriesx might be problematic. Click here for more details.

Files changed (28) hide show
  1. cardiac_geometriesx-0.2.0/LICENSE +21 -0
  2. cardiac_geometriesx-0.2.0/PKG-INFO +94 -0
  3. cardiac_geometriesx-0.2.0/README.md +48 -0
  4. {cardiac_geometriesx-0.1.2 → cardiac_geometriesx-0.2.0}/pyproject.toml +19 -2
  5. {cardiac_geometriesx-0.1.2 → cardiac_geometriesx-0.2.0}/src/cardiac_geometries/cli.py +15 -1
  6. {cardiac_geometriesx-0.1.2 → cardiac_geometriesx-0.2.0}/src/cardiac_geometries/fibers/lv_ellipsoid.py +10 -12
  7. {cardiac_geometriesx-0.1.2 → cardiac_geometriesx-0.2.0}/src/cardiac_geometries/fibers/slab.py +10 -12
  8. {cardiac_geometriesx-0.1.2 → cardiac_geometriesx-0.2.0}/src/cardiac_geometries/fibers/utils.py +13 -8
  9. {cardiac_geometriesx-0.1.2 → cardiac_geometriesx-0.2.0}/src/cardiac_geometries/geometry.py +82 -32
  10. cardiac_geometriesx-0.2.0/src/cardiac_geometries/gui.py +272 -0
  11. {cardiac_geometriesx-0.1.2 → cardiac_geometriesx-0.2.0}/src/cardiac_geometries/mesh.py +45 -22
  12. cardiac_geometriesx-0.2.0/src/cardiac_geometries/utils.py +440 -0
  13. cardiac_geometriesx-0.2.0/src/cardiac_geometriesx.egg-info/PKG-INFO +94 -0
  14. {cardiac_geometriesx-0.1.2 → cardiac_geometriesx-0.2.0}/src/cardiac_geometriesx.egg-info/SOURCES.txt +4 -1
  15. {cardiac_geometriesx-0.1.2 → cardiac_geometriesx-0.2.0}/src/cardiac_geometriesx.egg-info/requires.txt +15 -0
  16. {cardiac_geometriesx-0.1.2 → cardiac_geometriesx-0.2.0}/tests/test_cli.py +8 -3
  17. cardiac_geometriesx-0.2.0/tests/test_save_load.py +146 -0
  18. cardiac_geometriesx-0.1.2/PKG-INFO +0 -51
  19. cardiac_geometriesx-0.1.2/README.md +0 -20
  20. cardiac_geometriesx-0.1.2/src/cardiac_geometries/utils.py +0 -122
  21. cardiac_geometriesx-0.1.2/src/cardiac_geometriesx.egg-info/PKG-INFO +0 -51
  22. {cardiac_geometriesx-0.1.2 → cardiac_geometriesx-0.2.0}/setup.cfg +0 -0
  23. {cardiac_geometriesx-0.1.2 → cardiac_geometriesx-0.2.0}/src/cardiac_geometries/__init__.py +0 -0
  24. {cardiac_geometriesx-0.1.2 → cardiac_geometriesx-0.2.0}/src/cardiac_geometries/fibers/__init__.py +0 -0
  25. {cardiac_geometriesx-0.1.2 → cardiac_geometriesx-0.2.0}/src/cardiac_geometriesx.egg-info/dependency_links.txt +0 -0
  26. {cardiac_geometriesx-0.1.2 → cardiac_geometriesx-0.2.0}/src/cardiac_geometriesx.egg-info/entry_points.txt +0 -0
  27. {cardiac_geometriesx-0.1.2 → cardiac_geometriesx-0.2.0}/src/cardiac_geometriesx.egg-info/not-zip-safe +0 -0
  28. {cardiac_geometriesx-0.1.2 → cardiac_geometriesx-0.2.0}/src/cardiac_geometriesx.egg-info/top_level.txt +0 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Computational Physiology at Simula Research Laboratory
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,94 @@
1
+ Metadata-Version: 2.1
2
+ Name: cardiac-geometriesx
3
+ Version: 0.2.0
4
+ Summary: A python library for cardiac geometries
5
+ Author-email: Henrik Finsberg <henriknf@simula.no>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/finsberg/cardiac-geometriesx
8
+ Keywords: cardiac,geometry
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3 :: Only
12
+ Requires-Python: >=3.8
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: fenics-dolfinx>=0.8.0
16
+ Requires-Dist: structlog
17
+ Requires-Dist: cardiac-geometries-core
18
+ Requires-Dist: rich-click
19
+ Requires-Dist: adios4dolfinx
20
+ Provides-Extra: dev
21
+ Requires-Dist: bump-my-version; extra == "dev"
22
+ Requires-Dist: ipython; extra == "dev"
23
+ Requires-Dist: pdbpp; extra == "dev"
24
+ Requires-Dist: pre-commit; extra == "dev"
25
+ Requires-Dist: twine; extra == "dev"
26
+ Requires-Dist: wheel; extra == "dev"
27
+ Provides-Extra: docs
28
+ Requires-Dist: jupyter-book; extra == "docs"
29
+ Requires-Dist: jupytext; extra == "docs"
30
+ Requires-Dist: jupyter; extra == "docs"
31
+ Requires-Dist: pyvista[all]>=0.43.0; extra == "docs"
32
+ Requires-Dist: trame-vuetify; extra == "docs"
33
+ Requires-Dist: ipywidgets; extra == "docs"
34
+ Requires-Dist: fenicsx-ldrb; extra == "docs"
35
+ Provides-Extra: test
36
+ Requires-Dist: pre-commit; extra == "test"
37
+ Requires-Dist: pytest; extra == "test"
38
+ Requires-Dist: pytest-cov; extra == "test"
39
+ Provides-Extra: gui
40
+ Requires-Dist: streamlit; extra == "gui"
41
+ Requires-Dist: stpyvista; extra == "gui"
42
+ Requires-Dist: pyvista[all]>=0.43.0; extra == "gui"
43
+ Requires-Dist: trame-vuetify; extra == "gui"
44
+ Requires-Dist: ipywidgets; extra == "gui"
45
+ Requires-Dist: fenicsx-ldrb; extra == "gui"
46
+
47
+ ![_](docs/_static/logo.png)
48
+
49
+ [![Create and publish a Docker image](https://github.com/ComputationalPhysiology/cardiac-geometriesx/actions/workflows/docker-image.yml/badge.svg)](https://github.com/ComputationalPhysiology/cardiac-geometriesx/actions/workflows/docker-image.yml)
50
+ [![Test package](https://github.com/ComputationalPhysiology/cardiac-geometriesx/actions/workflows/test.yml/badge.svg)](https://github.com/ComputationalPhysiology/cardiac-geometriesx/actions/workflows/test.yml)
51
+ [![Test package MPI](https://github.com/ComputationalPhysiology/cardiac-geometriesx/actions/workflows/test-mpi.yml/badge.svg)](https://github.com/ComputationalPhysiology/cardiac-geometriesx/actions/workflows/test-mpi.yml)
52
+ [![Pre-commit](https://github.com/ComputationalPhysiology/cardiac-geometriesx/actions/workflows/pre-commit.yml/badge.svg)](https://github.com/ComputationalPhysiology/cardiac-geometriesx/actions/workflows/pre-commit.yml)
53
+ [![PyPI version](https://badge.fury.io/py/cardiac-geometriesx.svg)](https://badge.fury.io/py/cardiac-geometriesx)
54
+
55
+ # Cardiac geometries
56
+
57
+ Cardiac geometries is a software package built on top of [`cariac-geometries-core`](https://github.com/ComputationalPhysiology/cardiac-geometries-core) that adds support for creating idealized cardiac geometries for dolfinx.
58
+
59
+ There are two ways you can use `cardiac-geomtries`, either using the command line interface, e.g
60
+ ```
61
+ geox lv-ellipsoid --create-fibers lv-mesh --fiber-space P_2
62
+ ```
63
+
64
+ or using the python API e.g
65
+ ```python
66
+ geo = cardiac_geometries.mesh.lv_ellipsoid(outdir="lv-mesh", create_fibers=True, fiber_space="P_2")
67
+ ```
68
+
69
+ ## Install
70
+
71
+ To install the package you can use `pip`
72
+ ```
73
+ python3 -m pip install cardiac-geometriesx
74
+ ```
75
+ however, this assumes that you already have `dolfinx` pre-installed. You can also use the provided docker image e.g
76
+ ```
77
+ docker pull ghcr.io/computationalphysiology/cardiac-geometriesx:latest
78
+ ```
79
+ To start a new container interactive you can do
80
+ ```
81
+ docker run --name geox -v $PWD:/home/shared -w /home/shared -it ghcr.io/computationalphysiology/cardiac-geometriesx:latest
82
+ ```
83
+ or if you just want to create a mesh and exit you can run the command line interface directly e.g
84
+ ```
85
+ docker run --rm -v $PWD:/home/shared -w /home/shared -it ghcr.io/computationalphysiology/cardiac-geometriesx:latest geox lv-ellipsoid --create-fibers lv-mesh --fiber-space P_2
86
+ ```
87
+
88
+ ## Authors
89
+ Henrik Finsberg (henriknf@simula.no)
90
+
91
+ ## License
92
+ MIT
93
+
94
+ ## Contributing
@@ -0,0 +1,48 @@
1
+ ![_](docs/_static/logo.png)
2
+
3
+ [![Create and publish a Docker image](https://github.com/ComputationalPhysiology/cardiac-geometriesx/actions/workflows/docker-image.yml/badge.svg)](https://github.com/ComputationalPhysiology/cardiac-geometriesx/actions/workflows/docker-image.yml)
4
+ [![Test package](https://github.com/ComputationalPhysiology/cardiac-geometriesx/actions/workflows/test.yml/badge.svg)](https://github.com/ComputationalPhysiology/cardiac-geometriesx/actions/workflows/test.yml)
5
+ [![Test package MPI](https://github.com/ComputationalPhysiology/cardiac-geometriesx/actions/workflows/test-mpi.yml/badge.svg)](https://github.com/ComputationalPhysiology/cardiac-geometriesx/actions/workflows/test-mpi.yml)
6
+ [![Pre-commit](https://github.com/ComputationalPhysiology/cardiac-geometriesx/actions/workflows/pre-commit.yml/badge.svg)](https://github.com/ComputationalPhysiology/cardiac-geometriesx/actions/workflows/pre-commit.yml)
7
+ [![PyPI version](https://badge.fury.io/py/cardiac-geometriesx.svg)](https://badge.fury.io/py/cardiac-geometriesx)
8
+
9
+ # Cardiac geometries
10
+
11
+ Cardiac geometries is a software package built on top of [`cariac-geometries-core`](https://github.com/ComputationalPhysiology/cardiac-geometries-core) that adds support for creating idealized cardiac geometries for dolfinx.
12
+
13
+ There are two ways you can use `cardiac-geomtries`, either using the command line interface, e.g
14
+ ```
15
+ geox lv-ellipsoid --create-fibers lv-mesh --fiber-space P_2
16
+ ```
17
+
18
+ or using the python API e.g
19
+ ```python
20
+ geo = cardiac_geometries.mesh.lv_ellipsoid(outdir="lv-mesh", create_fibers=True, fiber_space="P_2")
21
+ ```
22
+
23
+ ## Install
24
+
25
+ To install the package you can use `pip`
26
+ ```
27
+ python3 -m pip install cardiac-geometriesx
28
+ ```
29
+ however, this assumes that you already have `dolfinx` pre-installed. You can also use the provided docker image e.g
30
+ ```
31
+ docker pull ghcr.io/computationalphysiology/cardiac-geometriesx:latest
32
+ ```
33
+ To start a new container interactive you can do
34
+ ```
35
+ docker run --name geox -v $PWD:/home/shared -w /home/shared -it ghcr.io/computationalphysiology/cardiac-geometriesx:latest
36
+ ```
37
+ or if you just want to create a mesh and exit you can run the command line interface directly e.g
38
+ ```
39
+ docker run --rm -v $PWD:/home/shared -w /home/shared -it ghcr.io/computationalphysiology/cardiac-geometriesx:latest geox lv-ellipsoid --create-fibers lv-mesh --fiber-space P_2
40
+ ```
41
+
42
+ ## Authors
43
+ Henrik Finsberg (henriknf@simula.no)
44
+
45
+ ## License
46
+ MIT
47
+
48
+ ## Contributing
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "cardiac-geometriesx"
7
- version = "0.1.2"
7
+ version = "0.2.0"
8
8
  description = "A python library for cardiac geometries"
9
9
  authors = [{name = "Henrik Finsberg", email = "henriknf@simula.no"}]
10
10
  license = {text = "MIT"}
@@ -38,12 +38,28 @@ dev = [
38
38
  "wheel",
39
39
  ]
40
40
  docs = [
41
+ "jupyter-book",
42
+ "jupytext",
43
+ "jupyter",
44
+ "pyvista[all]>=0.43.0",
45
+ "trame-vuetify",
46
+ "ipywidgets",
47
+ "fenicsx-ldrb",
41
48
  ]
42
49
  test = [
43
50
  "pre-commit",
44
51
  "pytest",
45
52
  "pytest-cov",
46
53
  ]
54
+ gui = [
55
+ "streamlit",
56
+ "stpyvista",
57
+ "pyvista[all]>=0.43.0",
58
+ "trame-vuetify",
59
+ "ipywidgets",
60
+ "fenicsx-ldrb",
61
+
62
+ ]
47
63
 
48
64
  [project.scripts]
49
65
  geox = "cardiac_geometries.cli:app"
@@ -80,6 +96,7 @@ exclude = [
80
96
 
81
97
  # Exclude a variety of commonly ignored directories.
82
98
  exclude = [
99
+ "demos/*.py",
83
100
  ".bzr",
84
101
  ".direnv",
85
102
  ".eggs",
@@ -156,7 +173,7 @@ tag = true
156
173
  sign_tags = false
157
174
  tag_name = "v{new_version}"
158
175
  tag_message = "Bump version: {current_version} → {new_version}"
159
- current_version = "0.1.2"
176
+ current_version = "0.2.0"
160
177
 
161
178
 
162
179
  [[tool.bumpversion.files]]
@@ -8,8 +8,10 @@ from . import mesh
8
8
 
9
9
  meta = metadata("cardiac-geometriesx")
10
10
  __version__ = meta["Version"]
11
- __author__ = meta["Author"]
11
+ __author__ = meta["Author-email"]
12
12
  __license__ = meta["License"]
13
+ __email__ = meta["Author-email"]
14
+ __program_name__ = meta["Name"]
13
15
 
14
16
 
15
17
  @click.group()
@@ -867,8 +869,20 @@ def slab_in_bath(
867
869
  geo.save(outdir / "slab_in_bath.bp")
868
870
 
869
871
 
872
+ @click.command("gui")
873
+ def gui():
874
+ # Make sure we can import the required packages
875
+ from . import gui # noqa: F401
876
+
877
+ gui_path = Path(__file__).parent.joinpath("gui.py")
878
+ import subprocess as sp
879
+
880
+ sp.run(["streamlit", "run", gui_path.as_posix()])
881
+
882
+
870
883
  app.add_command(lv_ellipsoid)
871
884
  app.add_command(biv_ellipsoid)
872
885
  app.add_command(biv_ellipsoid_torso)
873
886
  app.add_command(slab)
874
887
  app.add_command(slab_in_bath)
888
+ app.add_command(gui)
@@ -1,9 +1,9 @@
1
1
  from pathlib import Path
2
2
 
3
- import basix
4
3
  import dolfinx
5
4
  import numpy as np
6
5
 
6
+ from ..utils import space_from_string
7
7
  from . import utils
8
8
 
9
9
 
@@ -82,14 +82,9 @@ def compute_system(
82
82
  s0 = np.cross(f0, n0, axis=0)
83
83
  s0 = utils.normalize(s0)
84
84
 
85
- el = basix.ufl.element(
86
- element.family_name,
87
- mesh.ufl_cell().cellname(),
88
- degree=element.degree,
89
- discontinuous=element.discontinuous,
90
- shape=(mesh.geometry.dim,),
85
+ Vv = space_from_string(
86
+ space_string=f"{element.family_name}_{element.degree}", mesh=mesh, dim=mesh.geometry.dim
91
87
  )
92
- Vv = dolfinx.fem.functionspace(mesh, el)
93
88
 
94
89
  fiber = dolfinx.fem.Function(Vv)
95
90
  norm_f = np.linalg.norm(f0, axis=0)
@@ -131,10 +126,13 @@ def create_microstructure(
131
126
  )
132
127
 
133
128
  if outdir is not None:
134
- with dolfinx.io.VTXWriter(
135
- mesh.comm, Path(outdir) / "laplace.bp", [t], engine="BP4"
136
- ) as file:
137
- file.write(0.0)
129
+ try:
130
+ with dolfinx.io.VTXWriter(
131
+ mesh.comm, Path(outdir) / "laplace.bp", [t], engine="BP4"
132
+ ) as file:
133
+ file.write(0.0)
134
+ except RuntimeError:
135
+ pass
138
136
 
139
137
  system = compute_system(
140
138
  t,
@@ -1,9 +1,9 @@
1
1
  from pathlib import Path
2
2
 
3
- import basix
4
3
  import dolfinx
5
4
  import numpy as np
6
5
 
6
+ from ..utils import space_from_string
7
7
  from . import utils
8
8
 
9
9
 
@@ -59,14 +59,9 @@ def compute_system(
59
59
  n0 = np.cross(f0, s0, axis=0)
60
60
  n0 = utils.normalize(n0)
61
61
 
62
- el = basix.ufl.element(
63
- element.family_name,
64
- mesh.ufl_cell().cellname(),
65
- degree=element.degree,
66
- discontinuous=element.discontinuous,
67
- shape=(mesh.geometry.dim,),
62
+ Vv = space_from_string(
63
+ space_string=f"{element.family_name}_{element.degree}", mesh=mesh, dim=mesh.geometry.dim
68
64
  )
69
- Vv = dolfinx.fem.functionspace(mesh, el)
70
65
 
71
66
  fiber = dolfinx.fem.Function(Vv)
72
67
  norm_f = np.linalg.norm(f0, axis=0)
@@ -134,10 +129,13 @@ def create_microstructure(
134
129
  function_space=function_space,
135
130
  )
136
131
  if outdir is not None:
137
- with dolfinx.io.VTXWriter(
138
- mesh.comm, Path(outdir) / "laplace.bp", [t], engine="BP4"
139
- ) as file:
140
- file.write(0.0)
132
+ try:
133
+ with dolfinx.io.VTXWriter(
134
+ mesh.comm, Path(outdir) / "laplace.bp", [t], engine="BP4"
135
+ ) as file:
136
+ file.write(0.0)
137
+ except RuntimeError:
138
+ pass
141
139
 
142
140
  system = compute_system(
143
141
  t,
@@ -7,6 +7,8 @@ import numpy as np
7
7
  import ufl
8
8
  from dolfinx.fem.petsc import LinearProblem
9
9
 
10
+ from ..utils import space_from_string
11
+
10
12
 
11
13
  class Microstructure(NamedTuple):
12
14
  f0: dolfinx.fem.Function
@@ -20,17 +22,20 @@ def save_microstructure(
20
22
  from ..utils import element2array
21
23
 
22
24
  # Save for paraview visualization
23
- with dolfinx.io.VTXWriter(
24
- mesh.comm, Path(outdir) / "microstructure-viz.bp", functions, engine="BP4"
25
- ) as file:
26
- file.write(0.0)
25
+ try:
26
+ with dolfinx.io.VTXWriter(
27
+ mesh.comm, Path(outdir) / "microstructure-viz.bp", functions, engine="BP4"
28
+ ) as file:
29
+ file.write(0.0)
30
+ except RuntimeError:
31
+ pass
27
32
 
28
33
  # Save with proper function space
29
34
  filename = Path(outdir) / "microstructure.bp"
30
35
  for function in functions:
31
36
  adios4dolfinx.write_function(u=function, filename=filename)
32
37
 
33
- attributes = {f.name: element2array(f.ufl_element().basix_element) for f in functions}
38
+ attributes = {f.name: element2array(f.ufl_element()) for f in functions}
34
39
  adios4dolfinx.write_attributes(
35
40
  comm=mesh.comm,
36
41
  filename=filename,
@@ -73,10 +78,10 @@ def laplace(
73
78
  uh = problem.solve()
74
79
 
75
80
  if function_space != "P_1":
76
- family, degree = function_space.split("_")
77
- W = dolfinx.fem.functionspace(mesh, (family, int(degree)))
81
+ W = space_from_string(function_space, mesh, dim=1)
78
82
  t = dolfinx.fem.Function(W)
79
- t.interpolate(uh)
83
+ expr = dolfinx.fem.Expression(uh, W.element.interpolation_points())
84
+ t.interpolate(expr)
80
85
  else:
81
86
  t = uh
82
87
 
@@ -15,9 +15,11 @@ from . import utils
15
15
  @dataclass # (frozen=True, slots=True)
16
16
  class Geometry:
17
17
  mesh: dolfinx.mesh.Mesh
18
- markers: dict[str, tuple[str, str]] = field(default_factory=dict)
19
- ffun: dolfinx.mesh.MeshTags | None = None
18
+ markers: dict[str, tuple[int, int]] = field(default_factory=dict)
20
19
  cfun: dolfinx.mesh.MeshTags | None = None
20
+ ffun: dolfinx.mesh.MeshTags | None = None
21
+ efun: dolfinx.mesh.MeshTags | None = None
22
+ vfun: dolfinx.mesh.MeshTags | None = None
21
23
  f0: dolfinx.fem.Function | None = None
22
24
  s0: dolfinx.fem.Function | None = None
23
25
  n0: dolfinx.fem.Function | None = None
@@ -25,8 +27,7 @@ class Geometry:
25
27
  def save(self, path: str | Path) -> None:
26
28
  path = Path(path)
27
29
 
28
- if path.exists() and self.mesh.comm.rank == 0:
29
- shutil.rmtree(path)
30
+ shutil.rmtree(path, ignore_errors=True)
30
31
  self.mesh.comm.barrier()
31
32
  adios4dolfinx.write_mesh(mesh=self.mesh, filename=path)
32
33
 
@@ -37,15 +38,37 @@ class Geometry:
37
38
  attributes={k: np.array(v, dtype=np.uint8) for k, v in self.markers.items()},
38
39
  )
39
40
 
41
+ if self.cfun is not None:
42
+ adios4dolfinx.write_meshtags(
43
+ meshtags=self.cfun,
44
+ mesh=self.mesh,
45
+ filename=path,
46
+ meshtag_name="Cell tags",
47
+ )
40
48
  if self.ffun is not None:
41
49
  adios4dolfinx.write_meshtags(
42
50
  meshtags=self.ffun,
43
51
  mesh=self.mesh,
44
52
  filename=path,
53
+ meshtag_name="Facet tags",
54
+ )
55
+ if self.efun is not None:
56
+ adios4dolfinx.write_meshtags(
57
+ meshtags=self.efun,
58
+ mesh=self.mesh,
59
+ filename=path,
60
+ meshtag_name="Edge tags",
61
+ )
62
+ if self.vfun is not None:
63
+ adios4dolfinx.write_meshtags(
64
+ meshtags=self.vfun,
65
+ mesh=self.mesh,
66
+ filename=path,
67
+ meshtag_name="Vertex tags",
45
68
  )
46
69
 
47
70
  if self.f0 is not None:
48
- el = self.f0.ufl_element().basix_element
71
+ el = self.f0.ufl_element()
49
72
  arr = utils.element2array(el)
50
73
 
51
74
  adios4dolfinx.write_attributes(
@@ -60,26 +83,49 @@ class Geometry:
60
83
  if self.n0 is not None:
61
84
  adios4dolfinx.write_function(u=self.n0, filename=path, name="n0")
62
85
 
86
+ self.mesh.comm.barrier()
87
+
63
88
  @classmethod
64
89
  def from_file(cls, comm: MPI.Intracomm, path: str | Path) -> "Geometry":
65
90
  path = Path(path)
91
+
66
92
  mesh = adios4dolfinx.read_mesh(comm=comm, filename=path)
67
93
  markers = adios4dolfinx.read_attributes(comm=comm, filename=path, name="markers")
68
- ffun = adios4dolfinx.read_meshtags(mesh=mesh, meshtag_name="Facet tags", filename=path)
94
+ tags = {}
95
+ for name, meshtag_name in (
96
+ ("cfun", "Cell tags"),
97
+ ("ffun", "Facet tags"),
98
+ ("efun", "Edge tags"),
99
+ ("vfun", "Vertex tags"),
100
+ ):
101
+ try:
102
+ tags[name] = adios4dolfinx.read_meshtags(
103
+ mesh=mesh, meshtag_name=meshtag_name, filename=path
104
+ )
105
+ except KeyError:
106
+ tags[name] = None
107
+
108
+ functions = {}
69
109
  function_space = adios4dolfinx.read_attributes(
70
110
  comm=comm, filename=path, name="function_space"
71
111
  )
72
- element = utils.array2element(function_space["f0"])
73
- # Assume same function space for all functions
74
- V = dolfinx.fem.functionspace(mesh, element)
75
- f0 = dolfinx.fem.Function(V, name="f0")
76
- s0 = dolfinx.fem.Function(V, name="s0")
77
- n0 = dolfinx.fem.Function(V, name="n0")
78
-
79
- adios4dolfinx.read_function(u=f0, filename=path, name="f0")
80
- adios4dolfinx.read_function(u=s0, filename=path, name="s0")
81
- adios4dolfinx.read_function(u=n0, filename=path, name="n0")
82
- return cls(mesh=mesh, markers=markers, ffun=ffun, f0=f0, s0=s0, n0=n0)
112
+ for name, el in function_space.items():
113
+ element = utils.array2element(el)
114
+ V = dolfinx.fem.functionspace(mesh, element)
115
+ f = dolfinx.fem.Function(V, name=name)
116
+ try:
117
+ adios4dolfinx.read_function(u=f, filename=path, name=name)
118
+ except KeyError:
119
+ continue
120
+ else:
121
+ functions[name] = f
122
+
123
+ return cls(
124
+ mesh=mesh,
125
+ markers=markers,
126
+ **functions,
127
+ **tags,
128
+ )
83
129
 
84
130
  @classmethod
85
131
  def from_folder(cls, comm: MPI.Intracomm, folder: str | Path) -> "Geometry":
@@ -87,7 +133,7 @@ class Geometry:
87
133
 
88
134
  # Read mesh
89
135
  if (folder / "mesh.xdmf").exists():
90
- mesh, cfun, ffun = utils.read_mesh(comm=comm, filename=folder / "mesh.xdmf")
136
+ mesh, tags = utils.read_mesh(comm=comm, filename=folder / "mesh.xdmf")
91
137
  else:
92
138
  raise ValueError("No mesh file found")
93
139
 
@@ -101,22 +147,26 @@ class Geometry:
101
147
  else:
102
148
  markers = {}
103
149
 
150
+ functions = {}
104
151
  microstructure_path = folder / "microstructure.bp"
105
152
  if microstructure_path.exists():
106
153
  function_space = adios4dolfinx.read_attributes(
107
154
  comm=MPI.COMM_WORLD, filename=microstructure_path, name="function_space"
108
155
  )
109
- # Assume same function space for all functions
110
- element = utils.array2element(function_space["f0"])
111
- V = dolfinx.fem.functionspace(mesh, element)
112
- f0 = dolfinx.fem.Function(V, name="f0")
113
- s0 = dolfinx.fem.Function(V, name="s0")
114
- n0 = dolfinx.fem.Function(V, name="n0")
115
-
116
- adios4dolfinx.read_function(u=f0, filename=microstructure_path, name="f0")
117
- adios4dolfinx.read_function(u=s0, filename=microstructure_path, name="s0")
118
- adios4dolfinx.read_function(u=n0, filename=microstructure_path, name="n0")
119
- else:
120
- f0 = s0 = n0 = None
121
-
122
- return cls(mesh=mesh, ffun=ffun, cfun=cfun, markers=markers, f0=f0, s0=s0, n0=n0)
156
+ for name, el in function_space.items():
157
+ element = utils.array2element(el)
158
+ V = dolfinx.fem.functionspace(mesh, element)
159
+ f = dolfinx.fem.Function(V, name=name)
160
+ try:
161
+ adios4dolfinx.read_function(u=f, filename=microstructure_path, name=name)
162
+ except KeyError:
163
+ continue
164
+ else:
165
+ functions[name] = f
166
+
167
+ return cls(
168
+ mesh=mesh,
169
+ markers=markers,
170
+ **functions,
171
+ **tags,
172
+ )