cardiac-geometriesx 0.0.1__py3-none-any.whl
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.
- cardiac_geometries/__init__.py +8 -0
- cardiac_geometries/cli.py +875 -0
- cardiac_geometries/fibers/__init__.py +6 -0
- cardiac_geometries/fibers/lv_ellipsoid.py +150 -0
- cardiac_geometries/fibers/slab.py +150 -0
- cardiac_geometries/fibers/utils.py +84 -0
- cardiac_geometries/geometry.py +126 -0
- cardiac_geometries/mesh.py +727 -0
- cardiac_geometries/utils.py +173 -0
- cardiac_geometriesx-0.0.1.dist-info/METADATA +52 -0
- cardiac_geometriesx-0.0.1.dist-info/RECORD +14 -0
- cardiac_geometriesx-0.0.1.dist-info/WHEEL +5 -0
- cardiac_geometriesx-0.0.1.dist-info/entry_points.txt +2 -0
- cardiac_geometriesx-0.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import dolfinx
|
|
3
|
+
import numpy as np
|
|
4
|
+
import basix
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
from . import utils
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def compute_system(
|
|
11
|
+
t_func: dolfinx.fem.Function,
|
|
12
|
+
r_short_endo=0.025,
|
|
13
|
+
r_short_epi=0.035,
|
|
14
|
+
r_long_endo=0.09,
|
|
15
|
+
r_long_epi=0.097,
|
|
16
|
+
alpha_endo: float = -60,
|
|
17
|
+
alpha_epi: float = 60,
|
|
18
|
+
**kwargs,
|
|
19
|
+
) -> utils.Microstructure:
|
|
20
|
+
V = t_func.function_space
|
|
21
|
+
element = V.ufl_element()
|
|
22
|
+
mesh = V.mesh
|
|
23
|
+
|
|
24
|
+
dof_coordinates = V.tabulate_dof_coordinates()
|
|
25
|
+
|
|
26
|
+
alpha = lambda x: (alpha_endo + (alpha_epi - alpha_endo) * x) * (np.pi / 180)
|
|
27
|
+
r_long = lambda x: r_long_endo + (r_long_epi - r_long_endo) * x
|
|
28
|
+
r_short = lambda x: r_short_endo + (r_short_epi - r_short_endo) * x
|
|
29
|
+
|
|
30
|
+
drl_dt = r_long_epi - r_long_endo
|
|
31
|
+
drs_dt = r_short_epi - r_short_endo
|
|
32
|
+
|
|
33
|
+
t = t_func.x.array
|
|
34
|
+
|
|
35
|
+
rl = r_long(t)
|
|
36
|
+
rs = r_short(t)
|
|
37
|
+
al = alpha(t)
|
|
38
|
+
|
|
39
|
+
x = dof_coordinates[:, 0]
|
|
40
|
+
y = dof_coordinates[:, 1]
|
|
41
|
+
z = dof_coordinates[:, 2]
|
|
42
|
+
|
|
43
|
+
a = np.sqrt(y**2 + z**2) / rs
|
|
44
|
+
b = x / rl
|
|
45
|
+
mu = np.arctan2(a, b)
|
|
46
|
+
theta = np.pi - np.arctan2(z, -y)
|
|
47
|
+
theta[mu < 1e-7] = 0.0
|
|
48
|
+
|
|
49
|
+
e_t = np.array(
|
|
50
|
+
[
|
|
51
|
+
drl_dt * np.cos(mu),
|
|
52
|
+
drs_dt * np.sin(mu) * np.cos(theta),
|
|
53
|
+
drs_dt * np.sin(mu) * np.sin(theta),
|
|
54
|
+
],
|
|
55
|
+
)
|
|
56
|
+
e_t = utils.normalize(e_t)
|
|
57
|
+
|
|
58
|
+
e_mu = np.array(
|
|
59
|
+
[
|
|
60
|
+
-rl * np.sin(mu),
|
|
61
|
+
rs * np.cos(mu) * np.cos(theta),
|
|
62
|
+
rs * np.cos(mu) * np.sin(theta),
|
|
63
|
+
],
|
|
64
|
+
)
|
|
65
|
+
e_mu = utils.normalize(e_mu)
|
|
66
|
+
|
|
67
|
+
e_theta = np.array(
|
|
68
|
+
[
|
|
69
|
+
np.zeros_like(t),
|
|
70
|
+
-rs * np.sin(mu) * np.sin(theta),
|
|
71
|
+
rs * np.sin(mu) * np.cos(theta),
|
|
72
|
+
],
|
|
73
|
+
)
|
|
74
|
+
e_theta = utils.normalize(e_theta)
|
|
75
|
+
|
|
76
|
+
f0 = np.sin(al) * e_mu + np.cos(al) * e_theta
|
|
77
|
+
f0 = utils.normalize(f0)
|
|
78
|
+
|
|
79
|
+
n0 = np.cross(e_mu, e_theta, axis=0)
|
|
80
|
+
n0 = utils.normalize(n0)
|
|
81
|
+
|
|
82
|
+
s0 = np.cross(f0, n0, axis=0)
|
|
83
|
+
s0 = utils.normalize(s0)
|
|
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,),
|
|
91
|
+
)
|
|
92
|
+
Vv = dolfinx.fem.functionspace(mesh, el)
|
|
93
|
+
|
|
94
|
+
fiber = dolfinx.fem.Function(Vv)
|
|
95
|
+
norm_f = np.linalg.norm(f0, axis=0)
|
|
96
|
+
fiber.x.array[:] = (f0 / norm_f).T.reshape(-1)
|
|
97
|
+
fiber.name = "f0"
|
|
98
|
+
|
|
99
|
+
sheet = dolfinx.fem.Function(Vv)
|
|
100
|
+
sheet.x.array[:] = s0.T.reshape(-1)
|
|
101
|
+
sheet.name = "s0"
|
|
102
|
+
|
|
103
|
+
sheet_normal = dolfinx.fem.Function(Vv)
|
|
104
|
+
sheet_normal.x.array[:] = n0.T.reshape(-1)
|
|
105
|
+
sheet_normal.name = "n0"
|
|
106
|
+
|
|
107
|
+
return utils.Microstructure(f0=fiber, s0=sheet, n0=sheet_normal)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def create_microstructure(
|
|
111
|
+
mesh,
|
|
112
|
+
ffun,
|
|
113
|
+
markers,
|
|
114
|
+
function_space="P_1",
|
|
115
|
+
r_short_endo=0.025,
|
|
116
|
+
r_short_epi=0.035,
|
|
117
|
+
r_long_endo=0.09,
|
|
118
|
+
r_long_epi=0.097,
|
|
119
|
+
alpha_endo: float = -60,
|
|
120
|
+
alpha_epi: float = 60,
|
|
121
|
+
outdir: str | Path | None = None,
|
|
122
|
+
):
|
|
123
|
+
endo_marker = markers["ENDO"][0]
|
|
124
|
+
epi_marker = markers["EPI"][0]
|
|
125
|
+
t = utils.laplace(
|
|
126
|
+
mesh,
|
|
127
|
+
ffun,
|
|
128
|
+
endo_marker=endo_marker,
|
|
129
|
+
epi_marker=epi_marker,
|
|
130
|
+
function_space=function_space,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
if outdir is not None:
|
|
134
|
+
with dolfinx.io.XDMFFile(mesh.comm, Path(outdir) / "laplace.xdmf", "w") as file:
|
|
135
|
+
file.write_mesh(mesh)
|
|
136
|
+
file.write_function(t)
|
|
137
|
+
system = compute_system(
|
|
138
|
+
t,
|
|
139
|
+
function_space=function_space,
|
|
140
|
+
r_short_endo=r_short_endo,
|
|
141
|
+
r_short_epi=r_short_epi,
|
|
142
|
+
r_long_endo=r_long_endo,
|
|
143
|
+
r_long_epi=r_long_epi,
|
|
144
|
+
alpha_endo=alpha_endo,
|
|
145
|
+
alpha_epi=alpha_epi,
|
|
146
|
+
)
|
|
147
|
+
if outdir is not None:
|
|
148
|
+
utils.save_microstructure(mesh, system, outdir)
|
|
149
|
+
|
|
150
|
+
return system
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import dolfinx
|
|
4
|
+
import numpy as np
|
|
5
|
+
import basix
|
|
6
|
+
|
|
7
|
+
from . import utils
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def compute_system(
|
|
11
|
+
t_func: dolfinx.fem.Function,
|
|
12
|
+
alpha_endo: float = -60,
|
|
13
|
+
alpha_epi: float = 60,
|
|
14
|
+
**kwargs,
|
|
15
|
+
) -> utils.Microstructure:
|
|
16
|
+
"""Compute ldrb system for slab, assuming linear
|
|
17
|
+
angle between endo and epi
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
t_func : dolfin.Function
|
|
22
|
+
Solution to laplace equation with 0 on endo
|
|
23
|
+
and 1 on epi
|
|
24
|
+
alpha_endo : float, optional
|
|
25
|
+
Angle on endocardium, by default -60
|
|
26
|
+
alpha_epi : float, optional
|
|
27
|
+
Angle on epicardium, by default 60
|
|
28
|
+
|
|
29
|
+
Returns
|
|
30
|
+
-------
|
|
31
|
+
Microstructure
|
|
32
|
+
Tuple with fiber, sheet and sheet normal
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
V = t_func.function_space
|
|
36
|
+
element = V.ufl_element()
|
|
37
|
+
mesh = V.mesh
|
|
38
|
+
|
|
39
|
+
alpha = lambda x: (alpha_endo + (alpha_epi - alpha_endo) * x) * (np.pi / 180)
|
|
40
|
+
|
|
41
|
+
t = t_func.x.array
|
|
42
|
+
|
|
43
|
+
f0 = np.array(
|
|
44
|
+
[
|
|
45
|
+
np.cos(alpha(t)),
|
|
46
|
+
np.zeros_like(t),
|
|
47
|
+
np.sin(alpha(t)),
|
|
48
|
+
],
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
s0 = np.array(
|
|
52
|
+
[
|
|
53
|
+
np.zeros_like(t),
|
|
54
|
+
np.ones_like(t),
|
|
55
|
+
np.zeros_like(t),
|
|
56
|
+
],
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
n0 = np.cross(f0, s0, axis=0)
|
|
60
|
+
n0 = utils.normalize(n0)
|
|
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,),
|
|
68
|
+
)
|
|
69
|
+
Vv = dolfinx.fem.functionspace(mesh, el)
|
|
70
|
+
|
|
71
|
+
fiber = dolfinx.fem.Function(Vv)
|
|
72
|
+
norm_f = np.linalg.norm(f0, axis=0)
|
|
73
|
+
fiber.x.array[:] = (f0 / norm_f).T.reshape(-1)
|
|
74
|
+
fiber.name = "f0"
|
|
75
|
+
|
|
76
|
+
sheet = dolfinx.fem.Function(Vv)
|
|
77
|
+
sheet.x.array[:] = s0.T.reshape(-1)
|
|
78
|
+
sheet.name = "s0"
|
|
79
|
+
|
|
80
|
+
sheet_normal = dolfinx.fem.Function(Vv)
|
|
81
|
+
sheet_normal.x.array[:] = n0.T.reshape(-1)
|
|
82
|
+
sheet_normal.name = "n0"
|
|
83
|
+
|
|
84
|
+
return utils.Microstructure(f0=fiber, s0=sheet, n0=sheet_normal)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def create_microstructure(
|
|
88
|
+
mesh: dolfinx.mesh.Mesh,
|
|
89
|
+
ffun: dolfinx.mesh.MeshTags,
|
|
90
|
+
markers: dict[str, tuple[int, int]],
|
|
91
|
+
alpha_endo: float,
|
|
92
|
+
alpha_epi: float,
|
|
93
|
+
function_space: str = "P_1",
|
|
94
|
+
outdir: str | Path | None = None,
|
|
95
|
+
) -> utils.Microstructure:
|
|
96
|
+
"""Generate microstructure for slab using LDRB algorithm
|
|
97
|
+
|
|
98
|
+
Parameters
|
|
99
|
+
----------
|
|
100
|
+
mesh : dolfinx.mesh.Mesh
|
|
101
|
+
A slab mesh
|
|
102
|
+
ffun : dolfinx.mesh.MeshTags
|
|
103
|
+
Facet function defining the boundaries
|
|
104
|
+
markers: Dict[str, Tuple[int, int]]
|
|
105
|
+
Markers with keys Y0 and Y1 representing the endo and
|
|
106
|
+
epi planes respectively. The values should be a tuple
|
|
107
|
+
whose first value is the value of the marker (corresponding
|
|
108
|
+
to ffun) and the second value is the dimension
|
|
109
|
+
alpha_endo : float
|
|
110
|
+
Angle on the endocardium
|
|
111
|
+
alpha_epi : float
|
|
112
|
+
Angle on the epicardium
|
|
113
|
+
function_space : str
|
|
114
|
+
Function space to interpolate the fibers, by default P_1
|
|
115
|
+
outdir : Optional[Union[str, Path]], optional
|
|
116
|
+
Output directory to store the results, by default None.
|
|
117
|
+
If no output directory is specified the results will not be stored,
|
|
118
|
+
but only returned.
|
|
119
|
+
|
|
120
|
+
Returns
|
|
121
|
+
-------
|
|
122
|
+
Microstructure
|
|
123
|
+
Tuple with fiber, sheet and sheet normal
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
endo_marker = markers["Y0"][0]
|
|
127
|
+
epi_marker = markers["Y1"][0]
|
|
128
|
+
|
|
129
|
+
t = utils.laplace(
|
|
130
|
+
mesh,
|
|
131
|
+
ffun,
|
|
132
|
+
endo_marker=endo_marker,
|
|
133
|
+
epi_marker=epi_marker,
|
|
134
|
+
function_space=function_space,
|
|
135
|
+
)
|
|
136
|
+
if outdir is not None:
|
|
137
|
+
with dolfinx.io.XDMFFile(mesh.comm, Path(outdir) / "laplace.xdmf", "w") as file:
|
|
138
|
+
file.write_mesh(mesh)
|
|
139
|
+
file.write_function(t)
|
|
140
|
+
|
|
141
|
+
system = compute_system(
|
|
142
|
+
t,
|
|
143
|
+
alpha_endo=alpha_endo,
|
|
144
|
+
alpha_epi=alpha_epi,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
if outdir is not None:
|
|
148
|
+
utils.save_microstructure(mesh, system, outdir)
|
|
149
|
+
|
|
150
|
+
return system
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
from typing import NamedTuple
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import dolfinx
|
|
5
|
+
from dolfinx.fem.petsc import LinearProblem
|
|
6
|
+
import ufl
|
|
7
|
+
import numpy as np
|
|
8
|
+
import adios4dolfinx
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Microstructure(NamedTuple):
|
|
12
|
+
f0: dolfinx.fem.Function
|
|
13
|
+
s0: dolfinx.fem.Function
|
|
14
|
+
n0: dolfinx.fem.Function
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def save_microstructure(
|
|
18
|
+
mesh: dolfinx.mesh.Mesh, system: Microstructure, outdir: str | Path
|
|
19
|
+
) -> None:
|
|
20
|
+
from ..utils import element2array
|
|
21
|
+
|
|
22
|
+
# Save for paraview visualization
|
|
23
|
+
with dolfinx.io.XDMFFile(mesh.comm, Path(outdir) / "microstructure.xdmf", "w") as file:
|
|
24
|
+
file.write_mesh(mesh)
|
|
25
|
+
file.write_function(system.f0)
|
|
26
|
+
file.write_function(system.s0)
|
|
27
|
+
file.write_function(system.n0)
|
|
28
|
+
|
|
29
|
+
# Save with proper function space
|
|
30
|
+
filename = Path(outdir) / "microstructure.bp"
|
|
31
|
+
adios4dolfinx.write_function(u=system.f0, filename=filename)
|
|
32
|
+
adios4dolfinx.write_function(u=system.s0, filename=filename)
|
|
33
|
+
adios4dolfinx.write_function(u=system.n0, filename=filename)
|
|
34
|
+
arr = element2array(system.f0.ufl_element().basix_element)
|
|
35
|
+
adios4dolfinx.write_attributes(
|
|
36
|
+
comm=mesh.comm,
|
|
37
|
+
filename=filename,
|
|
38
|
+
name="function_space",
|
|
39
|
+
attributes={k: arr for k in ("f0", "s0", "n0")},
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def normalize(u):
|
|
44
|
+
return u / np.linalg.norm(u, axis=0)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def laplace(
|
|
48
|
+
mesh: dolfinx.mesh.Mesh,
|
|
49
|
+
ffun: dolfinx.mesh.MeshTags,
|
|
50
|
+
endo_marker: int,
|
|
51
|
+
epi_marker: int,
|
|
52
|
+
function_space: str,
|
|
53
|
+
):
|
|
54
|
+
V = dolfinx.fem.functionspace(mesh, ("Lagrange", 1))
|
|
55
|
+
|
|
56
|
+
u = ufl.TrialFunction(V)
|
|
57
|
+
v = ufl.TestFunction(V)
|
|
58
|
+
a = ufl.dot(ufl.grad(u), ufl.grad(v)) * ufl.dx
|
|
59
|
+
L = v * dolfinx.fem.Constant(mesh, dolfinx.default_scalar_type(0.0)) * ufl.dx
|
|
60
|
+
|
|
61
|
+
endo_facets = ffun.find(endo_marker)
|
|
62
|
+
endo_dofs = dolfinx.fem.locate_dofs_topological(V, 2, endo_facets)
|
|
63
|
+
epi_facets = ffun.find(epi_marker)
|
|
64
|
+
epi_dofs = dolfinx.fem.locate_dofs_topological(V, 2, epi_facets)
|
|
65
|
+
zero = dolfinx.fem.Constant(mesh, dolfinx.default_scalar_type(0.0))
|
|
66
|
+
one = dolfinx.fem.Constant(mesh, dolfinx.default_scalar_type(1.0))
|
|
67
|
+
|
|
68
|
+
endo_bc = dolfinx.fem.dirichletbc(zero, endo_dofs, V)
|
|
69
|
+
epi_bc = dolfinx.fem.dirichletbc(one, epi_dofs, V)
|
|
70
|
+
|
|
71
|
+
bcs = [endo_bc, epi_bc]
|
|
72
|
+
|
|
73
|
+
problem = LinearProblem(a, L, bcs=bcs, petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
|
|
74
|
+
uh = problem.solve()
|
|
75
|
+
|
|
76
|
+
if function_space != "P_1":
|
|
77
|
+
family, degree = function_space.split("_")
|
|
78
|
+
W = dolfinx.fem.functionspace(mesh, (family, int(degree)))
|
|
79
|
+
t = dolfinx.fem.Function(W)
|
|
80
|
+
t.interpolate(uh)
|
|
81
|
+
else:
|
|
82
|
+
t = uh
|
|
83
|
+
|
|
84
|
+
return t
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
import json
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import dolfinx
|
|
5
|
+
from mpi4py import MPI
|
|
6
|
+
import shutil
|
|
7
|
+
import adios4dolfinx
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
from . import utils
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True, slots=True)
|
|
14
|
+
class Geometry:
|
|
15
|
+
mesh: dolfinx.mesh.Mesh
|
|
16
|
+
markers: dict[str, tuple[str, str]] = field(default_factory=dict)
|
|
17
|
+
ffun: dolfinx.mesh.MeshTags | None = None
|
|
18
|
+
cfun: dolfinx.mesh.MeshTags | None = None
|
|
19
|
+
f0: dolfinx.fem.Function | None = None
|
|
20
|
+
s0: dolfinx.fem.Function | None = None
|
|
21
|
+
n0: dolfinx.fem.Function | None = None
|
|
22
|
+
|
|
23
|
+
def save(self, path: str | Path) -> None:
|
|
24
|
+
path = Path(path)
|
|
25
|
+
|
|
26
|
+
if path.exists() and self.mesh.comm.rank == 0:
|
|
27
|
+
shutil.rmtree(path)
|
|
28
|
+
self.mesh.comm.barrier()
|
|
29
|
+
adios4dolfinx.write_mesh(mesh=self.mesh, filename=path)
|
|
30
|
+
|
|
31
|
+
adios4dolfinx.write_attributes(
|
|
32
|
+
comm=self.mesh.comm,
|
|
33
|
+
filename=path,
|
|
34
|
+
name="markers",
|
|
35
|
+
attributes={k: np.array(v, dtype=np.uint8) for k, v in self.markers.items()},
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
if self.ffun is not None:
|
|
39
|
+
adios4dolfinx.write_meshtags(
|
|
40
|
+
meshtags=self.ffun,
|
|
41
|
+
mesh=self.mesh,
|
|
42
|
+
filename=path,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
if self.f0 is not None:
|
|
46
|
+
el = self.f0.ufl_element().basix_element
|
|
47
|
+
arr = utils.element2array(el)
|
|
48
|
+
|
|
49
|
+
adios4dolfinx.write_attributes(
|
|
50
|
+
comm=self.mesh.comm,
|
|
51
|
+
filename=path,
|
|
52
|
+
name="function_space",
|
|
53
|
+
attributes={k: arr for k in ("f0", "s0", "n0")},
|
|
54
|
+
)
|
|
55
|
+
adios4dolfinx.write_function(u=self.f0, filename=path, name="f0")
|
|
56
|
+
if self.s0 is not None:
|
|
57
|
+
adios4dolfinx.write_function(u=self.s0, filename=path, name="s0")
|
|
58
|
+
if self.n0 is not None:
|
|
59
|
+
adios4dolfinx.write_function(u=self.n0, filename=path, name="n0")
|
|
60
|
+
|
|
61
|
+
@classmethod
|
|
62
|
+
def from_file(cls, comm: MPI.Intracomm, path: str | Path) -> "Geometry":
|
|
63
|
+
path = Path(path)
|
|
64
|
+
mesh = adios4dolfinx.read_mesh(comm=comm, filename=path)
|
|
65
|
+
markers = adios4dolfinx.read_attributes(comm=comm, filename=path, name="markers")
|
|
66
|
+
ffun = adios4dolfinx.read_meshtags(mesh=mesh, meshtag_name="Facet tags", filename=path)
|
|
67
|
+
function_space = adios4dolfinx.read_attributes(
|
|
68
|
+
comm=comm, filename=path, name="function_space"
|
|
69
|
+
)
|
|
70
|
+
element = utils.array2element(function_space["f0"])
|
|
71
|
+
# Assume same function space for all functions
|
|
72
|
+
V = dolfinx.fem.functionspace(mesh, element)
|
|
73
|
+
f0 = dolfinx.fem.Function(V, name="f0")
|
|
74
|
+
s0 = dolfinx.fem.Function(V, name="s0")
|
|
75
|
+
n0 = dolfinx.fem.Function(V, name="n0")
|
|
76
|
+
|
|
77
|
+
adios4dolfinx.read_function(u=f0, filename=path, name="f0")
|
|
78
|
+
adios4dolfinx.read_function(u=s0, filename=path, name="s0")
|
|
79
|
+
adios4dolfinx.read_function(u=n0, filename=path, name="n0")
|
|
80
|
+
return cls(mesh=mesh, markers=markers, ffun=ffun, f0=f0, s0=s0, n0=n0)
|
|
81
|
+
|
|
82
|
+
@classmethod
|
|
83
|
+
def from_folder(cls, comm: MPI.Intracomm, folder: str | Path) -> "Geometry":
|
|
84
|
+
folder = Path(folder)
|
|
85
|
+
|
|
86
|
+
# Read mesh
|
|
87
|
+
if (folder / "mesh.xdmf").exists():
|
|
88
|
+
mesh, cfun = utils.read_mesh(comm=comm, filename=folder / "mesh.xdmf")
|
|
89
|
+
else:
|
|
90
|
+
raise ValueError("No mesh file found")
|
|
91
|
+
|
|
92
|
+
# Read meshtags
|
|
93
|
+
if (folder / "triangle_mesh.xdmf").exists():
|
|
94
|
+
ffun = utils.read_ffun(mesh=mesh, filename=folder / "triangle_mesh.xdmf")
|
|
95
|
+
else:
|
|
96
|
+
ffun = None
|
|
97
|
+
|
|
98
|
+
# Read markers
|
|
99
|
+
if (folder / "markers.json").exists():
|
|
100
|
+
if comm.rank == 0:
|
|
101
|
+
markers = json.loads((folder / "markers.json").read_text())
|
|
102
|
+
else:
|
|
103
|
+
markers = {}
|
|
104
|
+
markers = comm.bcast(markers, root=0)
|
|
105
|
+
else:
|
|
106
|
+
markers = {}
|
|
107
|
+
|
|
108
|
+
microstructure_path = folder / "microstructure.bp"
|
|
109
|
+
if microstructure_path.exists():
|
|
110
|
+
function_space = adios4dolfinx.read_attributes(
|
|
111
|
+
comm=MPI.COMM_WORLD, filename=microstructure_path, name="function_space"
|
|
112
|
+
)
|
|
113
|
+
# Assume same function space for all functions
|
|
114
|
+
element = utils.array2element(function_space["f0"])
|
|
115
|
+
V = dolfinx.fem.functionspace(mesh, element)
|
|
116
|
+
f0 = dolfinx.fem.Function(V, name="f0")
|
|
117
|
+
s0 = dolfinx.fem.Function(V, name="s0")
|
|
118
|
+
n0 = dolfinx.fem.Function(V, name="n0")
|
|
119
|
+
|
|
120
|
+
adios4dolfinx.read_function(u=f0, filename=microstructure_path, name="f0")
|
|
121
|
+
adios4dolfinx.read_function(u=s0, filename=microstructure_path, name="s0")
|
|
122
|
+
adios4dolfinx.read_function(u=n0, filename=microstructure_path, name="n0")
|
|
123
|
+
else:
|
|
124
|
+
f0 = s0 = n0 = None
|
|
125
|
+
|
|
126
|
+
return cls(mesh=mesh, ffun=ffun, cfun=cfun, markers=markers, f0=f0, s0=s0, n0=n0)
|