def updateCoefficients(self):

        # Init coefficient matrix
        P, Inv = SpatialCoordinate(self.mesh)

        self.a = as_matrix([[+.5 * (P * self.sigma)**2, 0], [0, 0]])

        # def K(t): return self.K0 + beta_SA * sin(4*pi*(t - t_SA))
        def K(t):
            return self.K0

        self.b = as_vector([
            +self.alpha * (K(self.t) - P),
            -(self.gamma[0] + self.cost(self.gamma[0]))
        ])

        self.c = Constant(-self.r)

        # Init right-hand side
        self.f = -(self.gamma[0] - self.cost(self.gamma[0])) * P

        self.u_T = -2 * P * ufl.Max(1000 - Inv, 0)
        # self.u_T = Constant(0.0)

        # Set boundary conditions
        # self.g_t = lambda t : [(Constant(0.0), "near(x[0],0)")]
        self.g = self.u_T
Esempio n. 2
0
    def bdrag_to_alpha(self, B2):
        """Convert basal drag to alpha"""
        sl = self.params.ice_dynamics.sliding_law
        if sl == 'linear':
            alpha = sqrt(B2)

        elif sl == 'budd':
            bed = self.bed
            H = self.H
            g = self.params.constants.g
            rhoi = self.params.constants.rhoi
            rhow = self.params.constants.rhow
            u_obs = self.u_obs_M
            v_obs = self.v_obs_M
            vel_rp = self.params.constants.vel_rp

            # Flotation Criterion
            H_flt = -rhow / rhoi * bed
            fl_ex = conditional(H <= H_flt, 1.0, 0.0)

            N = (1 - fl_ex) * (H * rhoi * g + ufl.Min(bed, 0.0) * rhow * g)
            U_mag = sqrt(u_obs**2 + v_obs**2 + vel_rp**2)
            alpha = (1 - fl_ex) * sqrt(
                B2 * ufl.Max(N, 0.01)**(-1.0 / 3.0) * U_mag**(2.0 / 3.0))

        return alpha
Esempio n. 3
0
    def gen_alpha(self, a_bgd=500.0, a_lb=1e2, a_ub=1e4):
        """Generate initial guess for alpha (slip coeff)"""
        bed = self.bed
        H = self.H
        g = self.params.constants.g
        rhoi = self.params.constants.rhoi
        rhow = self.params.constants.rhow
        u_obs = self.u_obs_M
        v_obs = self.v_obs_M
        vel_rp = self.params.constants.vel_rp

        U = ufl.Max((u_obs**2 + v_obs**2)**(1 / 2.0), 50.0)

        # Flotation Criterion
        H_s = -rhow / rhoi * bed
        fl_ex = conditional(H <= H_s, 1.0, 0.0)

        # Thickness Criterion
        m_d = conditional(H > 0, 1.0, 0.0)

        # Calculate surface gradient
        R_f = ((1.0 - fl_ex) * bed + (fl_ex) * (-rhoi / rhow) * H)

        s_ = ufl.Max(H + R_f, 0)
        s = project(s_, self.Q)
        grads = (s.dx(0)**2.0 + s.dx(1)**2.0)**(1.0 / 2.0)

        # Calculate alpha, apply background, apply bound
        B2_ = ((1.0 - fl_ex) * rhoi * g * H * grads / U +
               (fl_ex) * a_bgd) * m_d + (1.0 - m_d) * a_bgd

        B2_tmp1 = ufl.Max(B2_, a_lb)
        B2_tmp2 = ufl.Min(B2_tmp1, a_ub)

        sl = self.params.ice_dynamics.sliding_law
        if sl == 'linear':
            alpha = sqrt(B2_tmp2)
        elif sl == 'weertman':
            N = (1 - fl_ex) * (H * rhoi * g + ufl.Min(bed, 0.0) * rhow * g)
            U_mag = sqrt(u_obs**2 + v_obs**2 + vel_rp**2)
            alpha = (1 - fl_ex) * sqrt(
                B2_tmp2 * ufl.Max(N, 0.01)**(-1.0 / 3.0) * U_mag**(2.0 / 3.0))

        self.alpha = project(alpha, self.Qp)
        self.alpha.rename('alpha', 'a Function')
Esempio n. 4
0
def f1(phi):
    """Factor representing humidity effects,
    i.e. carbonation reaction stops for very low humidities.

    Note
    ----
    Saetta 1993, page 764, formula (5)

    """
    mid = 2.5 * (phi - 0.5)
    return ufl.Max(ufl.Min(mid, 1.0), 0.0)
    def initControl(self):

        # Initialize control spaces
        self.controlSpace = []
        self.controlSpace.append(FunctionSpace(self.mesh, "DG", 0))
        self.controlSpace.append(FunctionSpace(self.mesh, "DG", 0))
        # self.controlSpace.append(FunctionSpace(self.mesh, "CG", 1))
        # self.controlSpace.append(FunctionSpace(self.mesh, "CG", 1))

        self.gamma = []

        # Initialize controls
        Dxu = Dx(self.u, 0)
        spx = Dxu + self.beta
        smx = Dxu - self.beta

        Dyu = Dx(self.u, 1)
        spy = Dyu + self.beta
        smy = Dyu - self.beta

        if self.alpha < 1e-15:
            self.gamma.append(
                conditional(spx < 0, self.cmax,
                            conditional(smx > 0, self.cmin, 0)))
            self.gamma.append(
                conditional(spy < 0, self.cmax,
                            conditional(smy > 0, self.cmin, 0)))
        else:
            self.gamma.append(
                conditional(
                    spx < 0, ufl.Min(-1.0 * spx / self.alpha, self.cmax),
                    conditional(smx > 0,
                                ufl.Max(-1.0 * smx / self.alpha, self.cmin),
                                0)))

            self.gamma.append(
                conditional(
                    spy < 0, ufl.Min(-1.0 * spy / self.alpha, self.cmax),
                    conditional(smy > 0,
                                ufl.Max(-1.0 * smy / self.alpha, self.cmin),
                                0)))
