Example #1
0
def setup_material(material_model):
    """
    Choose parameters based on

    Hadjicharalambous, Myrianthi, et al. "Analysis of passive
    cardiac constitutive laws for parameter estimation using 3D
    tagged MRI." Biomechanics and modeling in mechanobiology 14.4
    (2015): 807-828.

    These parameters did not really match the Klotz curve here.
    Perhaps they did some more tuning?

    """
    if material_model == "guccione":

        matparams = pulse.Guccione.default_parameters()
        matparams["C"] = 0.18  # kPa
        matparams["bf"] = 27.75
        matparams["bt"] = 5.37
        matparams["bfs"] = 2.445
        material = pulse.Guccione(
            parameters=matparams,
            f0=geometry.f0,
            s0=geometry.s0,
            n0=geometry.n0,
        )

    elif material_model == "neo_hookean":

        matparams = pulse.NeoHookean.default_parameters()
        matparams["mu"] = 10.0  # kPa
        material = pulse.NeoHookean(parameters=matparams)

    elif material_model == "holzapfel_ogden":

        matparams = pulse.HolzapfelOgden.default_parameters()

        matparams["a"] = 4.0  # kPa
        matparams["a_f"] = 10.0  # kPa
        matparams["b"] = 5.0
        matparams["b_f"] = 5.0
        material = pulse.HolzapfelOgden(
            parameters=matparams,
            f0=geometry.f0,
            s0=geometry.s0,
            n0=geometry.n0,
        )
    return material
