def test_lv_regression(lv_geometry, use_krylov_solver): ldrb.dolfin_ldrb( mesh=lv_geometry.mesh, ffun=lv_geometry.ffun, markers=lv_geometry.markers, use_krylov_solver=use_krylov_solver, )
def generate_fibers(mesh, fiber_params, ffun=None): """ Generate fibers on mesh based on provided parameters. It is not recomemmended to use this function. Use the `ldrb` package directly instead. This function is mainly used to ensure version compatability. """ try: from ldrb import dolfin_ldrb except ImportError: msg = ('"ldrb" package not found. Please go to ' "https://github.com/finsberg/ldrb to see how you can get it!") print(msg) raise ImportError(msg) if isinstance(fiber_params, dolfin.Parameters): p = fiber_params.to_dict() else: p = fiber_params angles = dict(alpha_endo_lv=p.get("fiber_angle_endo"), alpha_epi_lv=p.get("fiber_angle_epi")) for name, a in angles.items(): if isinstance(a, dolfin.cpp.parameter.Parameter): angles[name] = a.value() return dolfin_ldrb(mesh, ffun=ffun, **angles)
def create_fiber_fields(mesh, markers, ffun, angles=None, fiber_space='Quadrature_2'): if angles is None: angles = dict( alpha_endo_lv=60, # Fiber angle on the endocardium alpha_epi_lv=-60, # Fiber angle on the epicardium beta_endo_lv=0, # Sheet angle on the endocardium beta_epi_lv=0) # Sheet angle on the epicardium # Choose space for the fiber fields # This is a string on the form {family}_{degree} # fiber_space = 'Quadrature_2' # At all nodes # fiber_space = 'Lagrange_1' m = { 'lv': markers.get('ENDO')[0], 'epi': markers.get('EPI')[0], 'base': markers.get('BASE')[0], } # Compute the microstructure fiber, sheet, sheet_normal = ldrb.dolfin_ldrb(mesh=mesh, fiber_space=fiber_space, ffun=ffun, markers=m, **angles) fiber.rename("fiber", "microstructure") sheet.rename("sheet", "microstructure") sheet_normal.rename("sheet_normal", "microstructure") ldrb.fiber_to_xdmf(fiber, 'lv_fiber') return [fiber, sheet, sheet_normal]
angles = dict( alpha_endo_lv=60, # Fiber angle on the endocardium alpha_epi_lv=-60, # Fiber angle on the epicardium beta_endo_lv=0, # Sheet angle on the endocardium beta_epi_lv=0, ) # Sheet angle on the epicardium # Choose space for the fiber fields # This is a string on the form {family}_{degree} # fiber_space = 'Quadrature_2' fiber_space = "Lagrange_1" # Compte the microstructure fiber, sheet, sheet_normal = ldrb.dolfin_ldrb(mesh=mesh, fiber_space=fiber_space, ffun=ffun, markers=markers, **angles) # fiber.rename('fiber', 'fibers') # sheet.rename('sheet', 'fibers') # sheet_normal.rename('sheet_normal', 'fibers') # import pulse.geometry_utils as utils # import numpy as np # focal = np.sqrt(1.5**2 - 0.5**2) # sfun = utils.mark_strain_regions(mesh, foc=focal) # df.File('sfun.pvd') << sfun # angles['alpha_endo_lv'] = 0
def prolate_ellipsoid_geometry( r_short_endo: float = 7.0, r_short_epi: float = 10.0, r_long_endo: float = 17.0, r_long_epi: float = 20.0, quota_base: float = 0.0, psize: float = 3.0, ndiv: float = 1.0, mesh_size_factor: float = 1.0, fiber_params: typing.Optional[typing.Dict[str, typing.Any]] = None, ): fiber_params = fiber_params or {} fiber_params = fiber_params.copy() signature = hashit( repr( dict( r_short_endo=r_short_endo, r_short_epi=r_short_epi, r_long_endo=r_long_endo, r_long_epi=r_long_epi, quota_base=quota_base, psize=psize, ndiv=ndiv, mesh_size_factor=mesh_size_factor, fiber_params=fiber_params, ), ), ) path = cachedir.joinpath(f"prolate_ellipsoid_geometry_{signature}.h5") if not path.is_file(): check_ldrb() msh_name = Path("test.msh") create_benchmark_ellipsoid_mesh_gmsh( msh_name, r_short_endo=r_short_endo, r_short_epi=r_short_epi, r_long_endo=r_long_endo, r_long_epi=r_long_epi, quota_base=quota_base, psize=psize, ndiv=ndiv, mesh_size_factor=mesh_size_factor, ) geo: HeartGeometry = gmsh2dolfin(msh_name) msh_name.unlink() ldrb_markers = { "base": geo.markers["BASE"][0], "epi": geo.markers["EPI"][0], "lv": geo.markers["ENDO"][0], } fiber_space = fiber_params.pop("fiber_space", "CG_1") fiber_sheet_system = ldrb.dolfin_ldrb(geo.mesh, fiber_space, geo.ffun, ldrb_markers, **fiber_params) geo.microstructure = Microstructure( f0=fiber_sheet_system.fiber, s0=fiber_sheet_system.sheet, n0=fiber_sheet_system.sheet_normal, ) geo.save(path) return HeartGeometry.from_file(path)
# In the case of a BiV we do a little trick where me mark the RV as LV in order to find the longitudinal vector field. We run the algorithm again with some different angles to get the circumferential vector field and finally take the cross product to get the radial vector field. # (if you find a better way of doing this, please submit a PR). # if case == "biv": lv_ffun = dolfin.MeshFunction("size_t", mesh, 2) lv_ffun.array()[:] = ffun.array().copy() lv_ffun.array()[ffun.array() == markers["rv"]] = markers["lv"] lv_markers = markers.copy() lv_markers.pop("rv") long, _, _ = ldrb.dolfin_ldrb( mesh=mesh, fiber_space=space, ffun=lv_ffun, markers=lv_markers, alpha_endo_lv=-90, alpha_epi_lv=-90, beta_endo_lv=0, beta_epi_lv=0, ) circ, _, _ = ldrb.dolfin_ldrb( mesh=mesh, fiber_space=space, ffun=ffun, markers=markers, alpha_endo_lv=0, alpha_epi_lv=0, beta_endo_lv=0, beta_epi_lv=0, )
def test_ldrb_without_correct_markers_raises_RuntimeError(lv_geometry): with pytest.raises(RuntimeError): ldrb.dolfin_ldrb(mesh=lv_geometry.mesh)
def create_geometry(h5name): """ Create an lv-ellipsoidal mesh and fiber fields using LDRB algorithm An ellipsoid is given by the equation .. math:: \frac{x^2}{a} + \frac{y^2}{b} + \frac{z^2}{c} = 1 We create two ellipsoids, one for the endocardium and one for the epicardium and subtract them and then cut the base. For simplicity we assume that the longitudinal axis is in in :math:`x`-direction and as default the base is located at the :math:`x=0` plane. """ # Number of subdivision (higher -> finer mesh) N = 13 # Parameter for the endo ellipsoid a_endo = 1.5 b_endo = 0.5 c_endo = 0.5 # Parameter for the epi ellipsoid a_epi = 2.0 b_epi = 1.0 c_epi = 1.0 # Center of the ellipsoid (same of endo and epi) center = (0.0, 0.0, 0.0) # Location of the base base_x = 0.0 # Create a lv ellipsoid mesh with longitudinal axis along the x-axis geometry = ldrb.create_lv_mesh(N=N, a_endo=a_endo, b_endo=b_endo, c_endo=c_endo, a_epi=a_epi, b_epi=b_epi, c_epi=c_epi, center=center, base_x=base_x) # Select fiber angles for rule based algorithm angles = dict( alpha_endo_lv=60, # Fiber angle on the endocardium alpha_epi_lv=-60, # Fiber angle on the epicardium beta_endo_lv=0, # Sheet angle on the endocardium beta_epi_lv=0) # Sheet angle on the epicardium fiber_space = 'Lagrange_1' # Compte the microstructure fiber, sheet, sheet_normal = ldrb.dolfin_ldrb(mesh=geometry.mesh, fiber_space=fiber_space, ffun=geometry.ffun, markers=geometry.markers, **angles) # Compute focal point focal = np.sqrt(a_endo**2 - (0.5 * (b_endo + c_endo))**2) # Make mesh according to AHA-zons pulse.geometry_utils.mark_strain_regions(mesh=geometry.mesh, foc=focal) mapper = {'lv': 'ENDO', 'epi': 'EPI', 'rv': 'ENDO_RV', 'base': 'BASE'} m = {mapper[k]: (v, 2) for k, v in geometry.markers.items()} pulse.geometry_utils.save_geometry_to_h5( geometry.mesh, h5name, markers=m, fields=[fiber, sheet, sheet_normal])
def gmsh2dolfin(msh_file): msh = meshio.gmsh.read(msh_file) vertex_mesh = create_mesh(msh, "vertex") line_mesh = create_mesh(msh, "line") triangle_mesh = create_mesh(msh, "triangle") tetra_mesh = create_mesh(msh, "tetra") vertex_mesh_name = Path("vertex_mesh.xdmf") meshio.write(vertex_mesh_name, vertex_mesh) line_mesh_name = Path("line_mesh.xdmf") meshio.write(line_mesh_name, line_mesh) triangle_mesh_name = Path("triangle_mesh.xdmf") meshio.write(triangle_mesh_name, triangle_mesh) tetra_mesh_name = Path("mesh.xdmf") meshio.write( tetra_mesh_name, tetra_mesh, ) mesh = dolfin.Mesh() with dolfin.XDMFFile(tetra_mesh_name.as_posix()) as infile: infile.read(mesh) cfun = dolfin.MeshFunction("size_t", mesh, 3) read_meshfunction(tetra_mesh_name, cfun) tetra_mesh_name.unlink() tetra_mesh_name.with_suffix(".h5").unlink() ffun_val = dolfin.MeshValueCollection("size_t", mesh, 2) read_meshfunction(triangle_mesh_name, ffun_val) ffun = dolfin.MeshFunction("size_t", mesh, ffun_val) ffun.array()[ffun.array() == max(ffun.array())] = 0 triangle_mesh_name.unlink() triangle_mesh_name.with_suffix(".h5").unlink() efun_val = dolfin.MeshValueCollection("size_t", mesh, 1) read_meshfunction(line_mesh_name, efun_val) efun = dolfin.MeshFunction("size_t", mesh, efun_val) efun.array()[efun.array() == max(efun.array())] = 0 line_mesh_name.unlink() line_mesh_name.with_suffix(".h5").unlink() vfun_val = dolfin.MeshValueCollection("size_t", mesh, 0) read_meshfunction(vertex_mesh_name, vfun_val) vfun = dolfin.MeshFunction("size_t", mesh, vfun_val) vfun.array()[vfun.array() == max(vfun.array())] = 0 vertex_mesh_name.unlink() vertex_mesh_name.with_suffix(".h5").unlink() markers = msh.field_data ldrb_markers = { "base": markers["BASE"][0], "epi": markers["EPI"][0], "lv": markers["ENDO"][0], } fiber_sheet_system = ldrb.dolfin_ldrb(mesh, "CG_1", ffun, ldrb_markers) marker_functions = pulse.MarkerFunctions(vfun=vfun, efun=efun, ffun=ffun, cfun=cfun) microstructure = pulse.Microstructure( f0=fiber_sheet_system.fiber, s0=fiber_sheet_system.sheet, n0=fiber_sheet_system.sheet_normal, ) geo = pulse.HeartGeometry( mesh=mesh, markers=markers, marker_functions=marker_functions, microstructure=microstructure, ) return geo
beta_endo_sept=0, # Sheet angle on the Septum endocardium beta_epi_sept=0, # Sheet angle on the Septum epicardium alpha_endo_rv=80, # Fiber angle on the RV endocardium alpha_epi_rv=-80, # Fiber angle on the RV epicardium beta_endo_rv=0, # Sheet angle on the RV endocardium beta_epi_rv=0) # Sheet angle on the RV epicardium # Choose space for the fiber fields. # This is a string on the form {family}_{degree} fiber_space = 'Quadrature_2' # fiber_space = 'Lagrange_1' # Compute the microstructure fiber, sheet, sheet_normal = ldrb.dolfin_ldrb(mesh=mesh, fiber_space=fiber_space, ffun=ffun, markers=markers, log_level=df.debug, **angles) # # Store the results df.File('biv_fiber.xml') << fiber df.File('biv_sheet.xml') << sheet df.File('biv_sheet_normal.xml') << sheet_normal # If you run in paralell you should skip the visualization step and do that in # serial in stead. In that case you can read the the functions from the xml # Using the following code # V = ldrb.space_from_string(fiber_space, mesh, dim=3) # fiber = df.Function(V, 'biv_fiber.xml') # sheet = df.Function(V, 'biv_sheet.xml') # sheet_normal = df.Function(V, 'biv_sheet_normal.xml')
ldrb_markers = { "epi": markers["Epicardium"][0], "lv": markers["Endocardium"][0], "base": markers["Basal plane"][0], } # Select linear langange elements fiber_space = "P_1" # Compute the fiber-sheet system fiber, sheet, sheet_normal = ldrb.dolfin_ldrb( mesh=mesh, fiber_space=fiber_space, ffun=ffun, markers=ldrb_markers, alpha_endo_lv=60, # Fiber angle on the endocardium alpha_epi_lv=-60, # Fiber angle on the epicardium beta_endo_lv=0, # Sheet angle on the endocardium beta_epi_lv=0, # Sheet angle on the epicardium ) # And save the results with dolfin.XDMFFile(mesh.mpi_comm(), "idealized_LV_fiber.xdmf") as xdmf: xdmf.write(fiber) # ![_](_static/figures/idealized_LV_fiber.png)
xdmf.read(ffun) # Choose space for the fiber fields # This is a string on the form {family}_{degree} fiber_space = "Lagrange_2" # Compute the microstructure fiber, sheet, sheet_normal = ldrb.dolfin_ldrb( mesh=mesh, fiber_space=fiber_space, ffun=ffun, markers=markers, alpha_endo_lv=30, # Fiber angle on the LV endocardium alpha_epi_lv=-30, # Fiber angle on the LV epicardium beta_endo_lv=0, # Sheet angle on the LV endocardium beta_epi_lv=0, # Sheet angle on the LV epicardium alpha_endo_sept=60, # Fiber angle on the Septum endocardium alpha_epi_sept=-60, # Fiber angle on the Septum epicardium beta_endo_sept=0, # Sheet angle on the Septum endocardium beta_epi_sept=0, # Sheet angle on the Septum epicardium alpha_endo_rv=80, # Fiber angle on the RV endocardium alpha_epi_rv=-80, # Fiber angle on the RV epicardium beta_endo_rv=0, # Sheet angle on the RV endocardium beta_epi_rv=0, ) # Store the results with df.HDF5File(mesh.mpi_comm(), "biv.h5", "w") as h5file: h5file.write(fiber, "/fiber") h5file.write(sheet, "/sheet") h5file.write(sheet_normal, "/sheet_normal")
def test_markers(lv_mesh): markers = dict(base=10, lv=30, epi=40) system = ldrb.dolfin_ldrb(lv_mesh, 'Lagrange_1', markers=markers)
def test_lv_regression(lv_mesh, fiber_space): system = ldrb.dolfin_ldrb(lv_mesh, fiber_space)