def boundary_conditions(geometry, **bcs_parameters):
    try:
        pericardium_spring = bcs_parameters['pericardium_spring']
        base_spring = bcs_parameters['base_spring']
        base_bc = bcs_parameters['base_bc']
    except KeyError:
        msg = "Not all boundary conditions have been set. You have provided "\
                "{}".format(bcs_parameters.keys())
        raise KeyError(msg)
    # Neumann BCs
    lv_pressure = pulse.NeumannBC(traction=Constant(0.0, name="lv_pressure"),
                                  marker=geometry.get_lv_marker(),
                                  name="lv")
    neumann_bc = [lv_pressure]

    if geometry.has_rv():
        rv_pressure = pulse.NeumannBC(traction=Constant(0.0,
                                                        name="rv_pressure"),
                                      marker=geometry.get_rv_marker(),
                                      name="rv")
        neumann_bc += [rv_pressure]

    # Robin BC
    robin_bc = []
    if pericardium_spring > 0.0:
        robin_bc += [
            pulse.RobinBC(value=Constant(pericardium_spring),
                          marker=geometry.get_epi_marker())
        ]

    if base_spring > 0.0:
        robin_bc += [
            pulse.RobinBC(value=Constant(base_spring),
                          marker=geometry.get_base_marker())
        ]

    # Dirichlet BC
    if base_bc == "fixed":
        dirichlet_bc = [
            partial(
                dirichlet_fix_base,
                ffun=geometry.ffun,
                marker=geometry.get_base_marker(),
            )
        ]

    elif base_bc == "fix_x":
        dirichlet_bc = [
            partial(dirichlet_fix_base_directional,
                    ffun=geometry.ffun,
                    marker=geometry.get_base_marker())
        ]

    return pulse.BoundaryConditions(dirichlet=dirichlet_bc,
                                    neumann=neumann_bc,
                                    robin=robin_bc)
Example #2
0
def mechanics_bcs(geometry):
    # LV Pressure
    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]

    bcs = pulse.BoundaryConditions(dirichlet=dirichlet_bc,
                                   neumann=neumann_bc,
                                   robin=robin_bc)
    return bcs
def test_boundary_observation():

    bc = pulse.NeumannBC(traction=dolfin_adjoint.Constant(0.0),
                         marker=0,
                         name="test bc")
    pressures = (0.0, 0.1, 0.2)
    bcs = BoundaryObservation(bc=bc, data=pressures)

    for i, b in enumerate(bcs):
        b.assign_bc()
        assert abs(float(b.bc.traction) - pressures[i]) < 1e-12
Example #4
0
def create_mechanics_problem(solver_parameters):
    import pulse
    # from pulse import (MechanicsProblem, HeartGeometry, BoundaryConditions,
    # NeumannBC, RobinBC, MarkerFunctions, Marker, CRLBasis)
    from pulse.material import HolzapfelOgden

    mfun = pulse.MarkerFunctions(ffun=solver_parameters['facet_function'],
                                 cfun=solver_parameters['mesh_function'])

    material = solver_parameters['material']
    microstructure = pulse.Microstructure(f0=material.f0,
                                          s0=material.s0,
                                          n0=material.f0)

    crl_basis = pulse.CRLBasis(
        c0=solver_parameters['crl_basis']['circumferential'],
        r0=solver_parameters['crl_basis']['radial'],
        l0=solver_parameters['crl_basis']['longitudinal'])

    geometry = pulse.HeartGeometry(mesh=solver_parameters['mesh'],
                                   markers=solver_parameters['markers'],
                                   marker_functions=mfun,
                                   microstructure=microstructure,
                                   crl_basis=crl_basis)

    neumann = []
    names = ['lv', 'rv']
    for i, n in enumerate(solver_parameters['bc']['neumann']):
        neumann.append(
            pulse.NeumannBC(traction=n[0], marker=n[1], name=names[i]))

    robin = []
    for i, n in enumerate(solver_parameters['bc']['robin']):
        robin.append(pulse.RobinBC(value=n[0], marker=n[1]))

    if hasattr(solver_parameters['bc']['dirichlet'], '__len__'):
        dirichlet = solver_parameters['bc']['dirichlet']
    else:
        dirichlet = (solver_parameters['bc']['dirichlet'], )

    bcs = pulse.BoundaryConditions(dirichlet=dirichlet,
                                   neumann=neumann,
                                   robin=robin)

    problem = pulse.MechanicsProblem(geometry, material, bcs)

    return problem
Example #5
0
def main():
    def fix_basal_plane(W):
        V = W if W.sub(0).num_sub_spaces() == 0 else W.sub(0)
        bc = dolfin.DirichletBC(V, dolfin.Constant((0.0, 0.0, 0.0)),
                                geometry.ffun, geometry.markers["BASE"][0])
        return bc

    dirichlet_bc = [fix_basal_plane]

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

    bcs = pulse.BoundaryConditions(dirichlet=dirichlet_bc, neumann=neumann_bc)

    fig, ax = plt.subplots()
    for material_model in ["neo_hookean", "guccione", "holzapfel_ogden"]:

        material = setup_material(material_model)
        problem = pulse.MechanicsProblem(geometry, material, bcs)

        pressures = [0.0]
        volumes = [geometry.cavity_volume()]

        for p in np.linspace(0, ED_pressure, 10)[1:]:
            pulse.iterate.iterate(problem, lvp, p)

            pressures.append(p)
            volumes.append(geometry.cavity_volume(u=problem.state.split()[0]))

        ax.plot(volumes, pressures, label=" ".join(material_model.split("_")))

        # Reset pressure
        lvp.assign(dolfin.Constant(0.0))

    vs, ps = klotz_curve()
    ax.plot(vs, ps, linestyle="--", label='Klotz curve')
    ax.legend(loc="best")
    ax.set_xlabel('Volume (ml)')
    ax.set_ylabel('Pressure (kPa)')
    # plt.show()
    plt.savefig('klotz_curve.png')
