Ejemplo n.º 1
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)
Ejemplo n.º 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
Ejemplo n.º 3
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
Ejemplo n.º 4
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
Ejemplo n.º 5
0
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])
    return bc


dirichlet_bc = [fix_basal_plane]
# You can also use a built in function for this
# from functools import partial
Ejemplo n.º 6
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
Ejemplo n.º 7
0
material = pulse.HolzapfelOgden(activation=activation,
                                parameters=matparams,
                                f0=geometry.f0,
                                s0=geometry.s0,
                                n0=geometry.n0)

# LV Pressure
lvp = dolfin.Constant(1.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])]


# 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])
    return bc


dirichlet_bc = [fix_basal_plane]
# You can also use a built in function for this
# from functools import partial
Ejemplo n.º 8
0
activation.assign(dolfin.Constant(0.2))
matparams = pulse.HolzapfelOgden.default_parameters()
material = pulse.HolzapfelOgden(activation=activation,
                                parameters=matparams,
                                f0=geometry.f0)

# LV Pressure
lvp = dolfin.Constant(1.0)
lv_marker = markers_dict["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=markers_dict["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,
                            markers_dict["BASE"][0])
    return bc


dirichlet_bc = [fix_basal_plane]
# You can also use a built in function for this
# from functools import partial
Ejemplo n.º 9
0
    parameters=matparams,
    f0=geometry.f0,
    s0=geometry.s0,
    n0=geometry.n0,
)

# LV Pressure
lvp = 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 epicardium of stiffness 1.0 kPa/cm^2 to represent pericardium
base_spring = 1.0
robin_bc = [
    pulse.RobinBC(value=Constant(base_spring), marker=geometry.markers["EPI"][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,
        geometry.markers["BASE"][0],
    )
    return bc
Ejemplo n.º 10
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)))