示例#1
0
    def action(self, **kwargs):
        r"""Return the action functional that gives the hybrid model as its
        Euler-Lagrange equations"""
        u, h = itemgetter("velocity", "thickness")(kwargs)
        mesh = u.ufl_domain()
        ice_front_ids = tuple(kwargs.pop("ice_front_ids", ()))
        side_wall_ids = tuple(kwargs.pop("side_wall_ids", ()))

        metadata = {"quadrature_degree": self.quadrature_degree(**kwargs)}
        dx = firedrake.dx(metadata=metadata)
        ds_b = firedrake.ds_b(domain=mesh, metadata=metadata)
        ds_v = firedrake.ds_v(domain=mesh)

        viscosity = self.viscosity(**kwargs) * dx
        gravity = self.gravity(**kwargs) * dx
        friction = self.friction(**kwargs) * ds_b

        side_friction = self.side_friction(**kwargs) * ds_v(side_wall_ids)
        if get_mesh_axes(mesh) == "xyz":
            penalty = self.penalty(**kwargs) * ds_v(side_wall_ids)
        else:
            penalty = 0.0

        xdegree_u, zdegree_u = u.ufl_element().degree()
        degree_h = h.ufl_element().degree()[0]
        degree = (xdegree_u + degree_h, 2 * zdegree_u + 1)
        ds_t = firedrake.ds_v(ice_front_ids,
                              metadata={"quadrature_degree": degree})
        terminus = self.terminus(**kwargs) * ds_t

        return viscosity + friction + side_friction - gravity - terminus + penalty
示例#2
0
def calculate_Pi0(state, theta0, rho0):
    # exner function
    Vr = rho0.function_space()
    Pi = Function(Vr).interpolate(thermodynamics.pi(state.parameters, rho0, theta0))
    Pi0 = assemble(Pi*dx)/assemble(Constant(1)*dx(domain=state.mesh))

    return Pi0
示例#3
0
def runSolvers(solverBeta, solverTheta, modelResults, uObs, mesh,
               nSteps=30, rtol=5.e-3, solveViscosity=True, solveBeta=True):
    """ Run joint solvers """
    JLastBeta, JLastTheta = np.inf, np.inf
    #
    area = firedrake.assemble(firedrake.Constant(1) * firedrake.dx(mesh))
    #
    # step solvers
    convergeTheta, convergeBeta = False, False
    for i in range(0, nSteps):
        #
        # run solver step for beta
        Print(f'\n\033[1mIteration {i}\033[0m')
        if solverBeta is not None:
            convergeBeta, JLastBeta, ve = solverStep(solverBeta, solverTheta,
                                                     area, JLastBeta, uObs,
                                                     'beta', 'theta', rtol)
        #
        # run solver step for theta
        if solverTheta is not None:
            convergeTheta, JLastTheta, ve = solverStep(solverTheta, solverBeta,
                                                       area, JLastTheta, uObs,
                                                       'theta', 'beta', rtol)
        modelResults[f'Verror_{i:03}'] = ve  # Last error for step
        if convergeTheta and convergeBeta:  # Done??
            break
    # Done, print message
    Print(f'Done at {datetime.now().strftime("%H:%M:%S")}')
示例#4
0
def AdvectionDiffusionGLS(
    V: fd.FunctionSpace,
    theta: fd.Function,
    phi: fd.Function,
    PeInv: float = 1e-4,
    phi_t: fd.Function = None,
):
    PeInv_ct = fd.Constant(PeInv)
    rho = fd.TestFunction(V)
    F = (inner(theta, grad(phi)) * rho +
         PeInv_ct * inner(grad(phi), grad(rho))) * dx

    if phi_t:
        F += phi_t * rho * dx

    h = fd.CellDiameter(V.ufl_domain())
    R_U = dot(theta, grad(phi)) - PeInv_ct * div(grad(phi))

    if phi_t:
        R_U += phi_t

    beta_gls = 0.9
    tau_gls = beta_gls * ((4.0 * dot(theta, theta) / h**2) + 9.0 *
                          (4.0 * PeInv_ct / h**2)**2)**(-0.5)

    theta_U = dot(theta, grad(rho)) - PeInv_ct * div(grad(rho))
    F += tau_gls * inner(R_U, theta_U) * dx()

    return F
