示例#1
0
    def initialize_solvers(self):
        # Kinematics                # Right Cauchy-Green tensor
        if self.nonlin:
            d = self.X.geometric_dimension()
            I = fd.Identity(d)  # Identity tensor
            F = I + fd.grad(self.X)  # Deformation gradient
            C = F.T * F
            E = (C - I) / 2.  # Green-Lagrangian strain
#            E = 1./2.*( fd.grad(self.X).T + fd.grad(self.X) + fd.grad(self.X).T * fd.grad(self.X) ) # alternative equivalent definition
        else:
            E = 1. / 2. * (fd.grad(self.X).T + fd.grad(self.X)
                           )  # linear strain

        self.W = (self.lam / 2.) * (fd.tr(E))**2 + self.mu * fd.tr(E * E)
        #        f = fd.Constant((0, 0, -self.g)) # body force / rho
        #        T = self.surface_force()

        # Total potential energy
        Pi = self.W * fd.dx
        # Compute first variation of Pi (directional derivative about X in the direction of v)
        F_expr = fd.derivative(Pi, self.X, self.v)

        self.DBC = fd.DirichletBC(self.V, fd.as_vector([0., 0., 0.]),
                                  self.bottom_id)

        #        delX = fd.nabla_grad(self.X)
        #        delv_B = fd.nabla_grad(self.v)
        #        T_x_dv = self.lam * fd.div(self.X) * fd.div(self.v) \
        #                + self.mu * ( fd.inner( delX, delv_B + fd.transpose(delv_B) ) )

        self.a_U = fd.dot(self.trial, self.v) * fd.dx
        #        self.L_U = ( fd.dot( self.U, self.v ) - self.dt/2./self.rho * T_x_dv ) * fd.dx
        self.L_U = fd.dot(
            self.U, self.v) * fd.dx - self.dt / 2. / self.rho * F_expr  #\
        #                  + self.dt/2./self.rho*fd.dot(T,self.v)*fd.ds(1) # surface force at x==0 plane
        # + self.dt/2.*fd.dot(f,self.v)*fd.dx # body force
        self.a_X = fd.dot(self.trial, self.v) * fd.dx
        #        self.L_interface = fd.dot(self.phi_vect, self.v) * fd.ds(self.interface_id)
        self.L_X = fd.dot((self.X + self.dt * self.U), self.v) * fd.dx  #\
        #                    - self.dt/self.rho * self.L_interface

        self.LVP_U = fd.LinearVariationalProblem(self.a_U,
                                                 self.L_U,
                                                 self.U,
                                                 bcs=[self.DBC])
        self.LVS_U = fd.LinearVariationalSolver(self.LVP_U)
        self.LVP_X = fd.LinearVariationalProblem(self.a_X,
                                                 self.L_X,
                                                 self.X,
                                                 bcs=[self.DBC])
        self.LVS_X = fd.LinearVariationalSolver(self.LVP_X)
示例#2
0
    def __init__(self, mesh, conditions, timestepping, params, output, solver_params):
        super().__init__(mesh, conditions, timestepping, params, output, solver_params)

        self.u0 = Function(self.V)
        self.u1 = Function(self.V)

        self.sigma0 = Function(self.S)
        self.sigma1 = Function(self.S)

        theta = conditions.theta
        uh = (1-theta) * self.u0 + theta * self.u1

        a = Function(self.U)
        h = Function(self.U)
        
        p = TestFunction(self.V)
        q = TestFunction(self.S)

        self.initial_condition((self.u0, conditions.ic['u']), (a, conditions.ic['a']), (h, conditions.ic['h']))
        
        ep_dot = self.strain(grad(uh))
        zeta = self.zeta(h, a, self.delta(uh))
        eta = zeta * params.e ** (-2)
        rheology = 2 * eta * ep_dot + (zeta - eta) * tr(ep_dot) * Identity(2) - 0.5 * self.Ice_Strength(h, a) * Identity(2)

        self.initial_condition((self.sigma0, rheology),(self.sigma1, self.sigma0))

        def sigma_next(timestep, zeta, ep_dot, sigma, P):
            A = 1 + 0.25 * (timestep * params.e ** 2) / params.T
            B = timestep * 0.125 * (1 - params.e ** 2) / params.T
            rhs = (1 - (timestep * params.e ** 2) / (4 * params.T)) * sigma - timestep / params.T * (
                    0.125 * (1 - params.e ** 2) * tr(sigma) * Identity(2) - 0.25 * P * Identity(2) + zeta * ep_dot)
            C = (rhs[0, 0] - rhs[1, 1]) / A
            D = (rhs[0, 0] + rhs[1, 1]) / (A + 2 * B)
            sigma00 = 0.5 * (C + D)
            sigma11 = 0.5 * (D - C)
            sigma01 = rhs[0, 1]
            sigma = as_matrix([[sigma00, sigma01], [sigma01, sigma11]])

            return sigma

        s = sigma_next(self.timestep, zeta, ep_dot, self.sigma0, self.Ice_Strength(h, a))

        sh = (1-theta) * s + theta * self.sigma0

        eqn = self.momentum_equation(h, self.u1, self.u0, p, sh, params.rho, uh, conditions.ocean_curr,
                                params.rho_a, params.C_a, params.rho_w, params.C_w, conditions.geo_wind, params.cor, self.timestep, ind=self.ind)

        tensor_eqn = inner(self.sigma1-s, q) * dx

        if conditions.stabilised['state']:
            alpha = conditions.stabilised['alpha']
            eqn += stabilisation_term(alpha=alpha, zeta=avg(zeta), mesh=mesh, v=uh, test=p)

        bcs = DirichletBC(self.V, conditions.bc['u'], "on_boundary")

        uprob = NonlinearVariationalProblem(eqn, self.u1, bcs)
        self.usolver = NonlinearVariationalSolver(uprob, solver_parameters=solver_params.bt_params)
        sprob = NonlinearVariationalProblem(tensor_eqn, self.sigma1)
        self.ssolver = NonlinearVariationalSolver(sprob, solver_parameters=solver_params.bt_params)
