示例#1
0
    def vert_integrate(self, u):
        """
    Integrate <u> from the surface to the bed.
    """
        s = '::: vertically integrating function :::'
        print_text(s, self.D1Model_color)

        ff = self.ff
        Q = self.Q
        phi = TestFunction(Q)
        v = TrialFunction(Q)

        # surface Dirichlet boundary :
        def surface(x, on_boundary):
            return on_boundary and x[0] == self.S_bc

        # integral is zero on surface
        bcs = DirichletBC(Q, 0.0, surface)
        a = v.dx(0) * phi * dx
        L = u * phi * dx
        v = Function(Q)
        solve(a == L, v, bcs, annotate=False)
        print_min_max(v, 'vertically integrated function')
        #print_min_max(v, 'vertically integrated %s' % u.name())
        return v
示例#2
0
  def solve(self, annotate=False):
    """ 
    Perform the Newton solve of the full-Stokes equations 
    """
    model  = self.model
    params = self.solve_params
    
    # solve nonlinear system :
    rtol   = params['solver']['newton_solver']['relative_tolerance']
    maxit  = params['solver']['newton_solver']['maximum_iterations']
    alpha  = params['solver']['newton_solver']['relaxation_parameter']
    s      = "::: solving BP horizontal velocity with %i max iterations" + \
             " and step size = %.1f :::"
    print_text(s % (maxit, alpha), self.color())
    
    # zero out self.velocity for good convergence for any subsequent solves,
    # e.g. model.L_curve() :
    model.assign_variable(self.get_U(), DOLFIN_EPS, cls=self)
    
    # compute solution :
    solve(self.mom_F == 0, self.G, J = self.mom_Jac, bcs = self.mom_bcs,
          annotate = annotate, solver_parameters = params['solver'])
    U, p = self.G.split()
    u, v, w = split(U)

    self.assx.assign(model.u, project(u, model.Q, annotate=False),
                     annotate=False)
    self.assy.assign(model.v, project(v, model.Q, annotate=False),
                     annotate=False)
    self.assz.assign(model.w, project(w, model.Q, annotate=False),
                     annotate=False)
    self.assp.assign(model.p, p, annotate=False)

    print_min_max(model.U3, 'U', cls=self)
    print_min_max(model.p,  'p', cls=self)
示例#3
0
 def init_rho(self, rho):
     """
 """
     s = "::: initializing density :::"
     print_text(s, self.D1Model_color)
     self.assign_variable(self.rho, rho)
     print_min_max(self.rho, 'rho')
示例#4
0
    def vert_integrate(self, u, d='up', Q='self'):
        """
    Integrate <u> from the bed to the surface.
    """
        s = "::: vertically integrating function :::"
        print_text(s, cls=self)

        if type(Q) != FunctionSpace:
            Q = self.Q
        ff = self.ff
        phi = TestFunction(Q)
        v = TrialFunction(Q)
        bcs = []
        # integral is zero on bed (ff = 3,5)
        if d == 'up':
            bcs.append(DirichletBC(Q, 0.0, ff, self.GAMMA_B_GND))  # grounded
            bcs.append(DirichletBC(Q, 0.0, ff, self.GAMMA_B_FLT))  # shelves
            a = v.dx(2) * phi * dx
        # integral is zero on surface (ff = 2,6)
        elif d == 'down':
            bcs.append(DirichletBC(Q, 0.0, ff, self.GAMMA_S_GND))  # grounded
            bcs.append(DirichletBC(Q, 0.0, ff, self.GAMMA_S_FLT))  # shelves
            bcs.append(DirichletBC(Q, 0.0, ff, self.GAMMA_U_GND))  # grounded
            bcs.append(DirichletBC(Q, 0.0, ff, self.GAMMA_U_FLT))  # shelves
            a = -v.dx(2) * phi * dx
        L = u * phi * dx
        name = 'value integrated %s' % d
        v = Function(Q, name=name)
        solve(a == L, v, bcs, annotate=False)
        print_min_max(u, 'vertically integrated function', cls=self)
        return v
示例#5
0
 def init_r(self, r):
     """
 """
     s = "::: initializing grain-size :::"
     print_text(s, self.D1Model_color)
     self.assign_variable(self.r, r)
     print_min_max(self.r, 'r^2')
示例#6
0
 def init_B_bc(self, B_bc):
     """
 Set the scalar-value for bed.
 """
     s = "::: initializng bed boundary condition :::"
     print_text(s, self.D1Model_color)
     self.B_bc = B_bc
     print_min_max(self.B_bc, 'B_bc')
示例#7
0
 def init_S_bc(self, S_bc):
     """
 Set the scalar-value for the surface. 
 """
     s = "::: initializng surface boundary condition :::"
     print_text(s, self.D1Model_color)
     self.S_bc = S_bc
     print_min_max(self.S_bc, 'S_bc')
示例#8
0
 def init_adot(self, adot):
     """
 """
     s = "::: initializing accumulation :::"
     print_text(s, self.D1Model_color)
     self.assign_variable(self.adot, adot)
     self.assign_variable(self.bdot, self.rhoi(0) * adot / self.spy(0))
     print_min_max(self.adot, 'adot')
     print_min_max(self.bdot, 'bdot')
示例#9
0
 def calc_thickness(self):
     """
 Calculate the continuous thickness field which increases from 0 at the 
 surface to the actual thickness at the bed.
 """
     s = "::: calculating z-varying thickness :::"
     print_text(s, cls=self)
     #H = project(self.S - self.x[2], self.Q, annotate=False)
     H = self.vert_integrate(Constant(1.0), d='down')
     Hv = H.vector()
     Hv[Hv < 0] = 0.0
     print_min_max(H, 'H', cls=self)
     return H