示例#5
0
    def action(self, **kwargs):
        r"""Return the action functional that gives the shallow ice
        diagnostic model as the Euler-Lagrange equations

        Parameters
        ----------
        velocity : firedrake.Function
        thickness : firedrake.Function
        surface : firedrake.Function
        fluidity : firedrake.Function or firedrake.Constant

        Returns
        -------
        E : firedrake.Form
            the shallow ice action functional

        Other parameters
        ----------------
        **kwargs
            All other keyword arguments will be passed on to the
            'mass', 'gravity' and 'penalty' functionals
        """
        metadata = {"quadrature_degree": self.quadrature_degree(**kwargs)}
        dx = firedrake.dx(metadata=metadata)
        mass = self.mass(**kwargs) * dx
        gravity = self.gravity(**kwargs) * dx
        penalty = self.penalty(**kwargs) * dx
        return mass + gravity + penalty
示例#6
0
    def action(self, **kwargs):
        r"""Return the action functional that gives the ice stream
        diagnostic model as the Euler-Lagrange equations"""
        u = kwargs["velocity"]
        mesh = u.ufl_domain()
        ice_front_ids = tuple(kwargs.pop("ice_front_ids", ()))
        side_wall_ids = tuple(kwargs.pop("side_wall_ids", ()))

        metadata = {"quadrature_degree": self.quadrature_degree(**kwargs)}
        dx = firedrake.dx(metadata=metadata)
        ds = firedrake.ds(domain=mesh, metadata=metadata)

        viscosity = self.viscosity(**kwargs) * dx
        friction = self.friction(**kwargs) * dx
        gravity = self.gravity(**kwargs) * dx

        side_friction = self.side_friction(**kwargs) * ds(side_wall_ids)
        if get_mesh_axes(mesh) == "xy":
            penalty = self.penalty(**kwargs) * ds(side_wall_ids)
        else:
            penalty = 0.0

        terminus = self.terminus(**kwargs) * ds(ice_front_ids)

        return viscosity + friction + side_friction - gravity - terminus + penalty
示例#7
0
def variational_form_residual(sim, solution):

    Gr = sim.grashof_number

    Pr = sim.prandtl_number

    ihat, jhat = sapphire.simulation.unit_vectors(sim.mesh)

    sim.gravity_direction = fe.Constant(-jhat)

    ghat = sim.gravity_direction

    p, u, T = fe.split(solution)

    psi_p, psi_u, psi_T = fe.TestFunctions(solution.function_space())

    mass = psi_p * div(u)

    momentum = dot(psi_u, grad(u)*u + Gr*T*ghat) \
        - div(psi_u)*p + 2.*inner(sym(grad(psi_u)), sym(grad(u)))

    energy = psi_T * dot(u, grad(T)) + dot(grad(psi_T), 1. / Pr * grad(T))

    dx = fe.dx(degree=sim.quadrature_degree)

    return (mass + momentum + energy) * dx
示例#8
0
 def energy(self):
     
     Re = self.reynolds_number
     
     Pr = self.prandtl_number
     
     Ste = self.stefan_number
     
     _, u, T = fe.split(self.solution)
     
     phil = self.liquid_volume_fraction(temperature = T)
     
     rho_sl = self.density_solid_to_liquid_ratio
     
     c_sl = self.heat_capacity_solid_to_liquid_ratio
     
     C = phase_dependent_material_property(rho_sl*c_sl)(phil)
     
     k_sl = self.thermal_conductivity_solid_to_liquid_ratio
     
     k = phase_dependent_material_property(k_sl)(phil)
     
     CT_t, phil_t = self.extra_time_discrete_terms()
     
     _, _, psi_T = fe.TestFunctions(self.solution_space)
     
     dx = fe.dx(degree = self.quadrature_degree)
     
     return (psi_T*(CT_t + 1./Ste*phil_t + dot(u, grad(C*T))) \
         + 1./(Re*Pr)*dot(grad(psi_T), k*grad(T)))*dx