示例#3
0
    def __init__(self, mesh, conditions, timestepping, params, output, solver_params):
        super().__init__(mesh, conditions, timestepping, params, output, solver_params)
    
        self.u0 = Function(self.V)
        self.u1 = Function(self.V)
        self.h = Function(self.U)
        self.a = Function(self.U)
        
        self.p = TestFunction(self.V)

        theta = conditions.theta
        self.uh = (1-theta) * self.u0 + theta * self.u1

        ep_dot = self.strain(grad(self.uh))
        
        self.initial_condition((self.u0, conditions.ic['u']),(self.u1, self.u0),
                               (self.a, conditions.ic['a']),(self.h, conditions.ic['h']))

        zeta = self.zeta(self.h, self.a, self.delta(self.uh))
        eta = zeta * params.e ** -2
        sigma = 2 * eta * ep_dot + (zeta - eta) * tr(ep_dot) * Identity(2) - 0.5 * self.Ice_Strength(self.h,self.a) * Identity(2)

        self.eqn = self.momentum_equation(self.h, self.u1, self.u0, self.p, sigma, params.rho, self.uh,
                                          conditions.ocean_curr, params.rho_a, params.C_a, params.rho_w,
                                          params.C_w, conditions.geo_wind, params.cor, self.timestep)

        if conditions.stabilised['state']:
            alpha = conditions.stabilised['alpha']
            self.eqn += self.stabilisation_term(alpha=alpha, zeta=avg(zeta), mesh=mesh, v=self.uh, test=self.p)
            
        self.bcs = DirichletBC(self.V, conditions.bc['u'], "on_boundary")
示例#4
0
def eigenvalues(a):
    r"""Return a pair of symbolic expressions for the largest and smallest
    eigenvalues of a 2D rank-2 tensor"""
    tr_a = tr(a)
    det_a = det(a)
    # TODO: Fret about numerical stability
    Δ = sqrt(tr_a**2 - 4 * det_a)
    return ((tr_a + Δ) / 2, (tr_a - Δ) / 2)
示例#5
0
 def derivative(self, out):
     super().derivative(out)
     if args.discretisation != "pkp0":
         return
     w = fd.TestFunction(self.V_m)
     u = solver.z.split()[0]
     v = solver.z_adj.split()[0]
     from firedrake import div, cell_avg, dx, tr, grad
     gamma = solver.gamma
     deriv = gamma * div(w) * cell_avg(div(u)) * div(v) * dx \
         + gamma * (cell_avg(div(u) * div(w) - tr(grad(u)*grad(w)))
                    - cell_avg(div(u)) * cell_avg(div(w))) * div(v) * dx \
         - gamma * cell_avg(div(u)) * tr(grad(v)*grad(w)) * dx
     fd.assemble(deriv,
                 tensor=self.deriv_m,
                 form_compiler_parameters=self.params)
     outcopy = out.clone()
     outcopy.from_first_derivative(self.deriv_r)
     fd.warning(fd.RED % ("norm of extra term %e" % outcopy.norm()))
     out.plus(outcopy)