示例#10
0
  def solve(self, annotate=False):
    """ 
    Perform the Newton solve of the full-Stokes equations 
    """
    model  = self.model
    params = self.solve_params
    
    # solve nonlinear system :
    rtol   = params['solver']['newton_solver']['relative_tolerance']
    maxit  = params['solver']['newton_solver']['maximum_iterations']
    alpha  = params['solver']['newton_solver']['relaxation_parameter']
    s    = "::: solving Dukowicz-Brinkerhoff-full-Stokes equations" + \
           " with %i max iterations and step size = %.1f :::"
    print_text(s % (maxit, alpha), self.color())
    
    # zero out self.velocity for good convergence for any subsequent solves,
    # e.g. model.L_curve() :
    model.assign_variable(self.get_U(), DOLFIN_EPS, cls=self)
    
    # compute solution :
    solve(self.mom_F == 0, self.U, J = self.mom_Jac, bcs = self.mom_bcs,
          annotate = annotate, solver_parameters = params['solver'])
    u, v, w, p = self.U.split()
    
    self.assx.assign(model.u, u, annotate=False)
    self.assy.assign(model.v, v, annotate=False)
    self.assz.assign(model.w, w, annotate=False)
    self.assp.assign(model.p, p, annotate=False)
    
    U3 = model.U3.split(True)

    print_min_max(U3[0],   'u', cls=self)
    print_min_max(U3[1],   'v', cls=self)
    print_min_max(U3[2],   'w', cls=self)
    print_min_max(model.p, 'p', cls=self)
示例#11
0
    def solve_compaction_velocity(self, annotate=True):
        """
    """
        s = "::: solving firn compaction velocity :::"
        print_text(s, self.color())

        w_delta = self.w_delta
        model = self.model

        # linear solve :
        solve(lhs(w_delta) == rhs(w_delta),
              model.w,
              self.wBc,
              annotate=annotate)
        print_min_max(model.w, 'w')
示例#12
0
    def solve(self):
        """
    """
        model = self.model

        s = "::: solving 'SSA_Balance' for flow direction :::"
        print_text(s, self.color())
        solve(lhs(self.delta) == rhs(self.delta), self.U_s)
        u_s, u_t = self.U_s.split(True)
        model.assign_variable(model.u_s, u_s)
        model.assign_variable(model.u_t, u_t)
        print_min_max(model.u_s, 'u_s')
        print_min_max(model.u_t, 'u_t')

        # solve for the individual stresses now that the corrected velocities
        # are found.
        self.solve_component_stress()
示例#13
0
 def calc_vert_average(self, u):
     """
 Calculates the vertical average of a given function space and function.  
 
 :param u: Function representing the model's function space
 :rtype:   Dolfin projection and Function of the vertical average
 """
     H = self.S - self.B
     uhat = self.vert_integrate(u, d='up')
     s = "::: calculating vertical average :::"
     print_text(s, cls=self)
     ubar = project(uhat / H, self.Q, annotate=False)
     print_min_max(ubar, 'ubar', cls=self)
     name = "vertical average of %s" % u.name()
     ubar.rename(name, '')
     ubar = self.vert_extrude(ubar, d='down')
     return ubar
示例#14
0
    def rhs_func_explicit(self, t, S, *f_args):
        """
    This function calculates the change in height of the surface of the
    ice sheet.
    
    :param t : Time
    :param S : Current height of the ice sheet
    :rtype   : Array containing rate of change of the ice surface values
    """
        model = self.model
        config = self.config
        thklim = config['free_surface']['thklim']
        B = model.B.compute_vertex_values()
        S[(S - B) < thklim] = thklim + B[(S - B) < thklim]

        # the surface is never on a periodic FunctionSpace :
        if config['periodic_boundary_conditions']:
            d2v = dof_to_vertex_map(model.Q_non_periodic)
        else:
            d2v = dof_to_vertex_map(model.Q)

        model.assign_variable(model.S, S[d2v])

        if config['velocity']['on']:
            model.U.vector()[:] = 0.0
            self.velocity_instance.solve()
            if config['velocity']['log']:
                U = project(as_vector([model.u, model.v, model.w]))
                s = '::: saving velocity U.pvd file :::'
                print_text(s, self.color())
                self.file_U << U
            print_min_max(U, 'U')

        if config['surface_climate']['on']:
            self.surface_climate_instance.solve()

        if config['free_surface']['on']:
            self.surface_instance.solve()
            if self.config['log']:
                s = '::: saving surface S.pvd file :::'
                print_text(s, self.color())
                self.file_S << model.S
            print_min_max(model.S, 'S')

        return model.dSdt.compute_vertex_values()
示例#15
0
    def solve_adjoint_momentum(self, H):
        """
    Solves for the adjoint variables self.Lam from the Hamiltonian <H>.
    """
        U = self.get_U()
        Phi = self.get_Phi()
        Lam = self.get_Lam()

        # we desire the derivative of the Hamiltonian w.r.t. the model state U
        # in the direction of the test function Phi to vanish :
        dI = derivative(H, U, Phi)

        s = "::: solving adjoint momentum :::"
        print_text(s, self.color())

        aw = assemble(lhs(dI))
        Lw = assemble(rhs(dI))

        a_solver = KrylovSolver('cg', 'hypre_amg')
        a_solver.solve(aw, Lam.vector(), Lw, annotate=False)

        #lam_nx, lam_ny = model.Lam.split(True)
        #lam_ix, lam_iy = model.Lam.split()

        #if self.config['adjoint']['surface_integral'] == 'shelves':
        #  lam_nx.vector()[model.gnd_dofs] = 0.0
        #  lam_ny.vector()[model.gnd_dofs] = 0.0
        #elif self.config['adjoint']['surface_integral'] == 'grounded':
        #  lam_nx.vector()[model.shf_dofs] = 0.0
        #  lam_ny.vector()[model.shf_dofs] = 0.0

        ## function assigner translates between mixed space and P1 space :
        #U_sp = model.U.function_space()
        #assx = FunctionAssigner(U_sp.sub(0), lam_nx.function_space())
        #assy = FunctionAssigner(U_sp.sub(1), lam_ny.function_space())

        #assx.assign(lam_ix, lam_nx)
        #assy.assign(lam_iy, lam_ny)

        #solve(self.aw == self.Lw, model.Lam,
        #      solver_parameters = {"linear_solver"  : "cg",
        #                           "preconditioner" : "hypre_amg"},
        #      annotate=False)
        #print_min_max(norm(model.Lam), '||Lam||')
        print_min_max(Lam, 'Lam')
