Ejemplo n.º 1
0
def test_eigenvalues():
    nx, ny = 32, 32
    mesh = firedrake.UnitSquareMesh(nx, ny)
    x, y = firedrake.SpatialCoordinate(mesh)

    V = firedrake.VectorFunctionSpace(mesh, family='CG', degree=2)
    u = interpolate(as_vector((x, 0)), V)

    Q = firedrake.FunctionSpace(mesh, family='DG', degree=2)
    ε = sym(grad(u))
    Λ1, Λ2 = eigenvalues(ε)
    λ1 = firedrake.project(Λ1, Q)
    λ2 = firedrake.project(Λ2, Q)

    assert norm(λ1 - Constant(1)) < norm(u) / (nx * ny)
    assert norm(λ2) < norm(u) / (nx * ny)
Ejemplo n.º 2
0
    def sources(self, **kwargs):
        keys = ("damage", "velocity", "strain_rate", "membrane_stress")
        D, u, ε, M = itemgetter(*keys)(kwargs)

        # Increase/decrease damage depending on stress and strain rates
        ε_1 = eigenvalues(ε)[0]
        σ_e = sqrt(inner(M, M) - det(M))

        ε_h = firedrake.Constant(self.healing_strain_rate)
        σ_d = firedrake.Constant(self.damage_stress)
        γ_h = firedrake.Constant(self.healing_rate)
        γ_d = firedrake.Constant(self.damage_rate)

        healing = γ_h * min_value(ε_1 - ε_h, 0)
        fracture = γ_d * conditional(σ_e - σ_d > 0, ε_1, 0.0) * (1 - D)

        return healing + fracture
Ejemplo n.º 3
0
    def sources(self, **kwargs):
        keys = ('damage', 'velocity', 'strain_rate', 'membrane_stress')
        keys_alt = ('D', 'u', 'ε', 'M')
        D, u, ε, M = get_kwargs_alt(kwargs, keys, keys_alt)

        # Increase/decrease damage depending on stress and strain rates
        ε_1 = eigenvalues(ε)[0]
        σ_e = sqrt(inner(M, M) - det(M))

        ε_h = firedrake.Constant(self.healing_strain_rate)
        σ_d = firedrake.Constant(self.damage_stress)
        γ_h = firedrake.Constant(self.healing_rate)
        γ_d = firedrake.Constant(self.damage_rate)

        healing = γ_h * min_value(ε_1 - ε_h, 0)
        fracture = γ_d * conditional(σ_e - σ_d > 0, ε_1, 0.) * (1 - D)

        return healing + fracture
Ejemplo n.º 4
0
    def sources(self, **kwargs):
        keys = ('damage', 'velocity', 'fluidity')
        keys_alt = ('D', 'u', 'A')
        D, u, A = get_kwargs_alt(kwargs, keys, keys_alt)

        # Increase/decrease damage depending on stress and strain rates
        ε = sym(grad(u))
        ε_1 = eigenvalues(ε)[0]

        σ = M(ε, A)
        σ_e = sqrt(inner(σ, σ) - det(σ))

        ε_h = firedrake.Constant(self.healing_strain_rate)
        σ_d = firedrake.Constant(self.damage_stress)
        γ_h = firedrake.Constant(self.healing_rate)
        γ_d = firedrake.Constant(self.damage_rate)

        healing = γ_h * min_value(ε_1 - ε_h, 0)
        fracture = γ_d * conditional(σ_e - σ_d > 0, ε_1, 0.) * (1 - D)

        return healing + fracture
Ejemplo n.º 5
0
    def solve(self, dt, D0, u, A, D_inflow=None, **kwargs):
        r"""Propogate the damage forward by one timestep

        This function uses a Runge-Kutta scheme to upwind damage
        (limiting damage diffusion) while sourcing and sinking
        damage assocaited with crevasse opening/crevasse healing

        Parameters
        ----------
        dt : float
            Timestep
        D0 : firedrake.Function
            initial damage feild should be discontinuous
        u : firedrake.Function
            Ice velocity
        A : firedrake.Function
            fluidity parameter
        D_inflow : firedrake.Function
            Damage of the upstream ice that advects into the domain

        Returns
        -------
        D : firedrake.Function
            Ice damage at `t + dt`
        """

        D_inflow = D_inflow if D_inflow is not None else D0
        Q = D0.function_space()
        dD, φ = firedrake.TrialFunction(Q), firedrake.TestFunction(Q)
        d = φ * dD * dx
        D = D0.copy(deepcopy=True)

        n = firedrake.FacetNormal(Q.mesh())

        un = 0.5 * (inner(u, n) + abs(inner(u, n)))
        L1 = dt * (D * div(φ * u) * dx - φ * max_value(inner(u, n), 0) * D * ds
                   - φ * min_value(inner(u, n), 0) * D_inflow * ds -
                   (φ('+') - φ('-')) *
                   (un('+') * D('+') - un('-') * D('-')) * dS)
        D1 = firedrake.Function(Q)
        D2 = firedrake.Function(Q)
        L2 = firedrake.replace(L1, {D: D1})
        L3 = firedrake.replace(L1, {D: D2})

        dq = firedrake.Function(Q)

        # Three-stage strong structure-preserving Runge Kutta (SSPRK3) method
        params = {
            'ksp_type': 'preonly',
            'pc_type': 'bjacobi',
            'sub_pc_type': 'ilu'
        }
        prob1 = firedrake.LinearVariationalProblem(d, L1, dq)
        solv1 = firedrake.LinearVariationalSolver(prob1,
                                                  solver_parameters=params)
        prob2 = firedrake.LinearVariationalProblem(d, L2, dq)
        solv2 = firedrake.LinearVariationalSolver(prob2,
                                                  solver_parameters=params)
        prob3 = firedrake.LinearVariationalProblem(d, L3, dq)
        solv3 = firedrake.LinearVariationalSolver(prob3,
                                                  solver_parameters=params)

        solv1.solve()
        D1.assign(D + dq)
        solv2.solve()
        D2.assign(0.75 * D + 0.25 * (D1 + dq))
        solv3.solve()
        D.assign((1.0 / 3.0) * D + (2.0 / 3.0) * (D2 + dq))

        # Increase/decrease damage depending on stress and strain rates
        ε = sym(grad(u))
        ε_1 = eigenvalues(ε)[0]

        σ = M(ε, A)
        σ_e = sqrt(inner(σ, σ) - det(σ))

        ε_h = firedrake.Constant(self.healing_strain_rate)
        σ_d = firedrake.Constant(self.damage_stress)
        γ_h = firedrake.Constant(self.healing_rate)
        γ_d = firedrake.Constant(self.damage_rate)

        healing = γ_h * min_value(ε_1 - ε_h, 0)
        fracture = γ_d * conditional(σ_e - σ_d > 0, ε_1, 0.) * (1 - D)

        # Clamp damage field to [0, 1]
        D.project(min_value(max_value(D + dt * (healing + fracture), 0), 1))
        return D