Esempio n. 6
0
    def increase_conductivity(self, cond, e):
        # Set up the three way choice function
        intermediate = e * self.k + self.h
        not_less_than = ufl.conditional(ufl.gt(e, self.threshold_irreversible),
                                        self.sigma_end, intermediate)
        cond_expression = ufl.conditional(ufl.lt(e, self.threshold_reversible),
                                          self.sigma_start, not_less_than)

        # Project this onto the function space
        cond_function = d.project(ufl.Max(cond_expression, cond),
                                  cond.function_space())
        cond.assign(cond_function)
Esempio n. 7
0
    def initControl(self):
        self.controlSpace = [
            FunctionSpace(self.mesh, "DG", 1),
            FunctionSpace(self.mesh, "DG", 1)
        ]

        self.gamma = []
        # Dxu = project(Dx(self.u,0),FunctionSpace(self.mesh, "DG", 0))
        Dxu = Dx(self.u, 0)
        spx = Dxu + self.beta
        smx = Dxu - self.beta

        # Dyu = project(Dx(self.u,1),FunctionSpace(self.mesh, "DG", 0))
        Dyu = Dx(self.u, 1)
        spy = Dyu + self.beta
        smy = Dyu - self.beta

        if self.alpha < 1e-15:
            self.gamma.append(
                conditional(spx < 0, self.cmax,
                            conditional(smx > 0, self.cmin, 0)))
            self.gamma.append(
                conditional(spy < 0, self.cmax,
                            conditional(smy > 0, self.cmin, 0)))
        else:

            self.gamma.append(
                conditional(
                    spx < 0, ufl.Min(-1.0 * spx / self.alpha, self.cmax),
                    conditional(smx > 0,
                                ufl.Max(-1.0 * smx / self.alpha, self.cmin),
                                0)))

            self.gamma.append(
                conditional(
                    spy < 0, ufl.Min(-1.0 * spy / self.alpha, self.cmax),
                    conditional(smy > 0,
                                ufl.Max(-1.0 * smy / self.alpha, self.cmin),
                                0)))
    def initControl(self):

        # Initialize control spaces
        self.controlSpace = [FunctionSpace(self.mesh, "DG", 1)]

        # Initialize controls

        P, Inv = SpatialCoordinate(self.mesh)

        cmax = self.k1 * sqrt(Inv)
        cmin = -self.k2 * sqrt(1 / (Inv + self.k3) - 1 / self.k4)
        ui = Dx(self.u, 1)
        u1 = self.Gamma(cmin, P, ui)
        u2 = self.Gamma(-Constant(self.k5), P, ui)
        u3 = self.Gamma(Constant(0.0), P, ui)
        u4 = self.Gamma(cmax, P, ui)
        umax = ufl.Max(u1, ufl.Max(u2, ufl.Max(u3, u4)))
        # self.gamma[0] = cmin
        g1 = conditional(
            u1 >= umax, cmin,
            conditional(u2 >= umax, -self.k5,
                        conditional(u3 >= umax, 0.0, cmax)))
        self.gamma = [g1]
Esempio n. 9
0
def eigenstate_legacy(A):
    """Eigenvalues and eigenprojectors of the 3x3 (real-valued) tensor A.
    Provides the spectral decomposition A = sum_{a=0}^{2} λ_a * E_a
    with eigenvalues λ_a and their associated eigenprojectors E_a = n_a^R x n_a^L
    ordered by magnitude.
    The eigenprojectors of eigenvalues with multiplicity n are returned as 1/n-fold projector.

    Note: Tensor A must not have complex eigenvalues!
    """
    if ufl.shape(A) != (3, 3):
        raise RuntimeError(
            f"Tensor A of shape {ufl.shape(A)} != (3, 3) is not supported!")
    #
    eps = 1.0e-10
    #
    A = ufl.variable(A)
    #
    # --- determine eigenvalues λ0, λ1, λ2
    #
    # additively decompose: A = tr(A) / 3 * I + dev(A) = q * I + B
    q = ufl.tr(A) / 3
    B = A - q * ufl.Identity(3)
    # observe: det(λI - A) = 0  with shift  λ = q + ω --> det(ωI - B) = 0 = ω**3 - j * ω - b
    j = ufl.tr(
        B * B
    ) / 2  # == -I2(B) for trace-free B, j < 0 indicates A has complex eigenvalues
    b = ufl.tr(B * B * B) / 3  # == I3(B) for trace-free B
    # solve: 0 = ω**3 - j * ω - b  by substitution  ω = p * cos(phi)
    #        0 = p**3 * cos**3(phi) - j * p * cos(phi) - b  | * 4 / p**3
    #        0 = 4 * cos**3(phi) - 3 * cos(phi) - 4 * b / p**3  | --> p := sqrt(j * 4 / 3)
    #        0 = cos(3 * phi) - 4 * b / p**3
    #        0 = cos(3 * phi) - r                  with  -1 <= r <= +1
    #    phi_k = [acos(r) + (k + 1) * 2 * pi] / 3  for  k = 0, 1, 2
    p = 2 / ufl.sqrt(3) * ufl.sqrt(j + eps**2)  # eps: MMM
    r = 4 * b / p**3
    r = ufl.Max(ufl.Min(r, +1 - eps), -1 + eps)  # eps: LMM, MMH
    phi = ufl.acos(r) / 3
    # sorted eigenvalues: λ0 <= λ1 <= λ2
    λ0 = q + p * ufl.cos(phi + 2 / 3 * ufl.pi)  # low
    λ1 = q + p * ufl.cos(phi + 4 / 3 * ufl.pi)  # middle
    λ2 = q + p * ufl.cos(phi)  # high
    #
    # --- determine eigenprojectors E0, E1, E2
    #
    E0 = ufl.diff(λ0, A).T
    E1 = ufl.diff(λ1, A).T
    E2 = ufl.diff(λ2, A).T
    #
    return [λ0, λ1, λ2], [E0, E1, E2]
    def updateCoefficients(self):

        x, y = SpatialCoordinate(self.mesh)

        sigma1 = 0.3
        sigma2 = 0.3
        rho = 0.5
        r = 0.05
        K = 40

        self.u_T = ufl.Max(K - ufl.Min(x, y), 0)
        self.u_ = ExplicitSolution_WorstOfTwoAssetsPut(
            self.t,
            K,
            r,
            self.T[1],
            sigma1,
            sigma2,
            rho,
            cell=self.mesh.ufl_cell(),
            domain=self.mesh)

        # Init coefficient matrix
        self.a = 0.5 * \
            as_matrix([[sigma1**2 * x**2, rho*sigma1*sigma2*x*y],
                       [rho*sigma1*sigma2*x*y, sigma2**2 * y**2]])

        self.b = as_vector([r * x, r * y])
        self.c = Constant(-r)

        # Init right-hand side
        self.f = Constant(0.0)

        # Set boundary conditions to exact solution
        if self.exact_bc:
            self.g = ExplicitSolution_WorstOfTwoAssetsPut(
                self.t,
                K,
                r,
                self.T[1],
                sigma1,
                sigma2,
                rho,
                cell=self.mesh.ufl_cell(),
                domain=self.mesh)
        else:
            self.g = [(Constant(0.0), 'near(max(x[0],x[1]),200)'),
                      (Constant(K * exp(-r * (self.T[1] - self.t))),
                       'near(min(x[0],x[1]),0)')]