示例#16
0
        def deriv_cb(I, dI, c):
            global counter, Rs, Js, J1s, J2s
            if method == 'ipopt':
                s0 = '>>> '
                s1 = 'iteration %i (max %i) complete'
                s2 = ' <<<'
                text0 = get_text(s0, 'red', 1)
                text1 = get_text(s1 % (counter, max_iter), 'red')
                text2 = get_text(s2, 'red', 1)
                if MPI.rank(mpi_comm_world()) == 0:
                    print text0 + text1 + text2
                counter += 1
            s = '::: adjoint obj. gradient post callback function :::'
            print_text(s, cls=self)
            print_min_max(dI, 'dI/dcontrol', cls=self)

            # update the DA current velocity to the model for evaluation
            # purposes only; the model.assign_variable function is
            # annotated for purposes of linking physics models to the adjoint
            # process :
            u_opt = DolfinAdjointVariable(model.U3).tape_value()
            model.init_U(u_opt, cls=self)

            # print functional values :
            control.assign(c, annotate=False)
            ftnls = self.calc_functionals()
            D = self.calc_misfit()

            # functional lists to be populated :
            Rs.append(ftnls[0])
            Js.append(ftnls[1])
            Ds.append(D)
            if self.obj_ftn_type == 'log_L2_hybrid':
                J1s.append(ftnls[2])
                J2s.append(ftnls[3])
            if self.reg_ftn_type == 'TV_Tik_hybrid':
                R1s.append(ftnls[4])
                R2s.append(ftnls[5])

            # call that callback, if you want :
            if adj_callback is not None:
                adj_callback(I, dI, c)
示例#17
0
    def solve(self):
        """
    """
        config = self.config

        self.assign_variable(self.Shat, self.S)
        self.assign_variable(self.ahat, self.adot)
        self.assign_variable(self.uhat, self.u)
        self.assign_variable(self.vhat, self.v)
        self.assign_variable(self.what, self.w)

        m = assemble(self.mass_matrix, keep_diagonal=True)
        r = assemble(self.stiffness_matrix, keep_diagonal=True)

        s = "::: solving free-surface :::"
        print_text(s, self.D3Model_color)
        if config['free_surface']['lump_mass_matrix']:
            m_l = assemble(self.lumped_mass)
            m_l = m_l.get_local()
            m_l[m_l == 0.0] = 1.0
            m_l_inv = 1. / m_l

        if config['free_surface']['static_boundary_conditions']:
            self.static_boundary.apply(m, r)

        if config['free_surface']['use_shock_capturing']:
            k = assemble(self.diffusion_matrix)
            r -= k
            print_min_max(r, 'D')

        if config['free_surface']['lump_mass_matrix']:
            self.assign_variable(self.dSdt, m_l_inv * r.get_local())
        else:
            m.ident_zeros()
            solve(m, self.dSdt.vector(), r, annotate=False)

        A = assemble(lhs(self.A_pro))
        p = assemble(rhs(self.A_pro))
        q = Vector()
        solve(A, q, p, annotate=False)
        self.assign_variable(self.dSdt, q)
示例#18
0
    def unify_eta(self):
        """
    Unifies viscosity defined over grounded and shelves to model.eta.
    """
        s = "::: unifying viscosity on shelf and grounded areas to model.eta :::"
        print_text(s, self.color())

        model = self.model

        num_shf = MPI.sum(mpi_comm_world(), len(model.shf_dofs))
        num_gnd = MPI.sum(mpi_comm_world(), len(model.gnd_dofs))

        print_min_max(num_shf, 'number of floating vertices')
        print_min_max(num_gnd, 'number of grounded vertices')

        if num_gnd == 0 and num_shf == 0:
            s = "    - floating and grounded regions have not been marked -"
            print_text(s, self.color())

        elif num_gnd == 0:
            s = "    - all floating ice, assigning eta_shf to eta  -"
            print_text(s, self.color())
            model.init_eta(project(self.eta_shf, model.Q))

        elif num_shf == 0:
            s = "    - all grounded ice, assigning eta_gnd to eta -"
            print_text(s, self.color())
            model.init_eta(project(self.eta_gnd, model.Q))

        else:
            s = "    - grounded and floating ice present, unifying eta -"
            print_text(s, self.color())
            eta_shf = project(self.eta_shf, model.Q)
            eta_gnd = project(self.eta_gnd, model.Q)

            # remove areas where viscosities overlap :
            eta_shf.vector()[model.gnd_dofs] = 0.0
            eta_gnd.vector()[model.shf_dofs] = 0.0

            # unify eta to self.eta :
            model.init_eta(eta_shf.vector() + eta_gnd.vector())
示例#19
0
    def solve(self, annotate=False):
        """ 
    Perform the Newton solve of the first order equations 
    """

        model = self.model
        params = self.solve_params

        # solve nonlinear system :
        rtol = params['solver']['newton_solver']['relative_tolerance']
        maxit = params['solver']['newton_solver']['maximum_iterations']
        alpha = params['solver']['newton_solver']['relaxation_parameter']
        s      = "::: solving Dukowicz BP horizontal velocity with %i max" + \
                 " iterations and step size = %.1f :::"
        print_text(s % (maxit, alpha), self.color())

        # zero out self.velocity for good convergence for any subsequent solves,
        # e.g. model.L_curve() :
        model.assign_variable(self.get_U(), DOLFIN_EPS, cls=self)

        # compute solution :
        solve(self.mom_F == 0,
              self.U,
              J=self.mom_Jac,
              bcs=self.mom_bcs,
              annotate=annotate,
              solver_parameters=params['solver'])
        u, v = self.U.split()

        self.assx.assign(model.u, u, annotate=annotate)
        self.assy.assign(model.v, v, annotate=annotate)

        u, v, w = model.U3.split(True)
        print_min_max(u, 'u', cls=self)
        print_min_max(v, 'v', cls=self)

        if params['solve_vert_velocity']:
            self.solve_vert_velocity(annotate)
        if params['solve_pressure']:
            self.solve_pressure(annotate=False)
