import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import fsolve
= 202 # outgoing radiation
A = 1.9 # outgoing radiation
B = 1.6*B # transport parameter
k = lambda y: 1 - 0.482*(3*y**2 - 1)/2 # solar weighting
s = 0.32 # water albedo
aw = 0.62 # ice albedo
ai = -10.0 # critical temperature for ice formation
Tc = 342.0 # solar constant (1380 W/m^2 divided by 4) Q
16 EBM with latitude IV
It is possible to solve the latitude-dependent EBM (steady-state) in a slightly more direct way (one that does not require making algebraic simplifications). We can do this by using a nonlinear solver such as Newton’s method. In essence, we are seeking the solution to: \[\begin{equation*} T = \Phi(T) = \frac{Q s(y)[1 - a(T)] - A + k\bar{T}}{B + k} \end{equation*}\] where in the above, \(T(y)\) replaces \(T_\infty(y)\).
In your problem class, you will go through the design of the following Python code, which is also found in the code repository.
First, the appropriate constants are defined.
Here we define the albedo function \(a(y)\) and also the function that we would seek to solve by Newton’s method
def afunc(y, ys):
# Non-smooth albedo function
# We want to make 'a' same dimensions as 'y'. Occasionally there are issues if we send in a vector vs. scalar
= np.array(y, ndmin=1) # Converts scalars to arrays but keeps arrays unchanged
y = np.zeros_like(y) # Same shape as y
a
= 0*y
a for i, yy in enumerate(y):
if yy > ys:
= ai
aa elif yy < ys:
= aw
aa else:
= (ai+aw)/2
aa = aa
a[i] return a
def myF(X):
# Total number of unknowns is N+1
= len(X)-1
N = X[0:N] # Be careful! Python list does not include last
T = X[N] # This is the N+1th element!
ys
# abar from eqn (14.5) of the notes
= ai + (aw - ai)*ys*(1 - 0.241*(ys**2-1))
abar # Tbar_inf from eqn (14.4) of the notes
= (Q*(1-abar) - A)/B
Tb
# For the given T values, compute Phi at each y
= (k*Tb + Q*s(y)*(1 - afunc(y, ys)) - A)/(B+k)
Phi
= np.zeros(N+1)
F 0:N] = T - Phi
F[
# Need one extra equation
= (k*Tb + Q*s(ys)*(1 - (ai+aw)/2) - A)/(B+k)
PhiC # Phi only has one entry
# PhiC = PhiC[0]
= PhiC - Tc
F[N]
return F
We should create an initial guess of the temperature profile. Here is a ‘random’ guess that goes from high to low.
# Initialise the mesh with N points
= 100
N = np.linspace(0, 1, N)
y
# Iterative scheme
# Form an initial guess
# Try this one for the fake solution
= 20; Tpole = -12;
Tequator = Tequator + (Tpole - Tequator)*y
T0
plt.plot(y, T0)1)
plt.grid("Initial guess of temperature") plt.title(
Text(0.5, 1.0, 'Initial guess of temperature')
Now we attempt to solve the system twice, once with an initial guess of the ice line for small \(y\) and one with an initial guess with larger \(y\). We should play around with parameters to make sure the solutions are robust, and also examine the residuals.
# We also need a guess of the ice line position
= 0.3
ysguess # Form a system of N+1 unknowns
= np.append(T0, ysguess)
guess
# Run the solver
= lambda X: myF(X)
fwd = fsolve(fwd, guess, full_output=1)
sol, info, ier, msg print(msg)
= sol[0:N]
T = sol[N]
ys1 = np.linspace(0, 1, N)
y
'-o')
plt.plot(y, T, -20, 20], '--')
plt.plot([ys1, ys1], [1)
plt.grid("Ice line, ys1 = %1.3f" % ys1);
plt.title(
# Solve it again with a higher ice line position
= 0.9
ysguess # Form a system of N+1 unknowns
= np.append(T0, ysguess)
guess
# Run the solver
= lambda X: myF(X)
fwd = fsolve(fwd, guess, full_output=1)
sol, info, ier, msg print(msg)
= sol[0:N]
T = sol[N]
ys2 = np.linspace(0, 1, N)
y
'-o')
plt.plot(y, T, -20, 20], '--')
plt.plot([ys2, ys2], [1)
plt.grid("Ice line, ys1 = %1.3f" % ys1); plt.title(
The solution converged.
The solution converged.