Esempio n. 11
0
def get_scaled_jacobians2d(mesh, python=False):
    """
    Computes the scaled Jacobian of each cell in a 2D triangular mesh

    :arg mesh: the input mesh to do computations on
    :kwarg python: compute the measure using Python?

    :rtype: firedrake.function.Function scaled_jacobians with scaled
        jacobian data.
    """
    P0 = firedrake.FunctionSpace(mesh, "DG", 0)
    if python:
        P0_ten = firedrake.TensorFunctionSpace(mesh, "DG", 0)
        J = firedrake.interpolate(ufl.Jacobian(mesh), P0_ten)
        edge1 = ufl.as_vector([J[0, 0], J[1, 0]])
        edge2 = ufl.as_vector([J[0, 1], J[1, 1]])
        edge3 = edge1 - edge2
        a = ufl.sqrt(ufl.dot(edge1, edge1))
        b = ufl.sqrt(ufl.dot(edge2, edge2))
        c = ufl.sqrt(ufl.dot(edge3, edge3))
        detJ = ufl.JacobianDeterminant(mesh)
        jacobian_sign = ufl.sign(detJ)
        max_product = ufl.Max(
            ufl.Max(ufl.Max(a * b, a * c), ufl.Max(b * c, b * a)), ufl.Max(c * a, c * b)
        )
        scaled_jacobians = firedrake.interpolate(detJ / max_product * jacobian_sign, P0)
    else:
        coords = mesh.coordinates
        scaled_jacobians = firedrake.Function(P0)
        op2.par_loop(
            get_pyop2_kernel("get_scaled_jacobian", 2),
            mesh.cell_set,
            scaled_jacobians.dat(op2.WRITE, scaled_jacobians.cell_node_map()),
            coords.dat(op2.READ, coords.cell_node_map()),
        )
    return scaled_jacobians
Esempio n. 12
0
def eig(A):
    """Eigenvalues of 3x3 tensor"""
    eps = 1.0e-12

    q = ufl.tr(A) / 3.0
    p1 = 0.5 * (A[0, 1]**2 + A[1, 0]**2 + A[0, 2]**2 + A[2, 0]**2 +
                A[1, 2]**2 + A[2, 1]**2)
    p2 = (A[0, 0] - q)**2 + (A[1, 1] - q)**2 + (A[2, 2] - q)**2 + 2 * p1
    p = ufl.sqrt(p2 / 6)
    B = (A - q * ufl.Identity(3))
    r = ufl.det(B) / (2 * p**3)

    r = ufl.Max(ufl.Min(r, 1.0 - eps), -1.0 + eps)
    phi = ufl.acos(r) / 3.0

    eig0 = ufl.conditional(p2 < eps, q, q + 2 * p * ufl.cos(phi))
    eig2 = ufl.conditional(p2 < eps, q,
                           q + 2 * p * ufl.cos(phi + (2 * numpy.pi / 3)))
    eig1 = ufl.conditional(p2 < eps, q, 3 * q - eig0 -
                           eig2)  # since trace(A) = eig1 + eig2 + eig3

    return eig0, eig1, eig2
Esempio n. 13
0
    def comp_Q_vaf(self, verbose=False):
        """QOI: Volume above flotation"""
        cnst = self.params.constants

        H = self.H_np
        # B stands in for self.bed, which leads to a taping error
        B = Function(self.bed.function_space())
        B.assign(self.bed, annotate=False)
        rhoi = Constant(cnst.rhoi)
        rhow = Constant(cnst.rhow)
        dIce = self.dIce
        # dt = self.dt

        b_ex = conditional(B < 0.0, 1.0, 0.0)
        HAF = ufl.Max(b_ex * (H + (rhow / rhoi) * B) + (1 - b_ex) * (H), 0.0)

        Q_vaf = HAF * dIce

        if verbose:
            info(f"Q_vaf: {assemble(Q_vaf)}")

        return Q_vaf
Esempio n. 14
0
import dolfin as df
import numpy as np
import ufl

# TODO: more ...
linear = lambda x: x
ReLu = lambda x: ufl.Max(x, df.Constant(0))


class DenseLayer(object):
    def __init__(self,
                 input_dim,
                 output_dim,
                 mesh,
                 use_bias=True,
                 activation=linear):
        self.input_dim = input_dim  # Remeber for consistency checks
        # Represent (odim, idim) matrix by rows
        W_space = df.VectorFunctionSpace(mesh, 'R', 0, input_dim)
        self.weights = [
            self.init_weights(W_space) for row in range(output_dim)
        ]

        if use_bias:
            b_space = df.VectorFunctionSpace(mesh, 'R', 0, output_dim)
            self.bias = self.init_bias(b_space)
        else:
            self.bias = None

        self.rho = activation