示例#20
0
 def solve_vert_velocity(self, annotate=annotate):
   """ 
   Solve for vertical velocity w.
   """
   s    = "::: solving Dukowicz reduced vertical velocity :::"
   print_text(s, self.color())
   
   model    = self.model
   aw       = assemble(lhs(self.w_F))
   Lw       = assemble(rhs(self.w_F))
   #if self.bc_w != None:
   #  self.bc_w.apply(aw, Lw)
   w_solver = LUSolver(self.solve_params['vert_solve_method'])
   w_solver.solve(aw, self.w.vector(), Lw, annotate=annotate)
   #solve(lhs(self.R2) == rhs(self.R2), self.w, bcs = self.bc_w,
   #      solver_parameters = {"linear_solver" : sm})#,
   #                           "symmetric" : True},
   #                           annotate=False)
   
   self.assz.assign(model.w, self.w, annotate=annotate)
   #w = project(self.w, model.Q, annotate=annotate)
   print_min_max(self.w, 'w', cls=self)
示例#21
0
  def vert_extrude(self, u, d='up', Q='self'):
    r"""
    This extrudes a function *u* vertically in the direction *d* = 'up' or
    'down'.  It does this by solving a variational problem:
  
    .. math::
       
       \frac{\partial v}{\partial z} = 0 \hspace{10mm}
       v|_b = u

    """
    s = "::: extruding function %swards :::" % d
    print_text(s, cls=self)
    if type(Q) != FunctionSpace:
      Q  = self.Q
    ff   = self.ff
    phi  = TestFunction(Q)
    v    = TrialFunction(Q)
    a    = v.dx(2) * phi * dx
    L    = DOLFIN_EPS * phi * dx
    bcs  = []
    # extrude bed (ff = 3,5) 
    if d == 'up':
      bcs.append(DirichletBC(Q, u, ff, self.GAMMA_B_GND))  # grounded
      bcs.append(DirichletBC(Q, u, ff, self.GAMMA_B_FLT))  # shelves
    # extrude surface (ff = 2,6) 
    elif d == 'down':
      bcs.append(DirichletBC(Q, u, ff, self.GAMMA_S_GND))  # grounded
      bcs.append(DirichletBC(Q, u, ff, self.GAMMA_S_FLT))  # shelves
      bcs.append(DirichletBC(Q, u, ff, self.GAMMA_U_GND))  # grounded
      bcs.append(DirichletBC(Q, u, ff, self.GAMMA_U_FLT))  # shelves
    try:
      name = '%s extruded %s' % (u.name(), d)
    except AttributeError:
      name = 'extruded'
    v    = Function(Q, name=name)
    solve(a == L, v, bcs, annotate=False)
    print_min_max(v, 'extruded function', cls=self)
    return v
示例#22
0
    def solve_vert_velocity(self, annotate=False):
        """ 
    Perform the Newton solve of the first order equations 
    """
        model = self.model

        # solve for vertical velocity :
        s = "::: solving BP vertical velocity :::"
        print_text(s, self.color())

        aw = assemble(lhs(self.w_F))
        Lw = assemble(rhs(self.w_F))
        if self.bc_w != None:
            self.bc_w.apply(aw, Lw)
        w_solver = LUSolver(self.solve_params['vert_solve_method'])
        w_solver.solve(aw, self.wf.vector(), Lw, annotate=annotate)
        #solve(lhs(self.R2) == rhs(self.R2), self.w, bcs = self.bc_w,
        #      solver_parameters = {"linear_solver" : sm})#,
        #                           "symmetric" : True},
        #                           annotate=False)

        self.assz.assign(model.w, self.wf, annotate=annotate)
        print_min_max(self.wf, 'w', cls=self)
示例#23
0
    def solve(self, annotate=True):
        """
    """
        s = "::: solving firn density, overburden stress, and grain radius :::"
        print_text(s, self.color())

        model = self.model

        # newton's iterative method :
        solve(self.delta == 0,
              self.U,
              bcs=self.bcs,
              J=self.J,
              solver_parameters=self.solve_params['solver'],
              annotate=annotate)
        rho, sigma, r = self.U.split()

        self.assrho.assign(model.rho, rho)
        self.asssig.assign(model.sigma, sigma)
        self.assrss.assign(model.r, r)

        rhop = model.rho.vector().array()

        # update kc term in drhodt :
        # if rho >  550, kc = kcHigh
        # if rho <= 550, kc = kcLow
        # with parameterizations given by ligtenberg et all 2011
        A = model.rhoi(0) / model.rhow(0) * 1e3 * model.adot(0)
        rhoCoefNew = np.ones(model.dof)
        rhoHigh = np.where(rhop > 550)[0]
        rhoLow = np.where(rhop <= 550)[0]
        rhoCoefNew[rhoHigh] = model.kcHh(0) * (2.366 - 0.293 * ln(A))
        rhoCoefNew[rhoLow] = model.kcLw(0) * (1.435 - 0.151 * ln(A))
        model.assign_variable(model.rhoCoef, rhoCoefNew)

        print_min_max(model.rho, 'rho')
        print_min_max(model.sigma, 'sigma')
        print_min_max(model.r, 'r')

        s = "::: solving firn densification rate :::"
        print_text(s, self.color())
        model.assign_variable(model.drhodt, project(self.drhodt))
        print_min_max(model.drhodt, 'drho/dt')

        self.solve_compaction_velocity(annotate=annotate)
