def n_min(self, n_min, apply_to_preconditioner=False): """Ensure n \geq n_min everywhere. If apply_to_preconditioner is True,then this is only done to the preconditioner.""" if apply_to_preconditioner: self.set_n_pre( fd.conditional(fd.lt(fd.real(self._n_pre), n_min), n_min, self._n_pre)) else: self.set_n( fd.conditional(fd.lt(fd.real(self._n), n_min), n_min, self._n))
def terminus(u, h, s): r"""Return the terminal stress part of the ice stream action functional The power exerted due to stress at the ice calving terminus :math:`\Gamma` is .. math:: E(u) = \frac{1}{2}\int_\Gamma\left(\rho_Igh^2 - \rho_Wgd^2\right) u\cdot \nu\, ds where :math:`d` is the water depth at the terminus. We assume that sea level is at :math:`z = 0` for purposes of calculating the water depth. Parameters ---------- u : firedrake.Function ice velocity h : firedrake.Function ice thickness s : firedrake.Function ice surface elevation ice_front_ids : list of int numeric IDs of the parts of the boundary corresponding to the calving front """ from firedrake import conditional, lt d = conditional(lt(s - h, 0), s - h, 0) τ_I = ρ_I * g * h**2 / 2 τ_W = ρ_W * g * d**2 / 2 ν = firedrake.FacetNormal(u.ufl_domain()) return (τ_I - τ_W) * inner(u, ν)
def rate_factor(T): r"""Compute the rate factor in Glen's flow law for a given temperature The strain rate :math:`\dot\varepsilon` of ice resulting from a stress :math:`\tau` is .. math:: \dot\varepsilon = A(T)\tau^3 where :math:`A(T)` is the temperature-dependent rate factor: .. math:: A(T) = A_0\exp(-Q/RT) where :math:`R` is the ideal gas constant, :math:`Q` has units of energy per mole, and :math:`A_0` is a prefactor with units of pressure :math:`\text{MPa}^{-3}\times\text{yr}^{-1}`. Parameters ---------- T : float, np.ndarray, or UFL expression The ice temperature Returns ------- A : same type as T The ice fluidity """ import ufl if isinstance(T, ufl.core.expr.Expr): cold = firedrake.lt(T, transition_temperature) A0 = firedrake.conditional(cold, A0_cold, A0_warm) Q = firedrake.conditional(cold, Q_cold, Q_warm) A = A0 * firedrake.exp(-Q / (R * T)) if isinstance(T, firedrake.Constant): return firedrake.Constant(A) return A cold = T < transition_temperature warm = ~cold if isinstance(T, np.ndarray) else (not cold) A0 = A0_cold * cold + A0_warm * warm Q = Q_cold * cold + Q_warm * warm return A0 * np.exp(-Q / (R * T))
# Use the static condensation PC for hybridized problems # and use a direct solve on the reduced system for lambda_h "pc_python_type": "firedrake.SCPC", "pc_sc_eliminate_fields": "0, 1", "condensed_field": { "ksp_type": "preonly", "pc_type": "lu", "pc_factor_mat_solver_type": "mumps" } } solver = fd.NonlinearVariationalSolver(problem, solver_parameters=hybrid_solver_params) # ----------------- wave_speed = fd.conditional(fd.lt(np.abs(vnorm), tol), h / tol, h / vnorm) # CFL dt_ = fd.interpolate(wave_speed, DG1).dat.data.min() * cfl outfile = fd.File(f"plots/adr-hdg-n-{refine}-p-{order}.pvd", project_output=True) dt = dt_ # dtime dtc.assign(dt_) # %% # solve problem # initialize timestep t = 0.0 it = 0 p = 0
shock = fd.interpolate(vshock * np.abs(R), DG0) shock.rename('vshock') F = F1 prob = fd.NonlinearVariationalProblem(F, c, bcs=t_bc) transport = fd.NonlinearVariationalSolver(prob) # %% # 4) Solve problem # ----------------- t = 0.0 it = 0 dt0 = dt cfl_conditional = fd.conditional(fd.lt(np.abs(vnorm), tol), 1 / tol, h / vnorm) outfile = fd.File("plots/sb_t_supg.pvd") sol = fd.Function(W) c0.assign(0.) # initialize timestep while t < sim_time: # move next time step print("* iteration= {:4d}, dtime= {:8.6f}, time={:8.6f}".format(it, dt, t)) # SB idt.assign(1 / dt) fd.solve(a == L, sol, bcs=bcs) vel.assign(sol.sub(0)) Pe = vnorm * h / (2.0 * fd.det(Diff))
J = fd.derivative(F, w, dw) problem = fd.NonlinearVariationalProblem(F, w, bcs, J) param = { 'snes_type': 'newtonls', 'snes_max_it': 100, 'ksp_type': 'gmres', 'ksp_rtol': 1e-3 } solver = fd.NonlinearVariationalSolver(problem, solver_parameters=param) # %% # 4) Solve problem # ----------------- wave_speed = fd.conditional(fd.lt(abs(vnorm), tol), h_E/tol, h_E/vnorm) outfile = fd.File("plots/sb_adr_fi.pvd") w0.sub(2).assign(0.0) # initialize timestep t = 0.0 it = 0 dt = np.sqrt(tol) while t < sim_time: # move next time step t += dt print("* iteration= {:4d}, dtime= {:8.6f}, time={:8.6f}".format(it, dt, t)) # solver system: SB + tracer