Esempio n. 15
0
    def gen_alpha(self, a_bgd=500.0, a_lb=1e2, a_ub=1e4):
        """Generate initial guess for alpha (slip coeff)"""

        method = self.params.inversion.initial_guess_alpha_method.lower()
        if method == "wearing":
            # Martin Wearing's: alpha = 358.4 - 26.9*log(17.9*speed_obs);
            u_obs = self.u_obs_M
            v_obs = self.v_obs_M
            vel_rp = self.params.constants.vel_rp
            U_mag = sqrt(u_obs**2 + v_obs**2 + vel_rp**2)
            # U_mag = ufl.Max((u_obs**2 + v_obs**2)**(1/2.0), 50.0)

            B2 = 358.4 - 26.9 * ln(17.9 * U_mag)
            alpha = self.bdrag_to_alpha(B2)
            self.alpha.assign(project(alpha, self.Qp))

        elif method == "sia":

            bed = self.bed
            H = self.H
            g = self.params.constants.g
            rhoi = self.params.constants.rhoi
            rhow = self.params.constants.rhow
            u_obs = self.u_obs_M
            v_obs = self.v_obs_M
            vel_rp = self.params.constants.vel_rp

            U = ufl.Max((u_obs**2 + v_obs**2)**(1 / 2.0), 50.0)

            # Flotation Criterion
            H_flt = -rhow / rhoi * bed
            fl_ex = conditional(H <= H_flt, 1.0, 0.0)

            # Thickness Criterion
            m_d = conditional(H > 0, 1.0, 0.0)

            # Calculate surface gradient
            R_f = ((1.0 - fl_ex) * bed + (fl_ex) * (-rhoi / rhow) * H)

            s_ = ufl.Max(H + R_f, 0)
            s = project(s_, self.Q)
            grads = (s.dx(0)**2.0 + s.dx(1)**2.0)**(1.0 / 2.0)

            # Calculate alpha, apply background, apply bound
            B2_ = ((1.0 - fl_ex) * rhoi * g * H * grads / U +
                   (fl_ex) * a_bgd) * m_d + (1.0 - m_d) * a_bgd

            B2_tmp1 = ufl.Max(B2_, a_lb)
            B2_tmp2 = ufl.Min(B2_tmp1, a_ub)

            alpha = self.bdrag_to_alpha(B2_tmp2)
            self.alpha.assign(project(alpha, self.Qp))

        elif method == "constant":
            init_guess = self.params.inversion.initial_guess_alpha
            self.alpha.vector()[:] = init_guess
            self.alpha.vector().apply('insert')
        else:
            raise NotImplementedError(f"Don't have code for method {method}")
        function_update_state(self.alpha)

        write_diag = self.params.io.write_diagnostics
        if write_diag:
            diag_dir = self.params.io.diagnostics_dir
            phase_suffix = self.params.inversion.phase_suffix
            phase_name = self.params.inversion.phase_name
            inout.write_variable(self.alpha,
                                 self.params,
                                 name="alpha_init_guess",
                                 outdir=diag_dir,
                                 phase_name=phase_name,
                                 phase_suffix=phase_suffix)
    return rho * g * Hmid * S.dx(0) * phi(s)


# Driving stress (floating)
def tau_dx_f(s):
    return rho * g * (1 - rho / rho_w) * Hmid * Hmid.dx(0) * phi(s)


# Normal vectors
normalx = (B.dx(0)) / sqrt((B.dx(0))**2 + 1.0)
normalz = sqrt(1 - normalx**2)

# Overburden
P_0 = rho * g * Hmid
# Water pressure (ocean only, no basal hydro.)
P_w = ufl.Max(-rho_w * g * B, 1e-16)

# basal shear stress applied on grounded ice
tau_b = beta2 * u(1) / (1.0 - normalx**2) * grounded

# Momentum balance residual (Blatter-Pattyn/O(1)/LMLa)
R = (-vi.intz(membrane_xx) - vi.intz(shear_xz) - phi(1) * tau_b -
     vi.intz(tau_dx) * grounded - vi.intz(tau_dx_f) * (1 - grounded)) * dx

# shelf front boundary condition
F_ocean_x = 1.0 / 2.0 * rho * g * (1 - (rho / rho_w)) * H**2 * Phi[0] * ds(1)

R += F_ocean_x

