Source code for cardiac_geometries.fibers.slab

from pathlib import Path

import dolfinx
import numpy as np

from ..utils import space_from_string
from . import utils


[docs] def compute_system( t_func: dolfinx.fem.Function, alpha_endo: float = -60, alpha_epi: float = 60, endo_epi_axis="y", ) -> utils.Microstructure: """Compute ldrb system for slab, assuming linear angle between endo and epi Parameters ---------- t_func : dolfin.Function Solution to laplace equation with 0 on endo and 1 on epi alpha_endo : float, optional Angle on endocardium, by default -60 alpha_epi : float, optional Angle on epicardium, by default 60 Returns ------- Microstructure Tuple with fiber, sheet and sheet normal """ V = t_func.function_space element = V.ufl_element() mesh = V.mesh alpha = lambda x: (alpha_endo + (alpha_epi - alpha_endo) * x) * (np.pi / 180) t = t_func.x.array if endo_epi_axis == "y": f0 = np.array( [ np.cos(alpha(t)), np.zeros_like(t), np.sin(alpha(t)), ], ) n0 = np.array( [ np.zeros_like(t), np.ones_like(t), np.zeros_like(t), ], ) elif endo_epi_axis == "z": f0 = np.array( [ np.cos(alpha(t)), np.sin(alpha(t)), np.zeros_like(t), ], ) n0 = np.array( [ np.zeros_like(t), np.zeros_like(t), np.ones_like(t), ], ) elif endo_epi_axis == "x": f0 = np.array( [ np.zeros_like(t), np.cos(alpha(t)), np.sin(alpha(t)), ], ) n0 = np.array( [ np.ones_like(t), np.zeros_like(t), np.zeros_like(t), ], ) else: raise ValueError(f"Unknown endo_epi_axis: {endo_epi_axis}") s0 = np.cross(f0, n0, axis=0) s0 = utils.normalize(s0) Vv = space_from_string( space_string=f"{element.family_name}_{element.degree}", mesh=mesh, dim=mesh.geometry.dim, discontinuous=element.discontinuous, ) fiber = dolfinx.fem.Function(Vv) norm_f = np.linalg.norm(f0, axis=0) fiber.x.array[:] = (f0 / norm_f).T.reshape(-1) fiber.name = "f0" sheet = dolfinx.fem.Function(Vv) sheet.x.array[:] = s0.T.reshape(-1) sheet.name = "s0" sheet_normal = dolfinx.fem.Function(Vv) sheet_normal.x.array[:] = n0.T.reshape(-1) sheet_normal.name = "n0" return utils.Microstructure(f0=fiber, s0=sheet, n0=sheet_normal)
[docs] def create_microstructure( mesh: dolfinx.mesh.Mesh, ffun: dolfinx.mesh.MeshTags, markers: dict[str, tuple[int, int]], alpha_endo: float, alpha_epi: float, function_space: str = "P_1", outdir: str | Path | None = None, **kwargs: dict, ) -> utils.Microstructure: """Generate microstructure for slab using LDRB algorithm Parameters ---------- mesh : dolfinx.mesh.Mesh A slab mesh ffun : dolfinx.mesh.MeshTags Facet function defining the boundaries markers: Dict[str, Tuple[int, int]] Markers with keys Y0 and Y1 representing the endo and epi planes respectively. The values should be a tuple whose first value is the value of the marker (corresponding to ffun) and the second value is the dimension alpha_endo : float Angle on the endocardium alpha_epi : float Angle on the epicardium function_space : str Function space to interpolate the fibers, by default P_1 outdir : Optional[Union[str, Path]], optional Output directory to store the results, by default None. If no output directory is specified the results will not be stored, but only returned. Returns ------- Microstructure Tuple with fiber, sheet and sheet normal """ endo_marker = markers["Y0"][0] epi_marker = markers["Y1"][0] t = utils.laplace( mesh, ffun, endo_marker=endo_marker, epi_marker=epi_marker, function_space=function_space, ) if outdir is not None: try: with dolfinx.io.VTXWriter( mesh.comm, Path(outdir) / "laplace.bp", [t], engine="BP4" ) as file: file.write(0.0) except RuntimeError: pass system = compute_system( t, alpha_endo=alpha_endo, alpha_epi=alpha_epi, ) if outdir is not None: utils.save_microstructure(mesh, system, outdir) return system