示例#24
0
    def solve(self, annotate=True):
        """
    Solves for hybrid conservation of mass.
    """
        model = self.model
        params = self.solve_params

        # find corrective velocities :
        s = "::: solving for corrective velocities :::"
        print_text(s, self.color())

        solve(self.M == self.ubar_proj,
              model.ubar_c,
              solver_parameters={'linear_solver': 'mumps'},
              form_compiler_parameters=params['ffc_params'],
              annotate=annotate)

        solve(self.M == self.vbar_proj,
              model.vbar_c,
              solver_parameters={'linear_solver': 'mumps'},
              form_compiler_parameters=params['ffc_params'],
              annotate=annotate)

        print_min_max(model.ubar_c, 'ubar_c', cls=self)
        print_min_max(model.vbar_c, 'vbar_c', cls=self)

        # SOLVE MASS CONSERVATION bounded by (H_max, H_min) :
        meth = params['solver']['snes_solver']['method']
        maxit = params['solver']['snes_solver']['maximum_iterations']
        s      = "::: solving 'MassTransportHybrid' using method '%s' with %i " + \
                 "max iterations :::"
        print_text(s % (meth, maxit), self.color())

        # define variational solver for the mass problem :
        #p = NonlinearVariationalProblem(self.R_thick, model.H, J=self.J_thick,
        #      bcs=self.bc, form_compiler_parameters=params['ffc_params'])
        #p.set_bounds(model.H_min, model.H_max)
        #s = NonlinearVariationalSolver(p)
        #s.parameters.update(params['solver'])
        out = self.solver.solve(annotate=annotate)

        print_min_max(model.H, 'H', cls=self)

        # update previous time step's H :
        model.assign_variable(model.H0, model.H, cls=self)

        # update the surface :
        s = "::: updating surface :::"
        print_text(s, self.color())
        B_v = model.B.vector().array()
        H_v = model.H.vector().array()
        S_v = B_v + H_v
        model.assign_variable(model.S, S_v, cls=self)

        return out
示例#25
0
  def solve(self, annotate=False):
    """ 
    Perform the Newton solve of the reduced full-Stokes equations 
    """
    model  = self.model
    params = self.solve_params
    
    # solve nonlinear system :
    rtol     = params['solver']['newton_solver']['relative_tolerance']
    maxit    = params['solver']['newton_solver']['maximum_iterations']
    alpha    = params['solver']['newton_solver']['relaxation_parameter']
    lin_slv  = params['solver']['newton_solver']['linear_solver']
    precon   = params['solver']['newton_solver']['preconditioner']
    err_conv = params['solver']['newton_solver']['error_on_nonconvergence']
    s    = "::: solving Dukowicz full-Stokes reduced equations with %i max" + \
             " iterations and step size = %.1f :::"
    print_text(s % (maxit, alpha), self.color())
    
    # zero out self.velocity for good convergence for any subsequent solves,
    # e.g. model.L_curve() :
    model.assign_variable(self.get_U(), DOLFIN_EPS, cls=self)

    def cb_ftn():
      self.solve_vert_velocity(annotate)
    
    # compute solution :
    #solve(self.mom_F == 0, self.U, J = self.mom_Jac, bcs = self.mom_bcs,
    #      annotate = annotate, solver_parameters = params['solver'])
    model.home_rolled_newton_method(self.mom_F, self.U, self.mom_Jac, 
                                    self.mom_bcs, atol=1e-6, rtol=rtol,
                                    relaxation_param=alpha, max_iter=maxit,
                                    method=lin_slv, preconditioner=precon,
                                    cb_ftn=cb_ftn)
    u, v = self.U.split()
  
    self.assx.assign(model.u, u, annotate=False)
    self.assy.assign(model.v, v, annotate=False)

    # solve for the vertical velocity :
    if params['solve_vert_velocity']:
      self.solve_vert_velocity(annotate)
    if params['solve_pressure']:
      self.solve_pressure(annotate)
    
    U3 = model.U3.split(True)

    print_min_max(U3[0], 'u', cls=self)
    print_min_max(U3[1], 'v', cls=self)
    print_min_max(U3[2], 'w', cls=self)
示例#26
0
  def solve(self, annotate=False):
    """ 
    Solve the energy equations, saving enthalpy to model.theta, temperature 
    to model.T, and water content to model.W.
    """
    model      = self.model
    mesh       = model.mesh
    Q          = model.Q
    T_melt     = model.T_melt
    T          = model.T
    T_w        = model.T_w
    W          = model.W
    W0         = model.W0
    L          = model.L
    c          = self.c
    params     = self.solve_params
    
    # solve nonlinear system :
    rtol   = params['solver']['newton_solver']['relative_tolerance']
    maxit  = params['solver']['newton_solver']['maximum_iterations']
    alpha  = params['solver']['newton_solver']['relaxation_parameter']
    s      = "::: solving monolithic with %i max iterations" + \
             " and step size = %.1f :::"
    print_text(s % (maxit, alpha), self.color())
    
    # compute solution :
    solve(self.F == 0, self.G, J = self.Jac, bcs = self.bcs,
          annotate = annotate, solver_parameters = params['solver'])
    U, theta = self.G.split()
    u, v     = split(U)
  
    self.assx.assign(model.u,     u,     annotate=False)
    self.assy.assign(model.v,     v,     annotate=False)
    self.asst.assign(model.theta, theta, annotate=False)

    # solve for the vertical velocity :
    if params['solve_vert_velocity']:
      self.solve_vert_velocity(annotate)
    
    U3 = model.U3.split(True)
    print_min_max(U3[0], 'u', cls=self)
    print_min_max(U3[1], 'v', cls=self)
    print_min_max(U3[2], 'w', cls=self)

    # temperature solved with quadradic formula, using expression for c : 
    s = "::: calculating temperature :::"
    print_text(s, cls=self)
    theta_v  = theta.vector().array()
    T_n_v    = (-146.3 + np.sqrt(146.3**2 + 2*7.253*theta_v)) / 7.253
    T_v      = T_n_v.copy()
    Tp_v     = T_n_v.copy()

    # create pressure-adjusted temperature for rate-factor :
    Tp_v[Tp_v > T_w(0)] = T_w(0)
    model.init_Tp(Tp_v, cls=self)
    
    # update temperature for wet/dry areas :
    T_melt_v     = T_melt.vector().array()
    theta_melt_v = model.theta_melt.vector().array()
    warm         = theta_v >= theta_melt_v
    cold         = theta_v <  theta_melt_v
    T_v[warm]    = T_melt_v[warm]
    model.assign_variable(T, T_v, cls=self)
    
    # water content solved diagnostically :
    s = "::: calculating water content :::"
    print_text(s, cls=self)
    W_v  = (theta_v - theta_melt_v) / L(0)
    
    # update water content :
    #W_v[cold]       = 0.0   # no water where frozen 
    W_v[W_v < 0.0]  = 0.0    # no water where frozen, please.
    #W_v[W_v > 1.0]  = 1.0    # capped at 100% water, i.e., no hot water.
    model.assign_variable(W0, W, cls=self)
    model.assign_variable(W,  W_v, cls=self)
