Exemplo n.º 1
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
Exemplo n.º 2
0
def create_forward_problem(
    mesh,
    activation,
    active_value=0.0,
    active_model="active_stain",
    T_ref=1.0,
):

    ffun = df.MeshFunction("size_t", mesh, 2)
    ffun.set_all(0)

    left = df.CompiledSubDomain("on_boundary && near(x[0], 0)")
    left_marker = 1
    left.mark(ffun, left_marker)

    # Collect the functions containing the markers
    marker_functions = pulse.MarkerFunctions(ffun=ffun)

    def dirichlet_bc(W):
        V = W if W.sub(0).num_sub_spaces() == 0 else W.sub(0)
        return da.DirichletBC(V, da.Constant((0.0, 0.0, 0.0)), left)

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

    f0 = df.as_vector([1, 0, 0])
    microstructure = pulse.Microstructure(f0=f0)

    geometry = pulse.Geometry(
        mesh=mesh,
        marker_functions=marker_functions,
        microstructure=microstructure,
    )

    material_parameters = dict(
        a=2.28,
        a_f=1.686,
        b=9.726,
        b_f=15.779,
        a_s=0.0,
        b_s=0.0,
        a_fs=0.0,
        b_fs=0.0,
    )
    material = pulse.HolzapfelOgden(
        active_model=active_model,
        parameters=material_parameters,
        activation=activation,
        T_ref=T_ref,
    )

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

    if active_value > 0.0:
        pulse.iterate.iterate(problem, activation, active_value)

    return problem
Exemplo n.º 3
0
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)
Exemplo n.º 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
Exemplo n.º 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')
Exemplo n.º 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
Exemplo n.º 7
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]
endo_apex_idx = geometry.vfun.array().tolist().index(endo_apex_marker)
endo_apex = geometry.mesh.coordinates()[endo_apex_idx, :]
endo_apex_pos = endo_apex + u(endo_apex)
Exemplo n.º 8
0
    bc = DirichletBC(V.sub(0), Constant(0.0), geometry.ffun,
                     markers["BASE"][0])
    return bc


dirichlet_bc = [fix_basal_plane]
# You can also use a built in function for this
# from functools import partial
# dirichlet_bc = partial(pulse.mechanicsproblem.dirichlet_fix_base_directional,
#                        ffun=geometry.ffun,
#                        marker=geometry.markers["BASE"][0])

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

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

problem.solve()

# Solve the problem
pulse.iterate.iterate(problem, (lvp, activation), (1.0, 0.2))

# Get the solution
u, p = problem.state.split(deepcopy=True)

volume = geometry.cavity_volume(u=u)
Exemplo n.º 9
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
Exemplo n.º 10
0
 def _handle_bcs(self, bcs, bcs_parameters):
     self.bcs = pulse.BoundaryConditions()
Exemplo n.º 11
0
def create_experiment(case):  # noqa: C901

    if case == "fs":

        def dirichlet_bc(W):
            V = W if W.sub(0).num_sub_spaces() == 0 else W.sub(0)
            return [
                DirichletBC(V, zero, xlow),
                DirichletBC(V, x, xhigh),
            ]

        def increment(xi):
            return (0, xi, 0)

        def shear_component(T):
            return dolfin.assemble(T[0, 1] * dolfin.dx)

    elif case == "fn":

        def dirichlet_bc(W):
            V = W if W.sub(0).num_sub_spaces() == 0 else W.sub(0)
            return [
                DirichletBC(V, zero, xlow),
                DirichletBC(V, x, xhigh),
            ]

        def increment(xi):
            return (0, 0, xi)

        def shear_component(T):
            return dolfin.assemble(T[0, 2] * dolfin.dx)

    elif case == "sf":

        def dirichlet_bc(W):
            V = W if W.sub(0).num_sub_spaces() == 0 else W.sub(0)
            return [
                DirichletBC(V, zero, ylow),
                DirichletBC(V, x, yhigh),
            ]

        def increment(xi):
            return (xi, 0, 0)

        def shear_component(T):
            return dolfin.assemble(T[1, 0] * dolfin.dx)

    elif case == "sn":

        def dirichlet_bc(W):
            V = W if W.sub(0).num_sub_spaces() == 0 else W.sub(0)
            return [
                DirichletBC(V, zero, ylow),
                DirichletBC(V, x, yhigh),
            ]

        def increment(xi):
            return (0, 0, xi)

        def shear_component(T):
            return dolfin.assemble(T[1, 2] * dolfin.dx)

    elif case == "nf":

        def dirichlet_bc(W):
            V = W if W.sub(0).num_sub_spaces() == 0 else W.sub(0)
            return [
                DirichletBC(V, zero, zlow),
                DirichletBC(V, x, zhigh),
            ]

        def increment(xi):
            return (xi, 0, 0)

        def shear_component(T):
            return dolfin.assemble(T[2, 0] * dolfin.dx)

    elif case == "ns":

        def dirichlet_bc(W):
            V = W if W.sub(0).num_sub_spaces() == 0 else W.sub(0)
            return [
                DirichletBC(V, zero, zlow),
                DirichletBC(V, x, zhigh),
            ]

        def increment(xi):
            return (0, xi, 0)

        def shear_component(T):
            return dolfin.assemble(T[2, 1] * dolfin.dx)

    else:
        raise ValueError(f"Unknown case {case}")

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

    # Create problem
    return Experiment(
        problem=pulse.MechanicsProblem(geometry, material, bcs),
        increment=increment,
        shear_component=shear_component,
    )
Exemplo n.º 12
0

# 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.sub(0), Constant(-x_strain), xlow),
        DirichletBC(V.sub(0), Constant(x_strain), xhigh),
        DirichletBC(V.sub(1), Constant(-y_strain), ylow),
        DirichletBC(V.sub(1), Constant(y_strain), yhigh),
        DirichletBC(V, np.zeros(3), center, method="pointwise"),
    ]


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

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

# Solve problem
max_xi = [0.1, 0.15, 0.1]
data = {}
for i, sr in enumerate([2.05, 1.02, 0.48]):

    strain_ratio.assign(sr)
    Effs = []
    Sffs = []
    Esss = []
    Ssss = []
Exemplo n.º 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)))