示例#9
0
def computeSummaryData(SD, h, s, u, a, melt, SMB, grounded, floating, year, Q,
                       mesh, deltaT, beginTime):
    ''' Compute summary results and sort in summaryData
        Save all as float for yaml output
    '''
    deltaVF, deltaVG = \
        volumeChange(grounded, floating, h, u, a, mesh)
    SD['deltaVF'][-1] += deltaVF * deltaT * iceToWater
    SD['deltaVG'][-1] += deltaVG * deltaT * iceToWater
    SD['DVF'][-1] += deltaVF * deltaT * iceToWater
    SD['DVG'][-1] += deltaVG * deltaT * iceToWater
    print(f"++{year:0.3f} {SD['deltaVF'][-1]/1e9:0.3f} "
          f"{SD['deltaVG'][-1]/1e9:0.3f} {SD['DVF'][-1]/1e9:0.3f} "
          f"{SD['DVG'][-1]/1e9:0.3f}")
    #
    # If not with half a time step of year return
    # Need to update this for different update interval (~=1)
    dTint = abs(year - round(year, 0))  # difference from int year
    # if before first year or not with half time step of int year return
    if year < (1. - deltaT * 0.5) or not (dTint < deltaT * 0.5):
        return False
    print(f'year {year} runtime {datetime.now() - beginTime}')
    #
    gArea = firedrake.assemble(grounded * firedrake.dx(mesh))
    SD['year'].append(float(year))
    SD['gArea'].append(gArea)
    SD['fArea'].append(SD['area'] - gArea)
    # append a new zero value to start incrementing
    SD['deltaVF'].append(0)
    SD['deltaVG'].append(0)
    # append current value to start incrementing
    SD['DVF'].append(SD['DVF'][-1])
    SD['DVG'].append(SD['DVG'][-1])
    #
    meltTot = firedrake.assemble(
        icepack.interpolate(floating * melt, Q) * firedrake.dx(mesh))
    SD['meltTot'].append(float(meltTot))
    SMBfloating = firedrake.assemble(
        icepack.interpolate(floating * SMB, Q) * firedrake.dx(mesh))
    SD['SMBfloating'].append(float(SMBfloating))
    SMBgrounded = firedrake.assemble(
        icepack.interpolate(grounded * SMB, Q) * firedrake.dx(mesh))
    SD['SMBgrounded'].append(float(SMBgrounded))
    #
    print(f'{year}: Initial melt {SD["meltTot"][0] / 1e9:.2f} current melt '
          f' {meltTot / 1e9:.2f}')
    return True
示例#10
0
def initSummary(grounded0,
                floating0,
                h0,
                u0,
                meltModel,
                meltParams,
                SMB,
                Q,
                mesh,
                forwardParams,
                restart=False):
    ''' Compute initial areas and summary data
        if restart, try reload restart data. If not go with clean slate, which
        should be a legacy case (from when intermediates steps were not saved)
    '''
    if forwardParams['restart']:
        summaryData = reinitSummary(forwardParams)
        if summaryData is not None:
            return summaryData
        # No summary.tmp from a prior run so reset restart
        forwardParams['restart'] = False
    # start from scratch
    area = firedrake.assemble(firedrake.Constant(1) * firedrake.dx(mesh))
    gArea0 = firedrake.assemble(grounded0 * firedrake.dx(mesh))
    fArea0 = area - gArea0
    melt = meltModel(h0, floating0, meltParams, Q, u0)
    meltTot = firedrake.assemble(
        icepack.interpolate(floating0 * melt, Q) * firedrake.dx(mesh))
    SMBfloating = firedrake.assemble(
        icepack.interpolate(floating0 * SMB, Q) * firedrake.dx(mesh))
    SMBgrounded = firedrake.assemble(
        icepack.interpolate(grounded0 * SMB, Q) * firedrake.dx(mesh))
    summaryData = {
        'year': [0],
        'DVG': [0, 0],
        'DVF': [0, 0],
        'deltaVF': [0, 0],
        'deltaVG': [0, 0],
        'gArea': [float(gArea0)],
        'fArea': [float(fArea0)],
        'meltTot': [float(meltTot)],
        'area': float(area),
        'SMBgrounded': [float(SMBgrounded)],
        'SMBfloating': [float(SMBfloating)],
        'dTsum': 1.
    }  # dTsum fixed - code modes needed to change
    return summaryData