示例#27
0
    def solve_component_stress(self):
        """
    """
        model = self.model

        s = "::: solving 'SSA_Balance' for stresses :::"
        print_text(s, self.color())

        Q = model.Q
        beta = model.beta
        S = model.S
        B = model.B
        H = S - B
        rhoi = model.rhoi
        g = model.g
        etabar = model.etabar

        Q = model.Q
        U_s = self.U_s
        U_n = self.U_n
        U_t = self.U_t

        phi = TestFunction(Q)
        dtau = TrialFunction(Q)

        s = dot(U_s, U_n)
        t = dot(U_s, U_t)
        grads = as_vector([s.dx(0), s.dx(1)])
        gradt = as_vector([t.dx(0), t.dx(1)])
        dsdi = dot(grads, U_n)
        dsdj = dot(grads, U_t)
        dtdi = dot(gradt, U_n)
        dtdj = dot(gradt, U_t)
        gradphi = as_vector([phi.dx(0), phi.dx(1)])
        gradS = as_vector([S.dx(0), S.dx(1)])
        dphidi = dot(gradphi, U_n)
        dphidj = dot(gradphi, U_t)
        dSdi = dot(gradS, U_n)
        dSdj = dot(gradS, U_t)
        gradphi = as_vector([dphidi, dphidj])
        gradS = as_vector([dSdi, dSdj])

        epi_1 = as_vector([2 * dsdi + dtdj, 0.5 * (dsdj + dtdi)])
        epi_2 = as_vector([0.5 * (dsdj + dtdi), 2 * dtdj + dsdi])

        tau_id_s = phi * rhoi * g * H * gradS[0] * dx
        tau_jd_s = phi * rhoi * g * H * gradS[1] * dx

        tau_ib_s = -beta * s * phi * dx
        tau_jb_s = -beta * t * phi * dx

        tau_ii_s = -2 * etabar * H * epi_1[0] * gradphi[0] * dx
        tau_ij_s = -2 * etabar * H * epi_1[1] * gradphi[1] * dx

        tau_ji_s = -2 * etabar * H * epi_2[0] * gradphi[0] * dx
        tau_jj_s = -2 * etabar * H * epi_2[1] * gradphi[1] * dx

        # mass matrix :
        M = assemble(phi * dtau * dx)

        # solve the linear system :
        solve(M, model.tau_id.vector(), assemble(tau_id_s))
        print_min_max(model.tau_id, 'tau_id')
        solve(M, model.tau_jd.vector(), assemble(tau_jd_s))
        print_min_max(model.tau_jd, 'tau_jd')
        solve(M, model.tau_ib.vector(), assemble(tau_ib_s))
        print_min_max(model.tau_ib, 'tau_ib')
        solve(M, model.tau_jb.vector(), assemble(tau_jb_s))
        print_min_max(model.tau_jb, 'tau_jb')
        solve(M, model.tau_ii.vector(), assemble(tau_ii_s))
        print_min_max(model.tau_ii, 'tau_ii')
        solve(M, model.tau_ij.vector(), assemble(tau_ij_s))
        print_min_max(model.tau_ij, 'tau_ij')
        solve(M, model.tau_ji.vector(), assemble(tau_ji_s))
        print_min_max(model.tau_ji, 'tau_ji')
        solve(M, model.tau_jj.vector(), assemble(tau_jj_s))
        print_min_max(model.tau_jj, 'tau_jj')
示例#28
0
    def solve(self):
        """
    """
        s = "::: solving 'FS_Balance' :::"
        print_text(s, self.color())

        model = self.model

        # solve the linear system :
        solve(self.M, model.tau_ii.vector(), assemble(self.tau_ii))
        print_min_max(model.tau_ii, 'tau_ii')
        solve(self.M, model.tau_ij.vector(), assemble(self.tau_ij))
        print_min_max(model.tau_ij, 'tau_ij')
        solve(self.M, model.tau_ik.vector(), assemble(self.tau_ik))
        print_min_max(model.tau_ik, 'tau_ik')
        solve(self.M, model.tau_ji.vector(), assemble(self.tau_ji))
        print_min_max(model.tau_ji, 'tau_ji')
        solve(self.M, model.tau_jj.vector(), assemble(self.tau_jj))
        print_min_max(model.tau_jj, 'tau_jj')
        solve(self.M, model.tau_jk.vector(), assemble(self.tau_jk))
        print_min_max(model.tau_jk, 'tau_jk')
        solve(self.M, model.tau_ki.vector(), assemble(self.tau_ki))
        print_min_max(model.tau_ki, 'tau_ki')
        solve(self.M, model.tau_kj.vector(), assemble(self.tau_kj))
        print_min_max(model.tau_kj, 'tau_kj')
        solve(self.M, model.tau_kk.vector(), assemble(self.tau_kk))
        print_min_max(model.tau_kk, 'tau_kk')