#
# MASS BALANCE  ###################################
Esempio n. 17
0
    def def_mom_eq(self):
        """Define the momentum equation to be solved in solve_mom_eq"""

        # Simplify accessing fields and parameters
        constants = self.params.constants
        bed = self.bed
        H = self.H
        alpha = self.alpha

        rhoi = constants.rhoi
        rhow = constants.rhow
        delta = 1.0 - rhoi / rhow
        g = constants.g
        n = constants.glen_n
        tol = constants.float_eps
        dIce = self.dIce
        ds = self.ds
        sl = self.params.ice_dynamics.sliding_law
        vel_rp = constants.vel_rp

        # Vector components of trial function
        u, v = split(self.U)

        # Vector components of test function
        Phi = self.Phi
        Phi_x, Phi_y = split(Phi)

        # Derivatives
        u_x, u_y = u.dx(0), u.dx(1)
        v_x, v_y = v.dx(0), v.dx(1)

        # Viscosity
        U_marker = Function(self.U.function_space(),
                            name="%s_marker" % self.U.name())
        nu = self.viscosity(U_marker)

        # Switch parameters
        H_s = -rhow / rhoi * bed
        fl_ex = self.float_conditional(H, H_s)
        B2 = self.sliding_law(alpha, U_marker)

        ##############################################
        # Construct weak form
        ##############################################

        # Driving stress quantities
        F = (1 - fl_ex) * 0.5*rhoi*g*H**2 + \
            (fl_ex) * 0.5*rhoi*g*(delta*H**2 + (1-delta)*H_s**2 )

        W = (1 - fl_ex) * rhoi*g*H + \
            (fl_ex) * rhoi*g*H_s

        # Depth of the submarine portion of the calving front
        # ufl.Max to avoid edge case of land termininating calving front
        draft = ufl.Max(((fl_ex) * (rhoi / rhow) * H - (1 - fl_ex) * bed),
                        Constant(0.0))

        # Terminating margin boundary condition
        # The -F term is related to the integration by parts in the weak form
        sigma_n = 0.5 * rhoi * g * ((H**2) - (rhow / rhoi) * (draft**2))

        self.mom_F = (
            # Membrance Stresses
            -inner(grad(Phi_x),
                   H * nu * as_vector([4 * u_x + 2 * v_y, u_y + v_x])) *
            self.dIce -
            inner(grad(Phi_y),
                  H * nu * as_vector([u_y + v_x, 4 * v_y + 2 * u_x])) *
            self.dIce

            # Basal Drag
            - inner(Phi, (1.0 - fl_ex) * B2 * as_vector([u, v])) * self.dIce

            # Driving Stress
            + (div(Phi) * F - inner(grad(bed), W * Phi)) * self.dIce)

        # Natural BC term which falls out of weak form:
        # Doesn't apply when domain is periodic
        if not self.params.mesh.periodic_bc:
            self.mom_F -= inner(Phi * F, self.nm) * ds

        ##########################################
        # Boundary Conditions
        ##########################################

        # Dirichlet
        self.flow_bcs = []
        for bc in self.params.bcs:
            if bc.flow_bc == "obs_vel":
                dirichlet_condition = self.latbc
            elif bc.flow_bc == "no_slip":
                dirichlet_condition = Constant((0.0, 0.0))
            elif bc.flow_bc == "free_slip":
                raise NotImplementedError
            else:
                continue

            # Add the dirichlet condition to list
            self.flow_bcs.extend([
                DirichletBC(self.V, dirichlet_condition, self.ff, lab)
                for lab in bc.labels
            ])

        # Neumann
        # We construct a MeasureSum of different exterior facet sections
        # (for now this is only for the calving front)
        # Then we add to the neumann_bcs list:  calving_weak_form_bc * ds(calving_fronts)
        self.neumann_bcs = []
        for bc in self.params.bcs:
            if bc.flow_bc == "calving":
                condition = inner(Phi * sigma_n, self.nm)
            else:  # don't need to do anything for 'natural'
                continue

            measure_list = [ds(i) for i in bc.labels]
            measure_sum = measure_list[0]
            for m in measure_list[1:]:
                measure_sum += m

            self.neumann_bcs.append(condition * measure_sum)

        # Add the Neumann BCs to the weak form
        for neumann in self.neumann_bcs:
            self.mom_F += neumann

        ###########################################
        # Expand derivatives & add marker functions
        ###########################################
        self.mom_Jac_p = ufl.algorithms.expand_derivatives(
            ufl.replace(derivative(self.mom_F, self.U), {U_marker: self.U}))

        self.mom_F = ufl.algorithms.expand_derivatives(
            ufl.replace(self.mom_F, {U_marker: self.U}))

        self.mom_Jac = ufl.algorithms.expand_derivatives(
            derivative(self.mom_F, self.U))
Esempio n. 18
0
def eps_eqv(sigma, E):

    e1, e2, e3 = fecoda.misc.eig(sigma)
    eqv = ufl.Max(e1, ufl.Max(e2, e3)) / E

    return eqv