示例#11
0
 def value_form(self):
     # volume integral
     self.detDT.interpolate(fd.det(fd.grad(self.Q.T)))
     if min(self.detDT.vector()) > 0.05:
         integrand = (self.sigma - self.f)**2
     else:
         integrand = np.nan * (self.sigma - self.f)**2
     return integrand * fd.dx(metadata={"quadrature_degree": 1})
示例#12
0
文件: mms.py 项目: mfkiwl/sapphire
        def weak_form_residual(self):

            return super().weak_form_residual() \
                - mms_source(
                    sim = self,
                    strong_residual = strong_residual,
                    manufactured_solution = manufactured_solution)\
                *fe.dx(degree = self.quadrature_degree)
示例#13
0
def poisson_gll(mesh, degree):
    V = FunctionSpace(
        mesh, FiniteElement('Q', mesh.ufl_cell(), degree, variant='spectral'))
    u = TrialFunction(V)
    v = TestFunction(V)
    dim = mesh.topological_dimension()
    finat_rule = gauss_lobatto_legendre_cube_rule(dim, degree)
    return dot(grad(u), grad(v)) * dx(rule=finat_rule)
def initial_values(sim):

    print("Solving steady heat driven cavity to obtain initial values")

    Ra = 2.518084e6

    Pr = 6.99

    sim.grashof_number = sim.grashof_number.assign(Ra / Pr)

    sim.prandtl_number = sim.prandtl_number.assign(Pr)

    dim = sim.mesh.geometric_dimension()

    T_c = sim.cold_wall_temperature.__float__()

    w = fe.interpolate(
        fe.Expression((0., ) + (0., ) * dim + (T_c, ), element=sim.element),
        sim.function_space)

    F = heat_driven_cavity_variational_form_residual(
        sim=sim, solution=w) * fe.dx(degree=sim.quadrature_degree)

    T_h = sim.hot_wall_temperature.__float__()

    problem = fe.NonlinearVariationalProblem(
        F=F,
        u=w,
        bcs=dirichlet_boundary_conditions(sim),
        J=fe.derivative(F, w))

    solver = fe.NonlinearVariationalSolver(problem=problem,
                                           solver_parameters={
                                               "snes_type": "newtonls",
                                               "snes_monitor": True,
                                               "ksp_type": "preonly",
                                               "pc_type": "lu",
                                               "mat_type": "aij",
                                               "pc_factor_mat_solver_type":
                                               "mumps"
                                           })

    def solve():

        solver.solve()

        return w

    w, _ = \
        sapphire.continuation.solve_with_bounded_regularization_sequence(
            solve = solve,
            solution = w,
            backup_solution = fe.Function(w),
            regularization_parameter = sim.grashof_number,
            initial_regularization_sequence = (
                0., sim.grashof_number.__float__()))

    return w
示例#15
0
    def mass(self):

        u = self.solution_fields["u"]
        
        psi_p = self.test_functions["p"]
        
        dx = fe.dx(degree = self.quadrature_degree)
        
        return psi_p*div(u)*dx
示例#16
0
 def mass(self):
     
     u, _ = fe.split(self.solution)
     
     _, psi_p = fe.TestFunctions(self.solution_space)
     
     dx = fe.dx(degree = self.quadrature_degree)
     
     return psi_p*div(u)*dx
示例#17
0
    def momentum(self):

        u_t = self.time_discrete_terms()

        psi_u, _ = fe.TestFunctions(self.solution_space)

        dx = fe.dx(degree=self.quadrature_degree)

        return super().momentum() + dot(psi_u, u_t) * dx
    def energy(self):

        _, T_t = self.time_discrete_terms()

        _, _, psi_T = fe.TestFunctions(self.solution_space)

        dx = fe.dx(degree=self.quadrature_degree)

        return super().energy() + psi_T * T_t * dx
示例#19
0
    def energy(self):

        T_t = self.time_discrete_terms["T"]

        psi_T = self.test_functions["T"]

        dx = fe.dx(degree=self.quadrature_degree)

        return super().energy() + psi_T * T_t * dx
示例#20
0
    def momentum(self):

        u_t = self.time_discrete_terms["u"]

        psi_u = self.test_functions["u"]

        dx = fe.dx(degree=self.quadrature_degree)

        return super().momentum() + dot(psi_u, u_t) * dx