示例#6
0
def hyperelasticity(mesh, degree):
    V = VectorFunctionSpace(mesh, 'Q', degree)
    v = TestFunction(V)
    du = TrialFunction(V)  # Incremental displacement
    u = Function(V)  # Displacement from previous iteration
    B = Function(V)  # Body force per unit mass
    # Kinematics
    I = Identity(mesh.topological_dimension())
    F = I + grad(u)  # Deformation gradient
    C = F.T * F  # Right Cauchy-Green tensor
    E = (C - I) / 2  # Euler-Lagrange strain tensor
    E = variable(E)
    # Material constants
    mu = Constant(1.0)  # Lame's constants
    lmbda = Constant(0.001)
    # Strain energy function (material model)
    psi = lmbda / 2 * (tr(E)**2) + mu * tr(E * E)
    S = diff(psi, E)  # Second Piola-Kirchhoff stress tensor
    PK = F * S  # First Piola-Kirchoff stress tensor
    # Variational problem
    return derivative((inner(PK, grad(v)) - inner(B, v)) * dx, u, du)
示例#7
0
        def sigma_next(timestep, zeta, ep_dot, sigma, P):
            A = 1 + 0.25 * (timestep * params.e ** 2) / params.T
            B = timestep * 0.125 * (1 - params.e ** 2) / params.T
            rhs = (1 - (timestep * params.e ** 2) / (4 * params.T)) * sigma - timestep / params.T * (
                    0.125 * (1 - params.e ** 2) * tr(sigma) * Identity(2) - 0.25 * P * Identity(2) + zeta * ep_dot)
            C = (rhs[0, 0] - rhs[1, 1]) / A
            D = (rhs[0, 0] + rhs[1, 1]) / (A + 2 * B)
            sigma00 = 0.5 * (C + D)
            sigma11 = 0.5 * (D - C)
            sigma01 = rhs[0, 1]
            sigma = as_matrix([[sigma00, sigma01], [sigma01, sigma11]])

            return sigma
示例#8
0
    def __init__(self, mesh, conditions, timestepping, params, output, solver_params):
        super().__init__(mesh, conditions, timestepping, params, output, solver_params)

        self.w0 = Function(self.W3)
        self.w1 = Function(self.W3)

        u0, s0, h0, a0 = self.w0.split()

        p, q, r, m = TestFunctions(self.W3)

        self.initial_condition((u0, conditions.ic['u']), (s0, conditions.ic['s']),
                               (a0, conditions.ic['a']), (h0, conditions.ic['h']))

        self.w1.assign(self.w0)

        u1, s1, h1, a1 = split(self.w1)
        u0, s0, h0, a0 = split(self.w0)

        theta = conditions.theta
        uh = (1-theta) * u0 + theta * u1
        sh = (1-theta) * s0 + theta * s1
        hh = (1-theta) * h0 + theta * h1
        ah = (1-theta) * a0 + theta * a1

        ep_dot = self.strain(grad(uh))
        zeta = self.zeta(hh, ah, self.delta(uh))

        rheology = params.e ** 2 * sh + Identity(2) * 0.5 * ((1 - params.e ** 2) * tr(sh) + self.Ice_Strength(hh, ah))
        
        eqn = self.momentum_equation(hh, u1, u0, p, sh, params.rho, uh, conditions.ocean_curr, params.rho_a,
                                params.C_a, params.rho_w, params.C_w, conditions.geo_wind, params.cor, self.timestep, ind=self.ind)
        eqn += self.transport_equation(uh, hh, ah, h1, h0, a1, a0, r, m, self.n, self.timestep)
        eqn += inner(self.ind * (s1 - s0) + 0.5 * self.timestep * rheology / params.T, q) * dx
        eqn -= inner(q * zeta * self.timestep / params.T, ep_dot) * dx

        if conditions.stabilised['state']:
            alpha = conditions.stabilised['alpha']
            eqn += self.stabilisation_term(alpha=alpha, zeta=avg(zeta), mesh=mesh, v=uh, test=p)

        bcs = DirichletBC(self.W3.sub(0), conditions.bc['u'], "on_boundary")

        uprob = NonlinearVariationalProblem(eqn, self.w1, bcs)
        self.usolver = NonlinearVariationalSolver(uprob, solver_parameters=solver_params.bt_params)

        self.u1, self.s0, self.h1, self.a1 = self.w1.split()
