Exemplo n.º 1
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
Exemplo n.º 2
0
    def sliding_law(self, alpha, U):

        constants = self.params.constants

        bed = self.bed
        H = self.H
        rhoi = constants.rhoi
        rhow = constants.rhow
        g = constants.g
        sl = self.params.ice_dynamics.sliding_law
        vel_rp = constants.vel_rp

        fl_ex = self.float_conditional(H)

        C = alpha * alpha
        u, v = split(U)

        if sl == 'linear':
            B2 = C

        elif sl == 'weertman':
            N = (1 - fl_ex) * (H * rhoi * g + ufl.Min(bed, 0.0) * rhow * g)
            U_mag = sqrt(U[0]**2 + U[1]**2 + vel_rp**2)
            # Need to catch N <= 0.0 here, as it's raised to
            # 1/3 (forward) and -2/3 (adjoint)
            N_term = ufl.conditional(N > 0.0, N**(1.0 / 3.0), 0)
            B2 = (1 - fl_ex) * (C * N_term * U_mag**(-2.0 / 3.0))

        return B2
Exemplo n.º 3
0
def damage(eps_eqv, mesh, E, f_t, G_f):
    h_cb = ufl.CellVolume(mesh) ** (1 / 3)
    eps0 = f_t / E

    eps_f = G_f / 1.0e+6 / (f_t * h_cb) + eps0 / 2

    dmg = ufl.Min(1.0 - eps0 / eps_eqv * ufl.exp(- (eps_eqv - eps0) / (eps_f - eps0)), 1.0 - dmg_eps)
    return ufl.conditional(eps_eqv <= eps0, 0.0, 0.0 if args.damage_off else dmg)
Exemplo n.º 4
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')
Exemplo n.º 5
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)))
Exemplo 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)))
Exemplo n.º 8
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)')]
Exemplo n.º 10
0
def distance_function_segments_ufl(P, control_points, impact_radii):
    if len(control_points) == 1:
        return distance_function_point_ufl(P,
                                           control_points[0]), impact_radii[0]
    else:
        rho1 = impact_radii[0]
        rho2 = impact_radii[1]
        df, xi = distance_function_line_segement_ufl(P, control_points[0],
                                                     control_points[1])
        for i in range(len(control_points) - 1):
            tmp_df, tmp_xi = distance_function_line_segement_ufl(
                P, control_points[i], control_points[i + 1])
            xi = fe.conditional(fe.lt(tmp_df, df), tmp_xi, xi)
            rho1 = fe.conditional(fe.lt(tmp_df, df), impact_radii[i], rho1)
            rho2 = fe.conditional(fe.lt(tmp_df, df), impact_radii[i + 1], rho2)
            df = ufl.Min(tmp_df, df)
        return df, (1 - xi) * rho1 + xi * rho2
Exemplo n.º 11
0
def stableNeumannBC(traction,
                    rho,
                    u,
                    v,
                    n,
                    g=None,
                    ds=ds,
                    gamma=Constant(1.0)):
    """
    This function returns the boundary contribution of a stable Neumann BC
    corresponding to a boundary ``traction`` when the velocity ``u`` (with 
    corresponding test function ``v``) is flowing out of the domain, 
    as determined by comparison with the outward-pointing normal, ``n``.  
    The optional velocity ``g`` can be used to offset the boundary velocity,
    as when this term is used to obtain a(n inflow-
    stabilized) consistent traction for weak enforcement of Dirichlet BCs.  
    The paramter ``gamma`` can optionally be used to scale the
    inflow term.  The BC is integrated using the optionally-specified 
    boundary measure ``ds``, which defaults to the entire boundary.

    NOTE: The sign convention here assumes that the return value is 
    ADDED to the residual given by ``interiorResidual``.

    NOTE: The boundary traction enforced differs from ``traction`` if 
    ``gamma`` is nonzero.  A pure traction BC is not generally stable,
    which is why the default ``gamma`` is one.  See

    https://www.oden.utexas.edu/media/reports/2004/0431.pdf

    for theory in the advection--diffusion model problem, and 

    https://doi.org/10.1007/s00466-011-0599-0

    for discussion in the context of Navier--Stokes.  
    """
    if (g == None):
        u_minus_g = u
    else:
        u_minus_g = u - g
    return -(inner(traction, v) + gamma * rho *
             ufl.Min(inner(u, n), Constant(0.0)) * inner(u_minus_g, v)) * ds
Exemplo 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
def norm2(u, eps=0.0):
    return sqrt(inner(u, u) + eps**2)


c_s = sqrt((K + 4.0 * mu / 3.0) / rho)
dxi_dxiHat = 0.5 * ufl.Jacobian(spline.mesh)
dx_dxi = spline.parametricGrad(spline.F + u_alpha)
dx_dxiHat = dx_dxi * dxi_dxiHat
dxiHat_dx = inv(dx_dxiHat)
G = dxiHat_dx.T * dxiHat_dx
h_K2 = tr(inv(G))
h = sqrt(h_K2)
nu_DC_res = h*C_DC*norm2(resLHS_strong(uddot_alpha,u_alpha)-f)\
            /norm2(gradx(u_alpha,udot_alpha),eps=Constant(DOLFIN_EPS))
nu_DC_max = 0.5 * rho / J(u_alpha) * C_max * c_s * h
nu_DC = ufl.Min(nu_DC_res, nu_DC_max)


def D_op(u, udot):
    return sym(gradx(u, udot))
res_DC = nu_DC*inner(D_op(u_alpha,udot_alpha),D_op(u_alpha,w))\
         *J(u_alpha)*spline.dx

# Residual of the variational formulation:
res = res_weak
if (not GALERKIN):
    res += res_DC

# Linearization and definition of a nonlinear problem:
tangent = derivative(res, u)
problem = ExtractedNonlinearProblem(spline, res, tangent, u)
Exemplo n.º 14
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)
Exemplo n.º 15
0
def visc(u):
    # second invariant of strain
    eps_dot = sqrt(0.5 * inner(sym(grad(u)), sym(grad(u))))
    nu_out = glen_fact * eps_dot**((1.0 - nglen) / nglen)
    #     return nu_out
    return ufl.Min(nu_out, 2e15)  # would introduce a viscosity limit
Exemplo n.º 16
0
def psi_minus_linear_elasticity_model_B(epsilon, lamda, mu):
    dim = 2
    bulk_mod = lamda + 2. * mu / dim
    tr_epsilon_minus = ufl.Min(fe.tr(epsilon), 0)
    return bulk_mod / 2. * tr_epsilon_minus**2