示例#21
0
    def scale(self, **kwargs):
        r"""Return the positive, convex part of the action functional

        The positive part of the action functional is used as a dimensional
        scale to determine when to terminate an optimization algorithm.
        """
        metadata = {"quadrature_degree": self.quadrature_degree(**kwargs)}
        dx = firedrake.dx(metadata=metadata)
        return (self.viscosity(**kwargs) + self.friction(**kwargs)) * dx
示例#22
0
def calculate_exner0(state, theta0, rho0):
    # exner function
    Vr = rho0.function_space()
    exner = Function(Vr).interpolate(
        thermodynamics.exner_pressure(state.parameters, rho0, theta0))
    exner0 = assemble(exner * dx) / assemble(
        Constant(1) * dx(domain=state.mesh))

    return exner0
示例#23
0
def solve_something(mesh):
    V = fd.FunctionSpace(mesh, "CG", 1)
    u = fd.Function(V)
    v = fd.TestFunction(V)

    x, y = fd.SpatialCoordinate(mesh)
    # f = fd.sin(x) * fd.sin(y) + x**2 + y**2
    # uex = x**4 * y**4
    uex = fd.sin(x) * fd.sin(y)  #*(x*y)**3
    # def source(xs, ys):
    #     return 1/((x-xs)**2+(y-ys)**2 + 0.1)
    # uex = source(0, 0)
    uex = uex - fd.assemble(uex * fd.dx) / fd.assemble(1 * fd.dx(domain=mesh))
    # f = fd.conditional(fd.ge(abs(x)-abs(y), 0), 1, 0)
    from firedrake import inner, grad, dx, ds, div, sym
    eps = fd.Constant(0.0)
    f = uex - div(grad(uex)) + eps * div(grad(div(grad(uex))))
    n = fd.FacetNormal(mesh)
    g = inner(grad(uex), n)
    g1 = inner(grad(div(grad(uex))), n)
    g2 = div(grad(uex))
    # F = 0.1 * inner(u, v) * dx + inner(grad(u), grad(v)) * dx + inner(grad(grad(u)), grad(grad(v))) * dx - f * v * dx - g * v * ds
    F = inner(u, v) * dx + inner(grad(u),
                                 grad(v)) * dx - f * v * dx - g * v * ds
    F += eps * inner(div(grad(u)), div(grad(v))) * dx
    F += eps * g1 * v * ds
    F -= eps * g2 * inner(grad(v), n) * ds
    # f = -div(grad(uex))
    # F = inner(grad(u), grad(v)) * dx - f * v * dx

    # bc = fd.DirichletBC(V, uex, "on_boundary")
    bc = None
    fd.solve(F == 0,
             u,
             bcs=bc,
             solver_parameters={
                 "ksp_type": "cg",
                 "ksp_atol": 1e-13,
                 "ksp_rtol": 1e-13,
                 "ksp_dtol": 1e-13,
                 "ksp_stol": 1e-13,
                 "pc_type": "jacobi",
                 "pc_factor_mat_solver_type": "mumps",
                 "snes_type": "ksponly",
                 "ksp_converged_reason": None
             })
    print("||u-uex||             =", fd.norm(u - uex))
    print("||grad(u-uex)||       =", fd.norm(grad(u - uex)))
    print("||grad(grad(u-uex))|| =", fd.norm(grad(grad(u - uex))))
    err = fd.Function(
        fd.TensorFunctionSpace(mesh, "DG",
                               V.ufl_element().degree() - 2)).interpolate(
                                   grad(grad(u - uex)))
    # err = fd.Function(fd.FunctionSpace(mesh, "DG", V.ufl_element().degree())).interpolate(u-uex)
    fd.File(outdir + "sln.pvd").write(u)
    fd.File(outdir + "err.pvd").write(err)
示例#24
0
    def value_form(self):
        """Evaluate misfit functional."""
        nu = self.pde_solver.viscosity

        if self.pde_solver.failed_to_solve:  # return NaNs if state solve fails
            return np.nan * fd.dx(self.pde_solver.mesh_m)
        else:
            z = self.pde_solver.solution
            u, p = fd.split(z)
            return nu * fd.inner(fd.grad(u), fd.grad(u)) * fd.dx
