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.

@@ -0,0 +1,727 @@
1
+ from pathlib import Path
2
+ import math
3
+ import json
4
+ import datetime
5
+ from importlib.metadata import metadata
6
+ from structlog import get_logger
7
+
8
+ from mpi4py import MPI
9
+ import cardiac_geometries_core as cgc
10
+
11
+ from . import utils
12
+ from .geometry import Geometry
13
+
14
+ meta = metadata("cardiac-geometriesx")
15
+ __version__ = meta["Version"]
16
+
17
+ logger = get_logger()
18
+
19
+
20
+ def biv_ellipsoid(
21
+ outdir: str | Path,
22
+ char_length: float = 0.5,
23
+ center_lv_x: float = 0.0,
24
+ center_lv_y: float = 0.0,
25
+ center_lv_z: float = 0.0,
26
+ a_endo_lv: float = 2.5,
27
+ b_endo_lv: float = 1.0,
28
+ c_endo_lv: float = 1.0,
29
+ a_epi_lv: float = 3.0,
30
+ b_epi_lv: float = 1.5,
31
+ c_epi_lv: float = 1.5,
32
+ center_rv_x: float = 0.0,
33
+ center_rv_y: float = 0.5,
34
+ center_rv_z: float = 0.0,
35
+ a_endo_rv: float = 3.0,
36
+ b_endo_rv: float = 1.5,
37
+ c_endo_rv: float = 1.5,
38
+ a_epi_rv: float = 4.0,
39
+ b_epi_rv: float = 2.5,
40
+ c_epi_rv: float = 2.0,
41
+ create_fibers: bool = False,
42
+ fiber_angle_endo: float = -60,
43
+ fiber_angle_epi: float = +60,
44
+ fiber_space: str = "P_1",
45
+ ) -> Geometry:
46
+ """Create BiV ellipsoidal geometry
47
+
48
+ Parameters
49
+ ----------
50
+ outdir : str | Path
51
+ Directory where to save the results.
52
+ char_length : float, optional
53
+ Characteristic length of mesh, by default 0.5
54
+ center_lv_y : float, optional
55
+ X-coordinate for the center of the lv, by default 0.0
56
+ center_lv_y : float, optional
57
+ Y-coordinate for the center of the lv, by default 0.0
58
+ center_lv_z : float, optional
59
+ Z-coordinate for the center of the lv, by default 0.0
60
+ a_endo_lv : float, optional
61
+ Dilation of lv endo ellipsoid in the x-direction, by default 2.5
62
+ b_endo_lv : float, optional
63
+ Dilation of lv endo ellipsoid in the y-direction, by default 1.0
64
+ c_endo_lv : float, optional
65
+ Dilation of lv endo ellipsoid in the z-direction, by default 1.0
66
+ a_epi_lv : float, optional
67
+ Dilation of lv epi ellipsoid in the x-direction, by default 3.0
68
+ b_epi_lv : float, optional
69
+ Dilation of lv epi ellipsoid in the y-direction, by default 1.5
70
+ c_epi_lv : float, optional
71
+ Dilation of lv epi ellipsoid in the z-direction, by default 1.5
72
+ center_rv_x : float, optional
73
+ X-coordinate for the center of the rv, by default 0.0
74
+ center_rv_y : float, optional
75
+ Y-coordinate for the center of the rv, by default 0.5
76
+ center_rv_z : float, optional
77
+ Z-coordinate for the center of the rv, by default 0.0
78
+ a_endo_rv : float, optional
79
+ Dilation of rv endo ellipsoid in the x-direction, by default 3.0
80
+ b_endo_rv : float, optional
81
+ Dilation of rv endo ellipsoid in the y-direction, by default 1.5
82
+ c_endo_rv : float, optional
83
+ Dilation of rv endo ellipsoid in the z-direction, by default 1.5
84
+ a_epi_rv : float, optional
85
+ Dilation of rv epi ellipsoid in the x-direction, by default 4.0
86
+ b_epi_rv : float, optional
87
+ Dilation of rv epi ellipsoid in the y-direction, by default 2.5
88
+ c_epi_rv : float, optional
89
+ Dilation of rv epi ellipsoid in the z-direction, by default 2.0
90
+ create_fibers : bool, optional
91
+ If True create analytic fibers, by default False
92
+ fiber_angle_endo : float, optional
93
+ Angle for the endocardium, by default -60
94
+ fiber_angle_epi : float, optional
95
+ Angle for the epicardium, by default +60
96
+ fiber_space : str, optional
97
+ Function space for fibers of the form family_degree, by default "P_1"
98
+
99
+ Returns
100
+ -------
101
+ Geometry
102
+ A Geometry with the mesh, markers, markers functions and fibers.
103
+
104
+ """
105
+ comm = MPI.COMM_WORLD
106
+ outdir = Path(outdir)
107
+ mesh_name = outdir / "biv_ellipsoid.msh"
108
+ if comm.rank == 0:
109
+ outdir.mkdir(exist_ok=True, parents=True)
110
+
111
+ with open(outdir / "info.json", "w") as f:
112
+ json.dump(
113
+ {
114
+ "char_length": char_length,
115
+ "center_lv_x": center_lv_x,
116
+ "center_lv_y": center_lv_y,
117
+ "center_lv_z": center_lv_z,
118
+ "a_endo_lv": a_endo_lv,
119
+ "b_endo_lv": b_endo_lv,
120
+ "c_endo_lv": c_endo_lv,
121
+ "a_epi_lv": a_epi_lv,
122
+ "b_epi_lv": b_epi_lv,
123
+ "c_epi_lv": c_epi_lv,
124
+ "center_rv_x": center_rv_x,
125
+ "center_rv_y": center_rv_y,
126
+ "center_rv_z": center_rv_z,
127
+ "a_endo_rv": a_endo_rv,
128
+ "b_endo_rv": b_endo_rv,
129
+ "c_endo_rv": c_endo_rv,
130
+ "a_epi_rv": a_epi_rv,
131
+ "b_epi_rv": b_epi_rv,
132
+ "c_epi_rv": c_epi_rv,
133
+ "create_fibers": create_fibers,
134
+ "fibers_angle_endo": fiber_angle_endo,
135
+ "fibers_angle_epi": fiber_angle_epi,
136
+ "fiber_space": fiber_space,
137
+ # "mesh_type": MeshTypes.biv_ellipsoid.value,
138
+ "cardiac_geometry_version": __version__,
139
+ "timestamp": datetime.datetime.now().isoformat(),
140
+ },
141
+ f,
142
+ indent=2,
143
+ default=utils.json_serial,
144
+ )
145
+
146
+ cgc.biv_ellipsoid(
147
+ mesh_name=mesh_name.as_posix(),
148
+ char_length=char_length,
149
+ center_lv_x=center_lv_x,
150
+ center_lv_y=center_lv_y,
151
+ center_lv_z=center_lv_z,
152
+ a_endo_lv=a_endo_lv,
153
+ b_endo_lv=b_endo_lv,
154
+ c_endo_lv=c_endo_lv,
155
+ a_epi_lv=a_epi_lv,
156
+ b_epi_lv=b_epi_lv,
157
+ c_epi_lv=c_epi_lv,
158
+ center_rv_x=center_rv_x,
159
+ center_rv_y=center_rv_y,
160
+ center_rv_z=center_rv_z,
161
+ a_endo_rv=a_endo_rv,
162
+ b_endo_rv=b_endo_rv,
163
+ c_endo_rv=c_endo_rv,
164
+ a_epi_rv=a_epi_rv,
165
+ b_epi_rv=b_epi_rv,
166
+ c_epi_rv=c_epi_rv,
167
+ )
168
+ comm.barrier()
169
+ geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name, unlink=False)
170
+
171
+ if comm.rank == 0:
172
+ with open(outdir / "markers.json", "w") as f:
173
+ json.dump(geometry.markers, f, default=utils.json_serial)
174
+ comm.barrier()
175
+ if create_fibers:
176
+ raise NotImplementedError("Fibers not implemented yet for biv ellipsoid.")
177
+ # from .fibers._biv_ellipsoid import create_biv_fibers
178
+
179
+ # create_biv_fibers(
180
+ # mesh=geometry.mesh,
181
+ # ffun=geometry.marker_functions.ffun,
182
+ # markers=geometry.markers,
183
+ # fiber_space=fiber_space,
184
+ # alpha_endo=fiber_angle_endo,
185
+ # alpha_epi=fiber_angle_epi,
186
+ # outdir=outdir,
187
+ # )
188
+
189
+ geo = Geometry.from_folder(comm=comm, folder=outdir)
190
+ return geo
191
+
192
+
193
+ def biv_ellipsoid_torso(
194
+ outdir: str | Path,
195
+ char_length: float = 0.5,
196
+ heart_as_surface: bool = False,
197
+ torso_length: float = 20.0,
198
+ torso_width: float = 20.0,
199
+ torso_height: float = 20.0,
200
+ rotation_angle: float = math.pi / 6,
201
+ center_lv_x: float = 0.0,
202
+ center_lv_y: float = 0.0,
203
+ center_lv_z: float = 0.0,
204
+ a_endo_lv: float = 2.5,
205
+ b_endo_lv: float = 1.0,
206
+ c_endo_lv: float = 1.0,
207
+ a_epi_lv: float = 3.0,
208
+ b_epi_lv: float = 1.5,
209
+ c_epi_lv: float = 1.5,
210
+ center_rv_x: float = 0.0,
211
+ center_rv_y: float = 0.5,
212
+ center_rv_z: float = 0.0,
213
+ a_endo_rv: float = 3.0,
214
+ b_endo_rv: float = 1.5,
215
+ c_endo_rv: float = 1.5,
216
+ a_epi_rv: float = 4.0,
217
+ b_epi_rv: float = 2.5,
218
+ c_epi_rv: float = 2.0,
219
+ create_fibers: bool = False,
220
+ fiber_angle_endo: float = -60,
221
+ fiber_angle_epi: float = +60,
222
+ fiber_space: str = "P_1",
223
+ ) -> Geometry:
224
+ """Create BiV ellipsoidal geometry
225
+
226
+ Parameters
227
+ ----------
228
+ outdir : str | Path
229
+ Directory where to save the results.
230
+ char_length : float, optional
231
+ Characteristic length of mesh, by default 0.5
232
+ heart_as_surface: bool
233
+ If true, create the heart as a a surface inside the torso,
234
+ otherwise let the heart be a volume, by default True.
235
+ torso_length : float, optional
236
+ Length of torso in the x-direction, by default 20.0
237
+ torso_width : float, optional
238
+ Length of torso in the y-direction, by default 20.0
239
+ torso_height : float, optional
240
+ Length of torso in the z-direction, by default 20.0
241
+ rotation_angle: float, optional
242
+ Angle to rotate the torso in order to object realistic position of
243
+ the heart in a torso, by default pi / 6
244
+ center_lv_x : float, optional
245
+ X-coordinate for the center of the lv, by default 0.0
246
+ center_lv_y : float, optional
247
+ Y-coordinate for the center of the lv, by default 0.0
248
+ center_lv_z : float, optional
249
+ Z-coordinate for the center of the lv, by default 0.0
250
+ a_endo_lv : float, optional
251
+ Dilation of lv endo ellipsoid in the x-direction, by default 2.5
252
+ b_endo_lv : float, optional
253
+ Dilation of lv endo ellipsoid in the y-direction, by default 1.0
254
+ c_endo_lv : float, optional
255
+ Dilation of lv endo ellipsoid in the z-direction, by default 1.0
256
+ a_epi_lv : float, optional
257
+ Dilation of lv epi ellipsoid in the x-direction, by default 3.0
258
+ b_epi_lv : float, optional
259
+ Dilation of lv epi ellipsoid in the y-direction, by default 1.5
260
+ c_epi_lv : float, optional
261
+ Dilation of lv epi ellipsoid in the z-direction, by default 1.5
262
+ center_rv_x : float, optional
263
+ X-coordinate for the center of the rv, by default 0.0
264
+ center_rv_y : float, optional
265
+ Y-coordinate for the center of the rv, by default 0.5
266
+ center_rv_z : float, optional
267
+ Z-coordinate for the center of the rv, by default 0.0
268
+ a_endo_rv : float, optional
269
+ Dilation of rv endo ellipsoid in the x-direction, by default 3.0
270
+ b_endo_rv : float, optional
271
+ Dilation of rv endo ellipsoid in the y-direction, by default 1.5
272
+ c_endo_rv : float, optional
273
+ Dilation of rv endo ellipsoid in the z-direction, by default 1.5
274
+ a_epi_rv : float, optional
275
+ Dilation of rv epi ellipsoid in the x-direction, by default 4.0
276
+ b_epi_rv : float, optional
277
+ Dilation of rv epi ellipsoid in the y-direction, by default 2.5
278
+ c_epi_rv : float, optional
279
+ Dilation of rv epi ellipsoid in the z-direction, by default 2.0
280
+ create_fibers : bool, optional
281
+ If True create analytic fibers, by default False
282
+ fiber_angle_endo : float, optional
283
+ Angle for the endocardium, by default -60
284
+ fiber_angle_epi : float, optional
285
+ Angle for the epicardium, by default +60
286
+ fiber_space : str, optional
287
+ Function space for fibers of the form family_degree, by default "P_1"
288
+
289
+ Returns
290
+ -------
291
+ Geometry
292
+ A Geometry with the mesh, markers, markers functions and fibers.
293
+
294
+ """
295
+ comm = MPI.COMM_WORLD
296
+ outdir = Path(outdir)
297
+ mesh_name = outdir / "biv_ellipsoid_torso.msh"
298
+ if comm.rank == 0:
299
+ outdir.mkdir(exist_ok=True, parents=True)
300
+
301
+ with open(outdir / "info.json", "w") as f:
302
+ json.dump(
303
+ {
304
+ "char_length": char_length,
305
+ "heart_as_surface": heart_as_surface,
306
+ "torso_length": torso_length,
307
+ "torso_width": torso_width,
308
+ "torso_height": torso_height,
309
+ "rotation_angle": rotation_angle,
310
+ "center_lv_x": center_lv_x,
311
+ "center_lv_y": center_lv_y,
312
+ "center_lv_z": center_lv_z,
313
+ "a_endo_lv": a_endo_lv,
314
+ "b_endo_lv": b_endo_lv,
315
+ "c_endo_lv": c_endo_lv,
316
+ "a_epi_lv": a_epi_lv,
317
+ "b_epi_lv": b_epi_lv,
318
+ "c_epi_lv": c_epi_lv,
319
+ "center_rv_x": center_rv_x,
320
+ "center_rv_y": center_rv_y,
321
+ "center_rv_z": center_rv_z,
322
+ "a_endo_rv": a_endo_rv,
323
+ "b_endo_rv": b_endo_rv,
324
+ "c_endo_rv": c_endo_rv,
325
+ "a_epi_rv": a_epi_rv,
326
+ "b_epi_rv": b_epi_rv,
327
+ "c_epi_rv": c_epi_rv,
328
+ "create_fibers": create_fibers,
329
+ "fibers_angle_endo": fiber_angle_endo,
330
+ "fibers_angle_epi": fiber_angle_epi,
331
+ "fiber_space": fiber_space,
332
+ # "mesh_type": MeshTypes.biv_ellipsoid.value,
333
+ "cardiac_geometry_version": __version__,
334
+ "timestamp": datetime.datetime.now().isoformat(),
335
+ },
336
+ f,
337
+ indent=2,
338
+ default=utils.json_serial,
339
+ )
340
+
341
+ cgc.biv_ellipsoid_torso(
342
+ mesh_name=mesh_name.as_posix(),
343
+ char_length=char_length,
344
+ heart_as_surface=heart_as_surface,
345
+ torso_length=torso_length,
346
+ torso_height=torso_height,
347
+ torso_width=torso_width,
348
+ rotation_angle=rotation_angle,
349
+ center_lv_x=center_lv_x,
350
+ center_lv_y=center_lv_y,
351
+ center_lv_z=center_lv_z,
352
+ a_endo_lv=a_endo_lv,
353
+ b_endo_lv=b_endo_lv,
354
+ c_endo_lv=c_endo_lv,
355
+ a_epi_lv=a_epi_lv,
356
+ b_epi_lv=b_epi_lv,
357
+ c_epi_lv=c_epi_lv,
358
+ center_rv_x=center_rv_x,
359
+ center_rv_y=center_rv_y,
360
+ center_rv_z=center_rv_z,
361
+ a_endo_rv=a_endo_rv,
362
+ b_endo_rv=b_endo_rv,
363
+ c_endo_rv=c_endo_rv,
364
+ a_epi_rv=a_epi_rv,
365
+ b_epi_rv=b_epi_rv,
366
+ c_epi_rv=c_epi_rv,
367
+ )
368
+ comm.barrier()
369
+
370
+ geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name, unlink=False)
371
+
372
+ if comm.rank == 0:
373
+ with open(outdir / "markers.json", "w") as f:
374
+ json.dump(geometry.markers, f, default=utils.json_serial)
375
+ comm.barrier()
376
+
377
+ if create_fibers:
378
+ if heart_as_surface:
379
+ logger.warning("Can only create fibers when heart is a volume.")
380
+ else:
381
+ raise NotImplementedError("Fibers not implemented yet for biv ellipsoid.")
382
+ # from .fibers._biv_ellipsoid import create_biv_in_torso_fibers
383
+
384
+ # create_biv_in_torso_fibers(
385
+ # mesh=geometry.mesh,
386
+ # ffun=geometry.marker_functions.ffun,
387
+ # cfun=geometry.marker_functions.cfun,
388
+ # markers=geometry.markers,
389
+ # fiber_space=fiber_space,
390
+ # alpha_endo=fiber_angle_endo,
391
+ # alpha_epi=fiber_angle_epi,
392
+ # outdir=outdir,
393
+ # )
394
+
395
+ geo = Geometry.from_folder(comm=comm, folder=outdir)
396
+ return geo
397
+
398
+
399
+ def lv_ellipsoid(
400
+ outdir: Path | str,
401
+ r_short_endo: float = 7.0,
402
+ r_short_epi: float = 10.0,
403
+ r_long_endo: float = 17.0,
404
+ r_long_epi: float = 20.0,
405
+ psize_ref: float = 3,
406
+ mu_apex_endo: float = -math.pi,
407
+ mu_base_endo: float = -math.acos(5 / 17),
408
+ mu_apex_epi: float = -math.pi,
409
+ mu_base_epi: float = -math.acos(5 / 20),
410
+ create_fibers: bool = False,
411
+ fiber_angle_endo: float = -60,
412
+ fiber_angle_epi: float = +60,
413
+ fiber_space: str = "P_1",
414
+ aha: bool = True,
415
+ ) -> Geometry:
416
+ """Create an LV ellipsoidal geometry
417
+
418
+ Parameters
419
+ ----------
420
+ outdir : Optional[Path], optional
421
+ Directory where to save the results.
422
+ r_short_endo : float, optional
423
+ Shortest radius on the endocardium layer, by default 7.0
424
+ r_short_epi : float, optional
425
+ Shortest radius on the epicardium layer, by default 10.0
426
+ r_long_endo : float, optional
427
+ Longest radius on the endocardium layer, by default 17.0
428
+ r_long_epi : float, optional
429
+ Longest radius on the epicardium layer, by default 20.0
430
+ psize_ref : float, optional
431
+ The reference point size (smaller values yield as finer mesh, by default 3
432
+ mu_apex_endo : float, optional
433
+ Angle for the endocardial apex, by default -math.pi
434
+ mu_base_endo : float, optional
435
+ Angle for the endocardial base, by default -math.acos(5 / 17)
436
+ mu_apex_epi : float, optional
437
+ Angle for the epicardial apex, by default -math.pi
438
+ mu_base_epi : float, optional
439
+ Angle for the epicardial apex, by default -math.acos(5 / 20)
440
+ create_fibers : bool, optional
441
+ If True create analytic fibers, by default False
442
+ fiber_angle_endo : float, optional
443
+ Angle for the endocardium, by default -60
444
+ fiber_angle_epi : float, optional
445
+ Angle for the epicardium, by default +60
446
+ fiber_space : str, optional
447
+ Function space for fibers of the form family_degree, by default "P_1"
448
+ aha : bool, optional
449
+ If True create 17-segment AHA regions
450
+
451
+ Returns
452
+ -------
453
+ Geometry
454
+ A Geometry with the mesh, markers, markers functions and fibers.
455
+
456
+ """
457
+ comm = MPI.COMM_WORLD
458
+ outdir = Path(outdir)
459
+ mesh_name = outdir / "lv_ellipsoid.msh"
460
+ if comm.rank == 0:
461
+ outdir.mkdir(exist_ok=True, parents=True)
462
+
463
+ with open(outdir / "info.json", "w") as f:
464
+ json.dump(
465
+ {
466
+ "r_short_endo": r_short_endo,
467
+ "r_short_epi": r_short_epi,
468
+ "r_long_endo": r_long_endo,
469
+ "r_long_epi": r_long_epi,
470
+ "psize_ref": psize_ref,
471
+ "mu_apex_endo": mu_apex_endo,
472
+ "mu_base_endo": mu_base_endo,
473
+ "mu_apex_epi": mu_apex_epi,
474
+ "mu_base_epi": mu_base_epi,
475
+ "create_fibers": create_fibers,
476
+ "fibers_angle_endo": fiber_angle_endo,
477
+ "fibers_angle_epi": fiber_angle_epi,
478
+ "fiber_space": fiber_space,
479
+ "aha": aha,
480
+ # "mesh_type": MeshTypes.lv_ellipsoid.value,
481
+ "cardiac_geometry_version": __version__,
482
+ "timestamp": datetime.datetime.now().isoformat(),
483
+ },
484
+ f,
485
+ indent=2,
486
+ default=utils.json_serial,
487
+ )
488
+
489
+ cgc.lv_ellipsoid(
490
+ mesh_name=mesh_name.as_posix(),
491
+ r_short_endo=r_short_endo,
492
+ r_short_epi=r_short_epi,
493
+ r_long_endo=r_long_endo,
494
+ r_long_epi=r_long_epi,
495
+ mu_base_endo=mu_base_endo,
496
+ mu_base_epi=mu_base_epi,
497
+ mu_apex_endo=mu_apex_endo,
498
+ mu_apex_epi=mu_apex_epi,
499
+ psize_ref=psize_ref,
500
+ )
501
+ comm.barrier()
502
+
503
+ geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name, unlink=False)
504
+
505
+ # if aha:
506
+ # from .aha import lv_aha
507
+
508
+ # geometry = lv_aha(
509
+ # geometry=geometry,
510
+ # r_long_endo=r_long_endo,
511
+ # r_short_endo=r_short_endo,
512
+ # mu_base=mu_base_endo,
513
+ # )
514
+ # from dolfin import XDMFFile
515
+
516
+ # with XDMFFile((outdir / "cfun.xdmf").as_posix()) as xdmf:
517
+ # xdmf.write(geometry.marker_functions.cfun)
518
+
519
+ if comm.rank == 0:
520
+ with open(outdir / "markers.json", "w") as f:
521
+ json.dump(geometry.markers, f, default=utils.json_serial)
522
+
523
+ if create_fibers:
524
+ from .fibers.lv_ellipsoid import create_microstructure
525
+
526
+ create_microstructure(
527
+ mesh=geometry.mesh,
528
+ ffun=geometry.ffun,
529
+ markers=geometry.markers,
530
+ function_space=fiber_space,
531
+ r_short_endo=r_short_endo,
532
+ r_short_epi=r_short_epi,
533
+ r_long_endo=r_long_endo,
534
+ r_long_epi=r_long_epi,
535
+ alpha_endo=fiber_angle_endo,
536
+ alpha_epi=fiber_angle_epi,
537
+ outdir=outdir,
538
+ )
539
+
540
+ geo = Geometry.from_folder(comm=comm, folder=outdir)
541
+ # if aha:
542
+ # # Update schema
543
+ # from .geometry import H5Path
544
+
545
+ # cfun = geo.schema["cfun"].to_dict()
546
+ # cfun["fname"] = "cfun.xdmf:f"
547
+ # geo.schema["cfun"] = H5Path(**cfun)
548
+
549
+ return geo
550
+
551
+
552
+ def slab(
553
+ outdir: Path | str,
554
+ lx: float = 20.0,
555
+ ly: float = 7.0,
556
+ lz: float = 3.0,
557
+ dx: float = 1.0,
558
+ create_fibers: bool = True,
559
+ fiber_angle_endo: float = -60,
560
+ fiber_angle_epi: float = +60,
561
+ fiber_space: str = "P_1",
562
+ ) -> Geometry:
563
+ """Create slab geometry
564
+
565
+ Parameters
566
+ ----------
567
+ outdir : Optional[Path], optional
568
+ Directory where to save the results.
569
+ lx : float, optional
570
+ Length of slab the x-direction, by default 20.0
571
+ ly : float, optional
572
+ Length of slab the x-direction, by default 7.0
573
+ lz : float, optional
574
+ Length of slab the z-direction, by default 3.0
575
+ dx : float, optional
576
+ Element size, by default 1.0
577
+ create_fibers : bool, optional
578
+ If True create analytic fibers, by default True
579
+ fiber_angle_endo : float, optional
580
+ Angle for the endocardium, by default -60
581
+ fiber_angle_epi : float, optional
582
+ Angle for the epicardium, by default +60
583
+ fiber_space : str, optional
584
+ Function space for fibers of the form family_degree, by default "P_1"
585
+
586
+ Returns
587
+ -------
588
+ Geometry
589
+ A Geometry with the mesh, markers, markers functions and fibers.
590
+
591
+ """
592
+ comm = MPI.COMM_WORLD
593
+ outdir = Path(outdir)
594
+ mesh_name = outdir / "slab.msh"
595
+ if comm.rank == 0:
596
+ outdir.mkdir(exist_ok=True, parents=True)
597
+
598
+ with open(outdir / "info.json", "w") as f:
599
+ json.dump(
600
+ {
601
+ "lx": lx,
602
+ "ly": ly,
603
+ "lz": lz,
604
+ "dx": dx,
605
+ "create_fibers": create_fibers,
606
+ "fibers_angle_endo": fiber_angle_endo,
607
+ "fibers_angle_epi": fiber_angle_epi,
608
+ "fiber_space": fiber_space,
609
+ # "mesh_type": MeshTypes.slab.value,
610
+ "cardiac_geometry_version": __version__,
611
+ "timestamp": datetime.datetime.now().isoformat(),
612
+ },
613
+ f,
614
+ indent=2,
615
+ default=utils.json_serial,
616
+ )
617
+
618
+ cgc.slab(mesh_name=mesh_name.as_posix(), lx=lx, ly=ly, lz=lz, dx=dx)
619
+ comm.barrier()
620
+
621
+ geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name, unlink=False)
622
+
623
+ if comm.rank == 0:
624
+ with open(outdir / "markers.json", "w") as f:
625
+ json.dump(geometry.markers, f, default=utils.json_serial)
626
+
627
+ if create_fibers:
628
+ from .fibers.slab import create_microstructure
629
+
630
+ create_microstructure(
631
+ mesh=geometry.mesh,
632
+ ffun=geometry.ffun,
633
+ markers=geometry.markers,
634
+ function_space=fiber_space,
635
+ alpha_endo=fiber_angle_endo,
636
+ alpha_epi=fiber_angle_epi,
637
+ outdir=outdir,
638
+ )
639
+
640
+ geo = Geometry.from_folder(comm=comm, folder=outdir)
641
+
642
+ return geo
643
+
644
+
645
+ def slab_in_bath(
646
+ outdir: Path | str,
647
+ lx: float = 1.0,
648
+ ly: float = 0.01,
649
+ lz: float = 0.5,
650
+ bx: float = 0.0,
651
+ by: float = 0.0,
652
+ bz: float = 0.1,
653
+ dx: float = 0.001,
654
+ ) -> Geometry:
655
+ """Create slab geometry
656
+
657
+ Parameters
658
+ ----------
659
+ outdir : Path
660
+ Directory where to save the results.
661
+ lx : float, optional
662
+ Length of slab the x-direction, by default 1.0
663
+ ly : float, optional
664
+ Length of slab the x-direction, by default 0.5
665
+ lz : float, optional
666
+ Length of slab the z-direction, by default 0.01
667
+ bx : float, optional
668
+ Thickness of bath the x-direction, by default 0.0
669
+ by : float, optional
670
+ Thickness of bath the x-direction, by default 0.0
671
+ bz : float, optional
672
+ Thickness of bath the z-direction, by default 0.1
673
+ dx : float, optional
674
+ Element size, by default 0.001
675
+
676
+ Returns
677
+ -------
678
+ Geometry
679
+ A Geometry with the mesh, markers, markers functions and fibers.
680
+
681
+ """
682
+ comm = MPI.COMM_WORLD
683
+
684
+ outdir = Path(outdir)
685
+ mesh_name = outdir / "slab_in_bath.msh"
686
+ if comm.rank == 0:
687
+ outdir.mkdir(exist_ok=True, parents=True)
688
+
689
+ with open(outdir / "info.json", "w") as f:
690
+ json.dump(
691
+ {
692
+ "lx": lx,
693
+ "ly": ly,
694
+ "lz": lz,
695
+ "bx": bx,
696
+ "by": by,
697
+ "bz": bz,
698
+ "dx": dx,
699
+ # "mesh_type": MeshTypes.slab.value,
700
+ "cardiac_geometry_version": __version__,
701
+ "timestamp": datetime.datetime.now().isoformat(),
702
+ },
703
+ f,
704
+ indent=2,
705
+ default=utils.json_serial,
706
+ )
707
+
708
+ cgc.slab_in_bath(
709
+ mesh_name=mesh_name.as_posix(),
710
+ lx=lx,
711
+ ly=ly,
712
+ lz=lz,
713
+ bx=bx,
714
+ by=by,
715
+ bz=bz,
716
+ dx=dx,
717
+ )
718
+
719
+ geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name, unlink=False)
720
+
721
+ if comm.rank == 0:
722
+ with open(outdir / "markers.json", "w") as f:
723
+ json.dump(geometry.markers, f, default=utils.json_serial)
724
+
725
+ geo = Geometry.from_folder(comm=comm, folder=outdir)
726
+
727
+ return geo