Esempio n. 19
0
def compile_forms(iv0,
                  iv1,
                  w0,
                  w1,
                  f,
                  g,
                  heat_flux,
                  water_flux,
                  co2_flux,
                  t,
                  dt,
                  reb_dx,
                  con_dx,
                  damage_off=False,
                  randomize=0.0):
    """Return Jacobian and residual forms"""

    t0 = time()

    mesh = w0["displ"].function_space.mesh

    # Prepare zero initial guesses, test and trial fctions, global
    w_displ_trial = ufl.TrialFunction(w0["displ"].function_space)
    w_displ_test = ufl.TestFunction(w0["displ"].function_space)

    w_temp_trial = ufl.TrialFunction(w0["temp"].function_space)
    w_temp_test = ufl.TestFunction(w0["temp"].function_space)

    w_phi_trial = ufl.TrialFunction(w0["phi"].function_space)
    w_phi_test = ufl.TestFunction(w0["phi"].function_space)

    w_co2_trial = ufl.TrialFunction(w0["co2"].function_space)
    w_co2_test = ufl.TestFunction(w0["co2"].function_space)

    #
    # Creep, shrinkage strains
    #

    # Autogenous shrinkage increment
    deps_sh_au = (mps.eps_sh_au(t + dt) - mps.eps_sh_au(t))

    # Thermal strain increment
    deps_th = (misc.beta_C * (w1["temp"] - w0["temp"]) * ufl.Identity(3))

    # Drying shrinkage increment
    deps_sh_dr = (mps.k_sh * (w1["phi"] - w0["phi"]) * ufl.Identity(3))

    eta_dash_mid = mps.eta_dash(iv0["eta_dash"], dt / 2.0, w0["temp"],
                                w0["phi"])

    # Prepare creep factors
    beta_cr = mps.beta_cr(dt)
    lambda_cr = mps.lambda_cr(dt, beta_cr)
    creep_v_mid = mps.creep_v(t + dt / 2.0)

    if randomize > 0.0:
        # Randomize Young's modulus
        # This helps convergence at the point where crack initiation begins
        # Randomized E fluctuates uniformly in [E-eps/2, E+eps/2]
        rnd = Function(iv0["eta_dash"].function_space)
        rnd.vector.array[:] = 1.0 - randomize / 2 + np.random.rand(
            *rnd.vector.array.shape) * randomize
    else:
        rnd = 1.0

    E_kelv = rnd * mps.E_kelv(creep_v_mid, lambda_cr, dt, t, eta_dash_mid)

    gamma0 = []
    for i in range(mps.M):
        gamma0.append(iv0[f"gamma_{i}"])

    deps_cr_kel = mps.deps_cr_kel(beta_cr, gamma0, creep_v_mid)
    deps_cr_dash = mps.deps_cr_dash(iv0["sigma"], eta_dash_mid, dt)

    deps_el = mech.eps_el(w1["displ"] - w0["displ"], deps_th, deps_cr_kel,
                          deps_cr_dash, deps_sh_dr, deps_sh_au)

    # Water vapour saturation pressure
    p_sat = water.p_sat(0.5 * (w1["temp"] + w0["temp"]))
    water_cont = water.water_cont(0.5 * (w1["phi"] + w0["phi"]))
    dw_dphi = water.dw_dphi(0.5 * (w1["phi"] + w0["phi"]))

    # Rate of CaCO_3 concentration change
    dot_caco3 = co2.dot_caco3(dt * 24 * 60 * 60, iv0["caco3"], w1["phi"],
                              w1["co2"], w1["temp"])

    #
    # Balances residuals
    #

    sigma_eff = iv0["sigma"] + mech.stress(E_kelv, deps_el)
    eps_eqv = ufl.Max(
        damage_rankine.eps_eqv(sigma_eff, mps.E_static(creep_v_mid)),
        iv0["eps_eqv"])
    f_c = mech.f_c(t)
    f_t = mech.f_t(f_c)
    G_f = mech.G_f(f_c)
    dmg = damage_rankine.damage(eps_eqv, mesh, mps.E_static(creep_v_mid), f_t,
                                G_f)

    # Prepare stress increments
    if damage_off:
        dmg = 0.0 * dmg
        eps_eqv = iv0["eps_eqv"]

    sigma_rebar = mech.stress_rebar(mech.E_rebar, w1["displ"])
    sigma = (1.0 - dmg) * sigma_eff

    _con_dx = []
    for dx in con_dx:
        _con_dx += [dx(metadata={"quadrature_degree": quad_degree_stress})]
    _con_dx = ufl.classes.MeasureSum(*_con_dx)

    _reb_dx = []
    for dx in reb_dx:
        _reb_dx += [dx(metadata={"quadrature_degree": quad_degree_stress})]
    _reb_dx = ufl.classes.MeasureSum(*_reb_dx)

    # Momentum balance for concrete material
    mom_balance = -ufl.inner(sigma, ufl.grad(w_displ_test)) * _con_dx

    # Momentum balance for rebar material
    if len(reb_dx) > 0:
        mom_balance += -ufl.inner(sigma_rebar,
                                  ufl.grad(w_displ_test)) * _reb_dx

    # Add volume body forces
    for measure, force in g.items():
        mom_balance -= ufl.inner(force, w_displ_test) * measure

    # Add surface forces to mom balance
    for measure, force in f.items():
        mom_balance += ufl.inner(force, w_displ_test) * measure

    _thc_dx = []
    for dx in con_dx + reb_dx:
        _thc_dx += [dx(metadata={"quadrature_degree": quad_degree_thc})]
    _thc_dx = ufl.classes.MeasureSum(*_thc_dx)

    # Energy balance = evolution of temperature
    energy_balance = (
        mech.rho_c * misc.C_pc / (dt * 24 * 60 * 60) * ufl.inner(
            (w1["temp"] - w0["temp"]), w_temp_test) * _thc_dx + misc.lambda_c *
        ufl.inner(ufl.grad(w1["temp"]), ufl.grad(w_temp_test)) * _thc_dx +
        water.h_v * water.delta_p * ufl.inner(ufl.grad(
            w1["phi"] * p_sat), ufl.grad(w_temp_test)) * _thc_dx +
        co2.alpha3 * dot_caco3 * w_temp_test * _thc_dx)

    # Water balance = evolution of humidity
    water_balance = (ufl.inner(
        dw_dphi * 1.0 / (dt * 24 * 60 * 60) *
        (w1["phi"] - w0["phi"]), w_phi_test) * _thc_dx + ufl.inner(
            dw_dphi * water.D_ws(water_cont) * ufl.grad(w1["phi"]) +
            water.delta_p * ufl.grad(w1["phi"] * p_sat), ufl.grad(w_phi_test))
                     * _thc_dx + co2.alpha2 * dot_caco3 * w_phi_test * _thc_dx)

    for measure, flux in water_flux.items():
        water_balance -= ufl.inner(flux, w_phi_test) * measure

    co2_balance = (
        ufl.inner(1.0 / (dt * 24 * 60 * 60) *
                  (w1["co2"] - w0["co2"]), w_co2_test) * _thc_dx +
        ufl.inner(co2.D_co2 * ufl.grad(w1["co2"]), ufl.grad(w_co2_test)) *
        _thc_dx + co2.alpha4 * dot_caco3 * w_co2_test * _thc_dx)

    for measure, flux in co2_flux.items():
        co2_balance -= ufl.inner(flux, w_co2_test) * measure

    J_mom = ufl.derivative(mom_balance, w1["displ"], w_displ_trial)

    J_energy_temp = ufl.derivative(energy_balance, w1["temp"], w_temp_trial)
    J_energy_hum = ufl.derivative(energy_balance, w1["phi"], w_phi_trial)
    J_energy_co2 = ufl.derivative(energy_balance, w1["co2"], w_co2_trial)

    J_energy = J_energy_hum + J_energy_temp + J_energy_co2

    J_water_temp = ufl.derivative(water_balance, w1["temp"], w_temp_trial)
    J_water_hum = ufl.derivative(water_balance, w1["phi"], w_phi_trial)
    J_water_co2 = ufl.derivative(water_balance, w1["co2"], w_co2_trial)

    J_water = J_water_temp + J_water_hum + J_water_co2

    J_co2_temp = ufl.derivative(co2_balance, w1["temp"], w_temp_trial)
    J_co2_hum = ufl.derivative(co2_balance, w1["phi"], w_phi_trial)
    J_co2_co2 = ufl.derivative(co2_balance, w1["co2"], w_co2_trial)

    J_co2 = J_co2_temp + J_co2_hum + J_co2_co2

    # Put all Jacobians together
    J_all = J_mom + J_energy + J_water + J_co2

    # Lower algebra symbols and apply derivatives up to terminals
    # This is needed for the Replacer to work properly
    preserve_geometry_types = (ufl.CellVolume, ufl.FacetArea)
    J_all = ufl.algorithms.apply_algebra_lowering.apply_algebra_lowering(J_all)
    J_all = ufl.algorithms.apply_derivatives.apply_derivatives(J_all)
    J_all = ufl.algorithms.apply_geometry_lowering.apply_geometry_lowering(
        J_all, preserve_geometry_types)
    J_all = ufl.algorithms.apply_derivatives.apply_derivatives(J_all)
    J_all = ufl.algorithms.apply_geometry_lowering.apply_geometry_lowering(
        J_all, preserve_geometry_types)
    J_all = ufl.algorithms.apply_derivatives.apply_derivatives(J_all)

    J = extract_blocks(J_all,
                       [w_displ_test, w_temp_test, w_phi_test, w_co2_test],
                       [w_displ_trial, w_temp_trial, w_phi_trial, w_co2_trial])

    J[0][0]._signature = "full" if not damage_off else "dmgoff"

    # Just make sure these are really empty Forms
    assert len(J[1][0].arguments()) == 0
    assert len(J[2][0].arguments()) == 0
    assert len(J[3][0].arguments()) == 0

    F = [-mom_balance, -energy_balance, -water_balance, -co2_balance]

    rank = MPI.COMM_WORLD.rank

    if rank == 0:
        logger.info("Compiling tangents J...")
    J_compiled = [
        Form(J[0][0]),
        [[Form(J[i][j]) for j in range(1, 4)] for i in range(1, 4)]
    ]

    if rank == 0:
        logger.info("Compiling residuals F...")
    F_compiled = [Form(F[0]), [Form(F[i]) for i in range(1, 4)]]

    expr = OrderedDict()

    eta_dash1 = mps.eta_dash(iv0["eta_dash"], dt, w1["temp"], w1["phi"])
    expr["eta_dash"] = (eta_dash1,
                        iv0["eta_dash"].function_space.ufl_element())
    expr["caco3"] = (iv0["caco3"] + dt * 24 * 60 * 60 * dot_caco3,
                     iv0["caco3"].function_space.ufl_element())

    expr["eps_cr_kel"] = (iv0["eps_cr_kel"] + deps_cr_kel,
                          iv0["eps_cr_kel"].function_space.ufl_element())
    expr["eps_cr_dash"] = (iv0["eps_cr_dash"] + deps_cr_dash,
                           iv0["eps_cr_dash"].function_space.ufl_element())

    expr["eps_sh_dr"] = (iv0["eps_sh_dr"] + deps_sh_dr,
                         iv0["eps_sh_dr"].function_space.ufl_element())
    expr["eps_th"] = (iv0["eps_th"] + deps_th,
                      iv0["eps_th"].function_space.ufl_element())

    expr["sigma"] = (iv0["sigma"] + mech.stress(E_kelv, deps_el),
                     iv0["sigma"].function_space.ufl_element())
    expr["eps_eqv"] = (eps_eqv, iv0["eps_eqv"].function_space.ufl_element())
    expr["dmg"] = (dmg, iv0["dmg"].function_space.ufl_element())

    for i in range(mps.M):
        expr[f"gamma_{i}"] = (lambda_cr[i] * (iv1["sigma"] - iv0["sigma"]) +
                              (beta_cr[i]) * gamma0[i],
                              gamma0[i].function_space.ufl_element())

    expr_compiled = OrderedDict()
    for name, item in expr.items():
        if rank == 0:
            logger.info(f"Compiling expressions for {name}...")
        expr_compiled[name] = CompiledExpression(item[0], item[1])

    if rank == 0:
        logger.info(f"[Timer] UFL forms setup and compilation: {time() - t0}")

    return J_compiled, F_compiled, expr_compiled