Example #6
0
def build_problem(geometry, matparams):
    activation = dolfin.Function(dolfin.FunctionSpace(geometry.mesh, "R", 0))
    material = pulse.HolzapfelOgden(
        activation=activation,
        parameters=matparams,
        f0=geometry.f0,
        s0=geometry.s0,
        n0=geometry.n0,
    )

    # LV Pressure
    lvp = dolfin.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=dolfin.Constant(base_spring), marker=geometry.markers["BASE"][0]
        )
    ]

    # 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]
        )
        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)
    return problem, activation, lvp
Example #7
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, ),
                               neumann=(neumann_bc, ))

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

# Solve problem
pulse.iterate.iterate(problem, lvp, 10.0)

# Get displacement and hydrostatic pressure
u, p = problem.state.split(deepcopy=True)

endo_apex_marker = geometry.markers['ENDOPT'][0]
Example #8
0
# Create material
material = pulse.HolzapfelOgden(
    active_model=active_model,
    parameters=material_parameters,
    activation=activation,
)


# Make Dirichlet boundary conditions
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)), fixed)


# Make Neumann boundary conditions
neumann_bc = pulse.NeumannBC(traction=Constant(0.0), marker=free_marker)

# Collect Boundary Conditions
bcs = pulse.BoundaryConditions(dirichlet=(dirichlet_bc,), neumann=(neumann_bc,))

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

# Solve problem
pulse.iterate.iterate(problem, activation, 0.1)

# Get displacement and hydrostatic pressure
u, p = problem.state.split(deepcopy=True)

V = dolfin.VectorFunctionSpace(mesh, "CG", 1)
u_int = interpolate(u, V)
Example #9
0
activation = dolfin.Constant(0.1)

# Create material
material = pulse.HolzapfelOgden(active_model=active_model,
                                params=material_parameters,
                                activation=activation)


# Make Dirichlet boundary conditions
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)), fixed)


# Make Neumann boundary conditions
neumann_bc = pulse.NeumannBC(traction=dolfin.Constant(0.0),
                             marker=free_marker.value)

# Collect Boundary Conditions
bcs = pulse.BoundaryConditions(dirichlet=(dirichlet_bc, ),
                               neumann=(neumann_bc, ))

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

# Solve problem
problem.solve()

# Get displacement and hydrostatic pressure
u, p = problem.state.split(deepcopy=True)

# Plot
Example #10
0
    microstructure=microstructure,
)

activation = Function(dolfin.FunctionSpace(geometry.mesh, "R", 0))
activation.assign(Constant(0.0))
matparams = pulse.HolzapfelOgden.default_parameters()
material = pulse.HolzapfelOgden(
    activation=activation,
    parameters=matparams,
    f0=geometry.f0,
)

# LV Pressure
lvp = Constant(0.0)
lv_marker = 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=Constant(base_spring), marker=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 = DirichletBC(V.sub(0), Constant(0.0), geometry.ffun,
                     markers["BASE"][0])
Example #11
0
def create_problem():

    geometry = pulse.HeartGeometry.from_file(
        pulse.mesh_paths["simple_ellipsoid"])

    activation = dolfin_adjoint.Function(dolfin.FunctionSpace(
        geometry.mesh, "R", 0),
                                         name="activation")
    activation.assign(dolfin_adjoint.Constant(0.0))
    matparams = pulse.HolzapfelOgden.default_parameters()

    V = dolfin.FunctionSpace(geometry.mesh, "R", 0)
    control = dolfin_adjoint.Function(V)
    control.assign(dolfin_adjoint.Constant(1.0))
    # control = dolfin_adjoint.Constant(1.0, name="matparam control (a)")
    matparams["a"] = control

    f0 = dolfin_adjoint.Function(geometry.f0.function_space())
    f0.assign(geometry.f0)
    s0 = dolfin_adjoint.Function(geometry.s0.function_space())
    s0.assign(geometry.s0)
    n0 = dolfin_adjoint.Function(geometry.n0.function_space())
    n0.assign(geometry.n0)

    material = pulse.HolzapfelOgden(activation=activation,
                                    parameters=matparams,
                                    f0=f0,
                                    s0=s0,
                                    n0=n0)

    # LV Pressure
    lvp = dolfin_adjoint.Constant(0.0, name="lvp")
    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=dolfin_adjoint.Constant(base_spring, name="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_adjoint.DirichletBC(
            V.sub(0),
            dolfin.Constant(0.0, name="fix_base"),
            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)

    return problem, control
Example #12
0
material_parameters['bf'] = 8.0
material_parameters['bfs'] = 4.0
material_parameters['bt'] = 2.0

material = pulse.Guccione(params=material_parameters)


# Define Dirichlet boundary. Fix at the left boundary
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)), left)


# Traction at the bottom of the beam
p_bottom = dolfin.Constant(0.004)
neumann_bc = pulse.NeumannBC(traction=p_bottom, marker=bottom_marker.value)

# Collect Boundary Conditions
bcs = pulse.BoundaryConditions(dirichlet=(dirichlet_bc, ),
                               neumann=(neumann_bc, ))

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

# Solve problem
problem.solve()

# Get displacement and hydrostatic pressure
u, p = problem.state.split(deepcopy=True)

point = np.array([10.0, 0.5, 1.0])
Example #13
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)))