示例#9
0
    def __init__(self, mesh, conditions, timestepping, params, output, solver_params):
        super().__init__(mesh, conditions, timestepping, params, output, solver_params)

        self.w0 = Function(self.W2)
        self.w1 = Function(self.W2)

        u0, h0, a0 = self.w0.split()

        p, q, r = TestFunctions(self.W2)

        self.initial_condition((u0, conditions.ic['u']), (h0, conditions.ic['h']),
                               (a0, conditions.ic['a']))

        self.w1.assign(self.w0)
        u1, h1, a1 = split(self.w1)
        u0, h0, a0 = split(self.w0)

        theta = conditions.theta
        uh = (1-theta) * u0 + theta * u1
        ah = (1-theta) * a0 + theta * a1
        hh = (1-theta) * h0 + theta * h1

        ep_dot = self.strain(grad(uh))
        zeta = self.zeta(hh, ah, self.delta(uh))
        eta = zeta * params.e ** (-2)
        sigma = 2 * eta * ep_dot + (zeta - eta) * tr(ep_dot) * Identity(2) - self.Ice_Strength(hh, ah) * 0.5 * Identity(
            2)

        eqn = self.momentum_equation(hh, u1, u0, p, sigma, params.rho, uh, conditions.ocean_curr, params.rho_a,
                                params.C_a, params.rho_w, params.C_w, conditions.geo_wind, params.cor, self.timestep)
        eqn += self.transport_equation(uh, hh, ah, h1, h0, a1, a0, q, r, self.n, self.timestep)

        if conditions.stabilised['state']:
            alpha = conditions.stabilised['alpha']
            eqn += self.stabilisation_term(alpha=alpha, zeta=avg(zeta), mesh=mesh, v=uh, test=p)

        bcs = DirichletBC(self.W2.sub(0), conditions.bc['u'], "on_boundary")

        uprob = NonlinearVariationalProblem(eqn, self.w1, bcs)
        self.usolver = NonlinearVariationalSolver(uprob, solver_parameters=solver_params.bt_params)

        self.u1, self.h1, self.a1 = self.w1.split()
示例#10
0
 def sigma(v):
     return 2.0 * mu * epsilon(v) + lmbda * tr(epsilon(v)) * Identity(2)
示例#11
0
 def delta(self, u):
     return sqrt(self.params.Delta_min ** 2 + 2 * self.params.e ** (-2) * inner(dev(self.strain(grad(u))),
                                                                                dev(self.strain(grad(u)))) + tr(
         self.strain(grad(u))) ** 2)
示例#12
0
    def __init__(self, mesh, conditions, timestepping, params, output, solver_params):
        super().__init__(mesh, conditions, timestepping, params, output, solver_params)

        self.w0 = Function(self.W1)
        self.w1 = Function(self.W1)
        self.a = Function(self.U)
        self.h = Function(self.U)

        self.u0, self.s0 = self.w0.split()
        self.p, self.q = TestFunctions(self.W1)

        self.initial_condition((self.u0, conditions.ic['u']), (self.s0, conditions.ic['s']),
                               (self.a, conditions.ic['a']), (self.h, conditions.ic['h']))

        self.w1.assign(self.w0)
        u1, s1 = split(self.w1)
        u0, s0 = split(self.w0)

        theta = conditions.theta
        uh = (1-theta) * u0 + theta * u1
        sh = (1-theta) * s0 + theta * s1

        self.ep_dot = self.strain(grad(uh))
        zeta = self.zeta(self.h, self.a, self.delta(uh))
        self.rheology = params.e ** 2 * sh + Identity(2) * 0.5 * ((1 - params.e ** 2) * tr(sh) + self.Ice_Strength(self.h, self.a))
        
        self.eqn = self.momentum_equation(self.h, u1, u0, self.p, sh, params.rho, uh, conditions.ocean_curr, params.rho_a,
                                          params.C_a, params.rho_w, params.C_w, conditions.geo_wind, params.cor, self.timestep, ind=self.ind)
        self.eqn += inner(self.ind * (s1 - s0) + 0.5 * self.timestep * self.rheology / params.T, self.q) * dx
        self.eqn -= inner(self.q * zeta * self.timestep / params.T, self.ep_dot) * dx

        if conditions.stabilised['state']:
            alpha = conditions.stabilised['alpha']
            self.eqn += self.stabilisation_term(alpha=alpha, zeta=avg(zeta), mesh=mesh, v=uh, test=self.p)
            
        self.bcs = DirichletBC(self.W1.sub(0), conditions.bc['u'], "on_boundary")
示例#13
0
def trace(A):
    r"""Compute the trace of a rank-2 tensor"""
    axes = get_mesh_axes(A.ufl_domain())
    if axes in ["x", "xz"]:
        return A
    return firedrake.tr(A)