# Total differential of yield function
df = + ufl.inner(ufl.diff(f, S), S - S0) \
     + ufl.inner(ufl.diff(f, h), h - h0) \
     + ufl.inner(ufl.diff(f, B), B - B0)

# Derivative of plastic potential wrt stress
dgdS = ufl.diff(g, S)

# Unwrap expression from variable
S, B, h = S.expression(), B.expression(), h.expression()

# Variation of Green-Lagrange strain
δE = dolfiny.expression.derivative(E, m, δm)

# Plastic multiplier (J2 plasticity: closed-form solution for return-map)
dλ = ufl.Max(f, 0)  # ppos = MacAuley bracket

# Weak form (as one-form)
F = + ufl.inner(δE, S) * dx \
    + ufl.inner(δP, (P - P0) - dλ * dgdS) * dx \
    + ufl.inner(δh, (h - h0) - dλ * bh * (qh * 1.00 - h)) * dx \
    + ufl.inner(δB, (B - B0) - dλ * bb * (qb * dgdS - B)) * dx

# Overall form (as list of forms)
F = dolfiny.function.extract_blocks(F, δm)

# Create output xdmf file -- open in Paraview with Xdmf3ReaderT
ofile = dolfiny.io.XDMFFile(comm, f"{name}.xdmf", "w")
# Write mesh, meshtags
ofile.write_mesh_meshtags(mesh, mts)
Esempio n. 21
0
def psi_plus_linear_elasticity_model_B(epsilon, lamda, mu):
    dim = 2
    bulk_mod = lamda + 2. * mu / dim
    tr_epsilon_plus = ufl.Max(fe.tr(epsilon), 0)
    return bulk_mod / 2. * tr_epsilon_plus**2 + mu * fe.inner(
        fe.dev(epsilon), fe.dev(epsilon))
def tau_dx():
    return rho * g * H_ * S.dx(0) * phibar


points, weights = full_quad(4)

vi = VerticalIntegrator(points, weights)

# Pressure and sliding law

normalx = (B.dx(0) + h_s.dx(0)) / df.sqrt((B.dx(0) + h_s.dx(0))**2 + 1.0)
normalz = df.sqrt(1 - normalx**2)

P_0 = H
P_w = ufl.Max(k * H, rho_w / rho_i * (l - Base))
N = ufl.Max(P_0 - P_w, df.Constant(0.000))
# tau_b = beta2 * u(1) * N
tau_b = (beta2 * (abs(N) + 1.0e-4)**(1.0 / n_sliding) *
         (abs(u(1)) + 1.0e-4)**(1.0 / n_sliding - 1) * u(1))