示例#29
0
    def solve(self, annotate=True):
        """
    Solve the balance velocity magnitude :math:`\Vert \\bar{\mathbf{u}} \Vert`.

    This will be completed in four steps,

    1. Calculate the surface gradient :math:`\\frac{\partial S}{\partial x}`
       and :math:`\\frac{\partial S}{\partial y}` saved to ``model.dSdx``
       and ``model.dSdy``.

    2. Solve for the smoothed component of driving stress

       .. math::
       
          \\tau_x = \\rho g H \\frac{\partial S}{\partial x}, \hspace{10mm}
          \\tau_y = \\rho g H \\frac{\partial S}{\partial y}
 
       saved respectively to ``model.Nx`` and ``model.Ny``. 
    
    3. Calculate the normalized flux directions
       
       .. math::
       
          d_x = -\\frac{\\tau_x}{\Vert \\tau_x \Vert}, \hspace{10mm}
          d_y = -\\frac{\\tau_y}{\Vert \\tau_y \Vert},
 
       saved respectively to ``model.d_x`` and ``model.d_y``. 
    
    4. Calculate the balance velocity magnitude 
       :math:`\Vert \\bar{\mathbf{u}} \Vert`
       from

       .. math::

          \\nabla \cdot \\left( \\bar{\mathbf{u}} H \\right) = \dot{a} - F_b

       saved to ``model.Ubar``.

    """
        model = self.model

        s = "::: solving BalanceVelocity :::"
        print_text(s, cls=self)

        s = "::: calculating surface gradient :::"
        print_text(s, cls=self)

        dSdx = project(model.S.dx(0), model.Q, annotate=annotate)
        dSdy = project(model.S.dx(1), model.Q, annotate=annotate)
        model.assign_variable(model.dSdx, dSdx, cls=self)
        model.assign_variable(model.dSdy, dSdy, cls=self)

        # update velocity direction from driving stress :
        s    = "::: solving for smoothed x-component of driving stress " + \
               "with kappa = %g :::" % self.kappa
        print_text(s, cls=self)
        solve(self.a_dSdx == self.L_dSdx, model.Nx, annotate=annotate)
        print_min_max(model.Nx, 'Nx', cls=self)

        s = "::: solving for smoothed y-component of driving stress :::"
        print_text(s, cls=self)
        solve(self.a_dSdy == self.L_dSdy, model.Ny, annotate=annotate)
        print_min_max(model.Ny, 'Ny', cls=self)

        # normalize the direction vector :
        s    =   "::: calculating normalized flux direction" \
               + " from driving stress :::"
        print_text(s, cls=self)
        d_x_v = model.Nx.vector().array()
        d_y_v = model.Ny.vector().array()
        d_n_v = np.sqrt(d_x_v**2 + d_y_v**2 + 1e-16)
        model.assign_variable(model.d_x, -d_x_v / d_n_v, cls=self)
        model.assign_variable(model.d_y, -d_y_v / d_n_v, cls=self)

        # calculate balance-velocity :
        s = "::: solving velocity balance magnitude :::"
        print_text(s, cls=self)
        solve(self.B == self.a, model.Ubar, annotate=annotate)
        print_min_max(model.Ubar, 'Ubar', cls=self)

        # enforce positivity of balance-velocity :
        s = "::: removing negative values of balance velocity :::"
        print_text(s, cls=self)
        Ubar_v = model.Ubar.vector().array()
        Ubar_v[Ubar_v < 0] = 0
        model.assign_variable(model.Ubar, Ubar_v, cls=self)