Example #2
0
behaviour. Proc. R. Soc. A. 2015 Dec 8;471(2184):20150641.
"""
import matplotlib.pyplot as plt
import dolfin
import pulse

geometry = pulse.HeartGeometry.from_file(pulse.mesh_paths['benchmark'])

# Create the material
material_parameters = pulse.Guccione.default_parameters()
material_parameters['CC'] = 10.0
material_parameters['bf'] = 1.0
material_parameters['bfs'] = 1.0
material_parameters['bt'] = 1.0

material = pulse.Guccione(params=material_parameters)


# Define Dirichlet boundary. Fix the base_spring
def dirichlet_bc(W):
    V = W if W.sub(0).num_sub_spaces() == 0 else W.sub(0)
    return dolfin.DirichletBC(V, dolfin.Constant((0.0, 0.0, 0.0)),
                              geometry.ffun, geometry.markers['BASE'][0])


# Traction at the bottom of the beam
lvp = dolfin.Constant(0.0)
neumann_bc = pulse.NeumannBC(traction=lvp, marker=geometry.markers['ENDO'][0])

# Collect Boundary Conditions
bcs = pulse.BoundaryConditions(dirichlet=(dirichlet_bc, ),
Example #3
0
import matplotlib.pyplot as plt
import dolfin
import pulse

from problem import Problem
from force import ca_transient

# pulse.parameters['log_level'] = dolfin.WARNING

geometry = pulse.HeartGeometry.from_file(pulse.mesh_paths['simple_ellipsoid'])
# Scale mesh to fit Windkessel parameters
geometry.mesh.coordinates()[:] *= 2.4

activation = dolfin.Constant(0.0)
matparams = pulse.Guccione.default_parameters()
material = pulse.Guccione(activation=activation,
                          parameters=matparams)


# Add spring term at the base with stiffness 1.0 kPa/cm^2
base_spring = 1.0
robin_bc = [pulse.RobinBC(value=dolfin.Constant(base_spring),
                          marker=geometry.markers["BASE"][0])]


# Fix the basal plane in the longitudinal direction
# 0 in V.sub(0) refers to x-direction, which is the longitudinal direction
def fix_basal_plane(W):
    V = W if W.sub(0).num_sub_spaces() == 0 else W.sub(0)
    bc = dolfin.DirichletBC(V.sub(0),
                            dolfin.Constant(0.0),
                            geometry.ffun, geometry.markers["BASE"][0])
Example #4
0
from fenics_plotly import plot

geometry = pulse.HeartGeometry.from_file(pulse.mesh_paths["benchmark"])
# geometry = pulse.geometries.benchmark_ellipsoid_geometry()

# Create the material
material_parameters = pulse.Guccione.default_parameters()
material_parameters["CC"] = 2.0
material_parameters["bf"] = 8.0
material_parameters["bfs"] = 4.0
material_parameters["bt"] = 2.0

activation = Constant(0.0)
material = pulse.Guccione(
    parameters=material_parameters,
    active_model=pulse.ActiveModels.active_stress,
    activation=activation,
)


# Define Dirichlet boundary. Fix the base_spring
def dirichlet_bc(W):
    V = W if W.sub(0).num_sub_spaces() == 0 else W.sub(0)
    return DirichletBC(
        V,
        Constant((0.0, 0.0, 0.0)),
        geometry.ffun,
        geometry.markers["BASE"][0],
    )

Example #5
0
def solve(
    geometry,
    EDP=1.0,
    ESP=15.0,
    Ta=60,
    material_parameters=None,
):
    """

    Arguments
    ---------
    EDP : float
        End diastolic pressure
    ESP : float
        End systolic pressure
    Ta : float
        Peak active tension (at ES)
    material_parameters : dict
        A dictionart with parameter in the Guccione model.
        Default:  {'C': 2.0, 'bf': 8.0, 'bt': 2.0, 'bfs': 4.0}
    filename : str
        Filname where to store the results

    """
    # Create model
    activation = df.Function(df.FunctionSpace(geometry.mesh, "R", 0))
    matparams = pulse.Guccione.default_parameters()
    if material_parameters is not None:
        matparams.update(material_parameters)
    material = pulse.Guccione(activation=activation,
                              parameters=matparams,
                              active_model="active_stress",
                              f0=geometry.f0,
                              s0=geometry.s0,
                              n0=geometry.n0)

    lvp = df.Constant(0.0)
    lv_marker = geometry.markers['ENDO'][0]
    lv_pressure = pulse.NeumannBC(traction=lvp, marker=lv_marker, name='lv')
    neumann_bc = [lv_pressure]

    # Add spring term at the base with stiffness 1.0 kPa/cm^2
    base_spring = 1.0
    robin_bc = [
        pulse.RobinBC(value=df.Constant(base_spring),
                      marker=geometry.markers["BASE"][0])
    ]

    # Fix the basal plane in the longitudinal direction
    # 0 in V.sub(0) refers to x-direction, which is the longitudinal direction
    def fix_basal_plane(W):
        V = W if W.sub(0).num_sub_spaces() == 0 else W.sub(0)
        bc = df.DirichletBC(V.sub(0), df.Constant(0.0), geometry.ffun,
                            geometry.markers["BASE"][0])
        return bc

    dirichlet_bc = [fix_basal_plane]

    # Collect boundary conditions
    bcs = pulse.BoundaryConditions(dirichlet=dirichlet_bc,
                                   neumann=neumann_bc,
                                   robin=robin_bc)

    # Create the problem
    problem = pulse.MechanicsProblem(geometry, material, bcs)

    xdmf = df.XDMFFile(df.mpi_comm_world(), 'output.xdmf')

    # Solve the problem
    print(("Do an initial solve with pressure = 0 kPa "
           "and active tension = 0 kPa"))
    problem.solve()
    u, p = problem.state.split()
    xdmf.write(u, 0.0)
    print("LV cavity volume = {} ml".format(geometry.cavity_volume(u=u)))

    # Solve for ED
    print(("Solver for ED with pressure = {} kPa and active tension = 0 kPa"
           "".format(EDP)))
    pulse.iterate.iterate(problem, lvp, EDP, initial_number_of_steps=20)

    u, p = problem.state.split(deepcopy=True)
    xdmf.write(u, 1.0)
    df.File("ED_displacement.xml") << u
    print("LV cavity volume = {} ml".format(geometry.cavity_volume(u=u)))

    # Solve for ES
    print(("Solver for ES with pressure = {} kPa and active tension = {} kPa"
           "".format(ESP, Ta)))
    pulse.iterate.iterate(problem, lvp, ESP, initial_number_of_steps=50)
    pulse.iterate.iterate(problem,
                          activation,
                          Ta,
                          adapt_step=False,
                          max_iters=100,
                          initial_number_of_steps=40)

    u, p = problem.state.split(deepcopy=True)
    xdmf.write(u, 2.0)
    df.File("ES_displacement.xml") << u
    print("LV cavity volume = {} ml".format(geometry.cavity_volume(u=u)))
Example #6
0
import dolfin
import pulse


geometry = pulse.HeartGeometry.from_file(pulse.mesh_paths['benchmark'])

# Create the material
material_parameters = pulse.Guccione.default_parameters()
material_parameters['CC'] = 2.0
material_parameters['bf'] = 8.0
material_parameters['bfs'] = 4.0
material_parameters['bt'] = 2.0

activation = dolfin.Constant(0.0)
material = pulse.Guccione(params=material_parameters,
                          active_model='active_stress',
                          activation=activation)


# Define Dirichlet boundary. Fix the base_spring
def dirichlet_bc(W):
    V = W if W.sub(0).num_sub_spaces() == 0 else W.sub(0)
    return dolfin.DirichletBC(V, dolfin.Constant((0.0, 0.0, 0.0)),
                              geometry.ffun, geometry.markers['BASE'][0])


# Traction at the bottom of the beam
lvp = dolfin.Constant(0.0)
neumann_bc = pulse.NeumannBC(traction=lvp,
                             marker=geometry.markers['ENDO'][0])