Source code for cardiac_geometries.fibers.utils

import json
import shutil
from pathlib import Path
from typing import NamedTuple, Sequence

import adios4dolfinx
import dolfinx
import numpy as np
import ufl
from dolfinx.fem.petsc import LinearProblem
from packaging.version import Version

from ..utils import space_from_string

_dolfinx_version = Version(dolfinx.__version__)


[docs] class Microstructure(NamedTuple): f0: dolfinx.fem.Function s0: dolfinx.fem.Function n0: dolfinx.fem.Function
def save_microstructure( mesh: dolfinx.mesh.Mesh, functions: Sequence[dolfinx.fem.Function], outdir: str | Path ) -> None: from ..utils import element2array if len(functions) == 0: return # Save for paraview visualization if functions[0].function_space.ufl_element().family_name == "quadrature": from scifem.xdmf import XDMFFile fname = Path(outdir) / "microstructure-viz.xdmf" fname.unlink(missing_ok=True) fname.with_suffix(".h5").unlink(missing_ok=True) with XDMFFile(fname, functions) as xdmf: xdmf.write(0.0) else: fname = Path(outdir) / "microstructure-viz.bp" shutil.rmtree(fname, ignore_errors=True) try: with dolfinx.io.VTXWriter(mesh.comm, fname, functions, engine="BP4") as file: file.write(0.0) except RuntimeError as ex: print(f"Failed to write microstructure: {ex}") # Save with proper function space filename = Path(outdir) / "microstructure.bp" shutil.rmtree(filename, ignore_errors=True) for function in functions: adios4dolfinx.write_function(u=function, filename=filename) attributes = {f.name: element2array(f.ufl_element()) for f in functions} adios4dolfinx.write_attributes( comm=mesh.comm, filename=filename, name="function_space", attributes=attributes, ) def json_serial(obj): if isinstance(obj, (np.ndarray)): return obj.tolist() raise TypeError("Type %s not serializable" % type(obj)) if mesh.comm.rank == 0: (Path(outdir) / "microstructure.json").write_text( json.dumps(attributes, indent=4, default=json_serial) ) def normalize(u): return u / np.linalg.norm(u, axis=0) def laplace( mesh: dolfinx.mesh.Mesh, ffun: dolfinx.mesh.MeshTags, endo_marker: int, epi_marker: int, function_space: str, ): V = dolfinx.fem.functionspace(mesh, ("Lagrange", 1)) u = ufl.TrialFunction(V) v = ufl.TestFunction(V) a = ufl.dot(ufl.grad(u), ufl.grad(v)) * ufl.dx L = v * dolfinx.fem.Constant(mesh, dolfinx.default_scalar_type(0.0)) * ufl.dx endo_facets = ffun.find(endo_marker) endo_dofs = dolfinx.fem.locate_dofs_topological(V, 2, endo_facets) epi_facets = ffun.find(epi_marker) epi_dofs = dolfinx.fem.locate_dofs_topological(V, 2, epi_facets) zero = dolfinx.fem.Constant(mesh, dolfinx.default_scalar_type(0.0)) one = dolfinx.fem.Constant(mesh, dolfinx.default_scalar_type(1.0)) endo_bc = dolfinx.fem.dirichletbc(zero, endo_dofs, V) epi_bc = dolfinx.fem.dirichletbc(one, epi_dofs, V) bcs = [endo_bc, epi_bc] kwargs = {} if _dolfinx_version >= Version("0.10"): kwargs["petsc_options_prefix"] = "cardiac_geometriesx_laplace" problem = LinearProblem( a, L, bcs=bcs, petsc_options={"ksp_type": "preonly", "pc_type": "lu"}, **kwargs ) uh = problem.solve() if function_space != "P_1": W = space_from_string(function_space, mesh, dim=1) t = dolfinx.fem.Function(W) if _dolfinx_version >= Version("0.10"): points = W.element.interpolation_points else: points = W.element.interpolation_points() expr = dolfinx.fem.Expression(uh, points) t.interpolate(expr) else: t = uh return t