示例#30
0
    def solve_component_stress(self):
        """
    """
        model = self.model

        s = "solving 'BP_Balance' for internal forces :::"
        print_text(s, self.color())

        Q = model.Q
        N = model.N
        beta = model.beta
        S = model.S
        B = model.B
        H = S - B
        rhoi = model.rhoi
        g = model.g
        eta = self.eta
        f_w = self.f_w

        dx = model.dx
        dx_f = model.dx_f
        dx_g = model.dx_g
        ds = model.ds
        dBed_g = model.dBed_g
        dBed_f = model.dBed_f
        dLat_t = model.dLat_t
        dBed = model.dBed

        # solve with corrected velociites :
        U_s = self.U_s
        U_n = self.U_n
        U_t = self.U_t

        ## or not :
        #u,v,w    = model.U3.split(True)
        #U        = as_vector([u, v])
        #U_mag    = sqrt(dot(U,U) + DOLFIN_EPS)
        #U_n      = U / U_mag
        #U_t      = as_vector([v, -u]) / U_mag
        #s        = dot(U, U_n)
        #t        = dot(U, U_t)
        #U_s      = as_vector([s, t])

        # functionspaces :
        phi = TestFunction(Q)
        dtau = TrialFunction(Q)

        s = dot(U_s, U_n)
        t = dot(U_s, U_t)
        U_s = as_vector([s, t])
        grads = as_vector([s.dx(0), s.dx(1)])
        gradt = as_vector([t.dx(0), t.dx(1)])
        dsdi = dot(grads, U_n)
        dsdj = dot(grads, U_t)
        dsdz = s.dx(2)
        dtdi = dot(gradt, U_n)
        dtdj = dot(gradt, U_t)
        dtdz = t.dx(2)
        dwdz = -(dsdi + dtdj)
        gradphi = as_vector([phi.dx(0), phi.dx(1)])
        gradS = as_vector([S.dx(0), S.dx(1)])
        dphidi = dot(gradphi, U_n)
        dphidj = dot(gradphi, U_t)
        dSdi = dot(gradS, U_n)
        dSdj = dot(gradS, U_t)
        gradphi = as_vector([dphidi, dphidj, phi.dx(2)])
        gradS = as_vector([dSdi, dSdj, S.dx(2)])

        epi_1 = as_vector([dsdi + dwdz, 0.5 * (dsdj + dtdi), 0.5 * dsdz])
        epi_2 = as_vector([0.5 * (dtdi + dsdj), dtdj + dwdz, 0.5 * dtdz])

        F_id_s = +phi * rhoi * g * gradS[0] * dx  #\
        #         - 2 * eta * dwdz * dphidi * dx #\
        #         + 2 * eta * dwdz * phi * N[0] * U_n[0] * ds
        F_jd_s = +phi * rhoi * g * gradS[1] * dx  #\
        #         - 2 * eta * dwdz * dphidj * dx #\
        #         + 2 * eta * dwdz * phi * N[1] * U_n[1] * ds

        F_ib_s = -beta * s * phi * dBed
        F_jb_s = -beta * t * phi * dBed

        F_ip_s = f_w * N[0] * phi * dLat_t
        F_jp_s = f_w * N[1] * phi * dLat_t

        F_pn_s = f_w * N[0] * phi * dLat_t
        F_pt_s = f_w * N[1] * phi * dLat_t

        F_ii_s = - 2 * eta * epi_1[0] * gradphi[0] * dx \
    #         + 2 * eta * epi_1[0] * phi * N[0] * U_n[0] * ds

        #         + f_w * N[0] * phi * U_n[0] * dLat_t
        F_ij_s = -2 * eta * epi_1[1] * gradphi[1] * dx  # \
        #         + 2 * eta * epi_1[1] * phi * N[1] * U_n[1] * ds
        #         + f_w * N[1] * phi * U_n[1] * dLat_t
        F_iz_s = -2 * eta * epi_1[2] * gradphi[2] * dx + F_ib_s  #\
        #        + 2 * eta * epi_1[2] * phi * N[2] * ds

        F_ji_s = -2 * eta * epi_2[0] * gradphi[0] * dx  # \
        #         + 2 * eta * epi_2[0] * phi * N[0] * U_t[0] * ds
        #         + f_w * N[0] * phi * U_t[0] * dLat_t
        F_jj_s = -2 * eta * epi_2[1] * gradphi[1] * dx  # \
        #         + 2 * eta * epi_2[0] * phi * N[1] * U_t[1] * ds
        #         + f_w * N[1] * phi * U_t[1] * dLat_t
        F_jz_s = -2 * eta * epi_2[2] * gradphi[2] * dx + F_jb_s  #\
        #         + 2 * eta * epi_2[2] * phi * N[2] * ds

        # mass matrix :
        M = assemble(phi * dtau * dx)

        # solve the linear system :
        solve(M, model.F_id.vector(), assemble(F_id_s))
        print_min_max(model.F_id, 'F_id')
        solve(M, model.F_jd.vector(), assemble(F_jd_s))
        print_min_max(model.F_jd, 'F_jd')
        solve(M, model.F_ib.vector(), assemble(F_ib_s))
        print_min_max(model.F_ib, 'F_ib')
        solve(M, model.F_jb.vector(), assemble(F_jb_s))
        print_min_max(model.F_jb, 'F_jb')
        solve(M, model.F_ip.vector(), assemble(F_ip_s))
        print_min_max(model.F_ip, 'F_ip')
        solve(M, model.F_jp.vector(), assemble(F_jp_s))
        print_min_max(model.F_jp, 'F_jp')
        solve(M, model.F_ii.vector(), assemble(F_ii_s))
        print_min_max(model.F_ii, 'F_ii')
        solve(M, model.F_ij.vector(), assemble(F_ij_s))
        print_min_max(model.F_ij, 'F_ij')
        solve(M, model.F_iz.vector(), assemble(F_iz_s))
        print_min_max(model.F_iz, 'F_iz')
        solve(M, model.F_ji.vector(), assemble(F_ji_s))
        print_min_max(model.F_ji, 'F_ji')
        solve(M, model.F_jj.vector(), assemble(F_jj_s))
        print_min_max(model.F_jj, 'F_jj')
        solve(M, model.F_jz.vector(), assemble(F_jz_s))
        print_min_max(model.F_jz, 'F_jz')

        if self.vert_integrate:
            s = "::: vertically integrating 'BP_Balance' internal forces :::"
            print_text(s, self.color())

            tau_ii = model.vert_integrate(model.F_ii, d='down')
            tau_ij = model.vert_integrate(model.F_ij, d='down')
            tau_iz = model.vert_integrate(model.F_iz, d='down')

            tau_ji = model.vert_integrate(model.F_ji, d='down')
            tau_jj = model.vert_integrate(model.F_jj, d='down')
            tau_jz = model.vert_integrate(model.F_jz, d='down')

            tau_id = model.vert_integrate(model.F_id, d='down')
            tau_jd = model.vert_integrate(model.F_jd, d='down')

            tau_ip = model.vert_integrate(model.F_ip, d='down')
            tau_jp = model.vert_integrate(model.F_jp, d='down')

            tau_ib = model.vert_extrude(model.F_ib, d='up')
            tau_jb = model.vert_extrude(model.F_jb, d='up')

            model.assign_variable(model.tau_id, tau_id, cls=self)
            model.assign_variable(model.tau_jd, tau_jd, cls=self)
            model.assign_variable(model.tau_ib, tau_ib, cls=self)
            model.assign_variable(model.tau_jb, tau_jb, cls=self)
            model.assign_variable(model.tau_ip, tau_ip, cls=self)
            model.assign_variable(model.tau_jp, tau_jp, cls=self)
            model.assign_variable(model.tau_ii, tau_ii, cls=self)
            model.assign_variable(model.tau_ij, tau_ij, cls=self)
            model.assign_variable(model.tau_iz, tau_iz, cls=self)
            model.assign_variable(model.tau_ji, tau_ji, cls=self)
            model.assign_variable(model.tau_jj, tau_jj, cls=self)
            model.assign_variable(model.tau_jz, tau_jz, cls=self)