示例#25
0
def estimate_timestep(mesh, V, c, estimate_max_eigenvalue=True):
    """Estimate the maximum stable timestep based on the spectral radius
    using optionally the Gershgorin Circle Theorem to estimate the
    maximum generalized eigenvalue. Otherwise computes the maximum
    generalized eigenvalue exactly

    ONLY WORKS WITH KMV ELEMENTS
    """

    u, v = fire.TrialFunction(V), fire.TestFunction(V)
    quad_rule = finat.quadrature.make_quadrature(V.finat_element.cell,
                                                 V.ufl_element().degree(),
                                                 "KMV")
    dxlump = fire.dx(rule=quad_rule)
    A = fire.assemble(u * v * dxlump)
    ai, aj, av = A.petscmat.getValuesCSR()
    av_inv = []
    for value in av:
        if value == 0:
            av_inv.append(0.0)
        else:
            av_inv.append(1 / value)
    Asp = scipy.sparse.csr_matrix((av, aj, ai))
    Asp_inv = scipy.sparse.csr_matrix((av_inv, aj, ai))

    K = fire.assemble(c * c * dot(grad(u), grad(v)) * dxlump)
    ai, aj, av = K.petscmat.getValuesCSR()
    Ksp = scipy.sparse.csr_matrix((av, aj, ai))

    # operator
    Lsp = Asp_inv.multiply(Ksp)
    if estimate_max_eigenvalue:
        # absolute maximum of diagonals
        max_eigval = np.amax(np.abs(Lsp.diagonal()))
    else:
        print(
            "Computing exact eigenvalues is extremely computationally demanding!",
            flush=True,
        )
        max_eigval = scipy.sparse.linalg.eigs(Ksp,
                                              M=Asp,
                                              k=1,
                                              which="LM",
                                              return_eigenvectors=False)[0]

    # print(max_eigval)
    if np.sqrt(max_eigval) > 0.0:
        max_dt = np.float(2 / np.sqrt(max_eigval))
    else:
        max_dt = 100000000
    #print(
    #    f"Maximum stable timestep should be about: {np.float(2 / np.sqrt(max_eigval))} seconds",
    #    flush=True,
    #)
    return max_dt
示例#26
0
 def momentum(self):
     
     _, u, T = fe.split(self.solution)
     
     d = self.solid_velocity_relaxation(temperature = T)
     
     _, psi_u, _ = fe.TestFunctions(self.solution_space)
     
     dx = fe.dx(degree = self.quadrature_degree)
     
     return super().momentum() + dot(psi_u, d*u)*dx
示例#27
0
def variational_form_residual(sim, solution):

    u = solution

    v = fe.TestFunction(solution.function_space())

    dot, grad = fe.dot, fe.grad

    dx = fe.dx(degree=sim.quadrature_degree)

    return -dot(grad(v), grad(u)) * dx
示例#28
0
 def weak_form_residual(self):
     
     u = self.solution
     
     v = fe.TestFunction(self.solution_space)
     
     dot, grad = fe.dot, fe.grad
     
     dx = fe.dx(degree = self.quadrature_degree)
     
     return -dot(grad(v), grad(u))*dx
示例#29
0
    def scale(self, **kwargs):
        r"""Return the positive, convex part of the action functional

        The positive part of the action functional is used as a dimensional
        scale to determine when to terminate an optimization algorithm.
        """
        u = kwargs["velocity"]
        mesh = u.ufl_domain()
        metadata = {"quadrature_degree": self.quadrature_degree(**kwargs)}
        dx = firedrake.dx(metadata=metadata)
        ds_b = firedrake.ds_b(domain=mesh, metadata=metadata)
        return self.viscosity(**kwargs) * dx + self.friction(**kwargs) * ds_b
示例#30
0
 def momentum(self):
     
     u, p = fe.split(self.solution)
     
     Re = self.reynolds_number
     
     psi_u, _ = fe.TestFunctions(self.solution_space)
     
     dx = fe.dx(degree = self.quadrature_degree)
     
     return (dot(psi_u, grad(u)*u) - div(psi_u)*p + \
         2./Re*inner(sym(grad(psi_u)), sym(grad(u))))*dx