# tau_b = (
#     beta2
#     * (abs(u(1)) + 1.0) ** (1.0 / n - 1)
#     * u(1)
#     * (abs(N) + 1.0) ** (1.0 / n)
#     #    * (1 - normalx**2)
#     #    * grounded
# )

I_stress = (-vi.intz(membrane_xx) - vi.intz(shear_xz) - phi(1) * tau_b -
            tau_dx()) * df.dx
Esempio n. 23
0
def main(config_file):

    print("===WARNING=== - this code has not been fully adapted to new config format")
    print("Consult TODOs in run_balancemeltrates.py")

    init_yr = 5 #TODO - where in the config?

    #Read run config file
    params = ConfigParser(config_file)

    log = inout.setup_logging(params)
    inout.log_preamble("balance meltrates", params)

    dd = params.io.input_dir
    outdir = params.io.output_dir
    run_length = params.time.run_length
    n_steps = params.time.total_steps

    assert init_yr < run_length

    # #Load Data
    # param = pickle.load( open( os.path.join(dd,'param.p'), "rb" ) )

    # param['outdir'] = outdir
    # param['sliding_law'] = sl
    # param['picard_params'] = {"nonlinear_solver":"newton",
    #             "newton_solver":{"linear_solver":"umfpack",
    #             "maximum_iterations":25,
    #             "absolute_tolerance":1.0e-3,
    #             "relative_tolerance":5.0e-2,
    #             "convergence_criterion":"incremental",
    #             "error_on_nonconvergence":False,
    #             "lu_solver":{"same_nonzero_pattern":False, "symmetric":False, "reuse_factorization":False}}}

    #Load Data
    mesh = Mesh(os.path.join(outdir, 'mesh.xml'))

    M = FunctionSpace(mesh, 'DG', 0)
    #TODO - what's the logic here?:
    Q = FunctionSpace(mesh, 'Lagrange', 1)# if os.path.isfile(os.path.join(dd,'param.p')) else M

    mask = Function(M,os.path.join(outdir,'mask.xml'))

    if os.path.isfile(os.path.join(outdir,'data_mesh.xml')):
        data_mesh = Mesh(os.path.join(outdir,'data_mesh.xml'))
        Mdata = FunctionSpace(data_mesh, 'DG', 0)
        data_mask = Function(Mdata, os.path.join(outdir,'data_mask.xml'))
    else:
        data_mesh = mesh
        data_mask = mask

    if not params.mesh.periodic_bc:
       Qp = Q
       V = VectorFunctionSpace(mesh,'Lagrange',1,dim=2)
    else:
       Qp = fice_mesh.get_periodic_space(params, mesh, dim=1)
       V = fice_mesh.get_periodic_space(params, mesh, dim=2)

    #Load fields
    U = Function(V,os.path.join(outdir,'U.xml'))

    alpha = Function(Qp,os.path.join(outdir,'alpha.xml'))
    beta = Function(Qp,os.path.join(outdir,'beta.xml'))
    bed = Function(Q,os.path.join(outdir,'bed.xml'))

    smb = Function(M,os.path.join(outdir, 'smb.xml'))
    thick = Function(M,os.path.join(outdir,'thick.xml'))
    mask_vel = Function(M,os.path.join(outdir,'mask_vel.xml'))
    u_obs = Function(M,os.path.join(outdir,'u_obs.xml'))
    v_obs = Function(M,os.path.join(outdir,'v_obs.xml'))
    u_std = Function(M,os.path.join(outdir,'u_std.xml'))
    v_std = Function(M,os.path.join(outdir,'v_std.xml'))
    uv_obs = Function(M,os.path.join(outdir,'uv_obs.xml'))

    mdl = model.model(mesh, data_mask, params, init_fields=False)  # TODO initialization
    mdl.init_bed(bed)
    mdl.init_thick(thick)
    mdl.gen_surf()
    mdl.init_mask(mask)
    mdl.init_vel_obs(u_obs,v_obs,mask_vel,u_std,v_std)
    mdl.init_lat_dirichletbc()
    mdl.init_bmelt(Constant(0.0))
    mdl.init_alpha(alpha)
    mdl.init_beta(beta, False)
    mdl.init_smb(smb)
    mdl.label_domain()

    #Solve
    slvr = solver.ssa_solver(mdl)
    slvr.save_ts_zero()
    slvr.timestep(save = 1, adjoint_flag=0)

    #Balance melt rates

    #Load time series of ice thicknesses
    hdf = HDF5File(slvr.mesh.mpi_comm(), os.path.join(outdir, 'H_ts.h5'), "r")
    attr = hdf.attributes("H")
    nsteps = attr['count']

    #model time step
    dt = params.time.dt

    #Model iterations to difference between
    iter_s = np.ceil(init_yr/dt)  #Iteration closest to 5yr
    iter_f = nsteps - 1         #Final iteration
    dT = dt*(iter_f - iter_s) #Time diff in years between iterations

    #Read iteration data
    HS = Function(slvr.M)
    HF = Function(slvr.M)
    hdf.read(HS, "H/vector_{0}".format(int(iter_s)))
    hdf.read(HF, "H/vector_{0}".format(int(iter_f)))

    #Mask out grounded region
    rhow = params.constants.rhow
    rhoi = params.constants.rhoi
    H_s = -rhow/rhoi * bed
    fl_ex = conditional(slvr.H_init <= H_s, Constant(1.0), Constant(0.0))

    #Calculate bmelt
    bmelt = project(ufl.Max(fl_ex*(HF - HS)/dT, Constant(0.0)), slvr.M)

    #Output model variables in ParaView+Fenics friendly format
    pickle.dump( mdl.param, open( os.path.join(outdir,'bmeltrate_param.p'), "wb" ) )

    # File(os.path.join(outdir,'mesh.xml')) << mdl.mesh

    vtkfile = File(os.path.join(outdir,'bmelt.pvd'))
    xmlfile = File(os.path.join(outdir,'bmelt.xml'))
    vtkfile << bmelt
    xmlfile << bmelt

    return mdl
 def u_T(x, y):
     return ufl.Max(y - K, 0)