function bergschrund()
% solve ode for steady glacier thickness with ice flux q = x*(1-x/2)
%% Parameters
n = 3;
mu = 0.1;
%% Numerical solutions of rescaled boundary layer problems
opts = odeset('reltol',1e-6);
xinf = 10; xeps = 1e-4; Heps =
2^(n/(2*n+2))*(n+2)^(1/(2*n+2))*xeps^(1/2); % analytical approximation
of singular behaviour
[xh2,Hh2] = ode45(@(x,H) ((n+2)*x.*H.^(-(n+2))).^(1/n)-1 , [xeps xinf]
, Heps , opts);
xinf = 10; Hinf = ((n+2)*xinf).^(1/(n+2)); % analytical approximation
of far field behaviour
[xh1,Hh1] = ode45(@(x,H) 1-((n+2)*x.*H.^(-(n+2))).^(1/n) , [xinf 0] ,
Hinf , opts);
Hhstar = Hh1(end),
%% Numerical solution
opts = odeset('reltol',1e-6);
xeps = 1e-4; Heps = mu^(-
n/(2*n+2))*2^(n/(2*n+2))*(n+2)^(1/(2*n+2))*xeps^(1/2); % analytical
approximation of singular behaviour at x = 2
[xn,Hn] = ode45(@ode_fun,[2-xeps 0],Heps,opts);
function dHdx = ode_fun(x,H)
dHdx = (1-((n+2)*x.*(1-x/2).*H.^(-(n+2))).^(1/n))/mu;
end
%% Outer solution
x = linspace(0,2,100);
H = ((n+2)*x.*(1-x/2)).^(1/(n+2));
%% Inner solutions
x1 = mu^((n+2)/(n+1))*xh1;
H1 = mu^(1/(n+1))*Hh1;
x2 = 2-mu^((n+2)/(n+1))*xh2;
H2 = mu^(1/(n+1))*Hh2;
%% Plot solutions
figure(1); clf;
set(gcf,'Paperpositionmode','auto','units','centimeters','position',[2
4 12 8]);
set(gcf,'DefaultAxesFontSize',12,'DefaultTextFontSize',12);
plot(xn,Hn,'b-','linewidth',2);
hold on;
plot(x,H,'k--',x1,H1,'r--',x2,H2,'r--');
xlabel('$x$','interpreter','latex');
ylabel('$H$','interpreter','latex');
xlim([0 2]);
% %% Save figure
% print(gcf,'-depsc2',mfilename,'-loose');
%% Plot other numerical solutions of boundary layer at x = 0
figure(2); clf;
set(gcf,'Paperpositionmode','auto','units','centimeters','position',[2
4 12 8]);
set(gcf,'DefaultAxesFontSize',12,'DefaultTextFontSize',12);
xinf = 10;
x = linspace(0,xinf,100);
plot(x,((n+2)*x).^(1/(n+2)),'k--','linewidth',2); % far-field
behaviour
hold on;
xinf = 10; H0s = [0.9:.02:1.1]*Hhstar; % guesses at initial value
for H0 = H0s
[xh1,Hh1] = ode45(@(x,H) 1-((n+2)*x.*H.^(-(n+2))).^(1/n) , [0
xinf] , H0 );
plot(xh1,Hh1,'-');
end
xlabel('$hat{x}$','interpreter','latex');
ylabel('$hat{H}$','interpreter','latex');
% %% Save figure
% print(gcf,'-depsc2',[mfilename,'2'],'-loose');
end
function carbon_cycles()
% solves equations for albedo and CO2 partial pressure
% da/dt = B(T) - a
% dp/dt = alpha*(1-w*p^mu*e^T)
% T = T(a,p)
% plots trajectories on phase plane
%
% IJH 28 Sept 2016
%% Dimensionless parameters
ap = 0.58;
am = 0.11;
c1 = 0.2;
c2 = 0.6;
mu = 0.3;
q = 1.37;
lambda = 0.25;
nu = 0.18;
alpha = .01; % 1.05 / .01
w = 1; % 1 / .15
%% Scaling parameters (for plotting dimesional quantity)
sc.p = 36; % [Pa]
sc.p = 1; % to plot as dimensionless
%% Functions
B = @(theta) ap-(ap-am)/2*(1+tanh(c1+c2*theta));
Theta = @(a,p) q/nu*(1-a)-1/nu+lambda*p;
dadt = @(a,p) B(Theta(a,p)) - a;
dpdt = @(a,p) alpha*(1-w*p.^mu.*exp(Theta(a,p)));
dydt = @(t,y) [ dadt(y(1),y(2)) ; dpdt(y(1),y(2)) ]; % y = [a,p]
%% Nullclines
a = linspace(am,ap,100+2); a = a(2:end-1);
p = NaN*a;
for i = 1:length(a)
p(i) = fzero(@(x) dadt(a(i),x),[-1e3 1e3]); % root-finding for
each a along a nullcline
end
a1 = a; p1 = p;
p = NaN*a;
for i = 1:length(a)
p(i) = fzero(@(x) dpdt(a(i),x),[0 1e3]); % root-finding for
each a along p nullcline
end
a2 = a; p2 = p;
%% Plot phase plane with nullclines and setup axes for solutions
figure(1); clf; width = 2; fontsize = 14;
set(gcf,'DefaultAxesFontSize',fontsize,'DefaultTextFontSize',fontsize)
;
%
set(gcf,'units','centimeters','Paperpositionmode','auto','position',[2
2 20 10]);
ax(1) = axes('position',[0.1 0.2 0.35 0.75]);
plot(sc.p*p1,a1,'k-',sc.p*p2,a2,'b-','linewidth',width); %
nullclines
xlabel('$p / [p]$','interpreter','latex');
ylabel('$a$','interpreter','latex');
ylim([am,ap]);
xlim([0 2*sc.p]);
hold on;
ax(2) = axes('position',[0.6 0.6 0.35 0.35]);
hold on;
box on;
set(gca,'XTickLabel',{});
ylabel('$a$','interpreter','latex');
ax(3) = axes('position',[0.6 0.2 0.35 0.35]);
hold on;
box on;
xlabel('$t / [t]$','interpreter','latex');
ylabel('$p / [p]$','interpreter','latex');
%% Solve trajectories and add to figures
n_trajectories = 1;
length_trajectory = 10/alpha;
for n = 1:n_trajectories
p0 = 2*rand; a0 = am+(ap-am)*rand; %
random starting point
% [p0,a0] = ginput(1); p0 = p0/sc.p; %
graphical input for trajectory starting point (click on phase plane)
opts = odeset('reltol',1e-6);
[t,y] = ode45(dydt,[0 length_trajectory],[a0,p0],opts); % use
ode45 to solve equations
a = y(:,1); p = y(:,2);
axes(ax(1));
plot(sc.p*p,a,'r-',sc.p*p(1),a(1),'ro','linewidth',width);
axes(ax(2));
plot(t,a,'r-','linewidth',width);
axes(ax(3));
plot(t,sc.p*p,'r-','linewidth',width);
end
% %% Save figure
% axes(ax(1)); text(0.95,0.95,['$alpha =
$',num2str(alpha)],'units','normalized','horizontalalignment','right',
'verticalalignment','top','interpreter','latex');
% print(gcf,'-depsc2',[mfilename,'_alpha',num2str(alpha),'.eps'],'-
loose');
end
% greenhouse factor gamma for varying tau_s when T = T_s
(tau/tau_s)^(R/M_a/c_p)
% IJH 22 Sept 2018
clear;
%% Parameters
M_a = 29e-3; %kg/mol
R = 8.3; %J/K/mol
g = 9.8; %m/s^2
c_p = 10^3; %J/kg/K
%% Calculate gamma(tau_s)
z = linspace(0,1,101); % pts to discretise integral
tau_ss = linspace(0,10,101); % values of tau_s
gammas = NaN*tau_ss;
for j = 1:length(tau_ss)
tau_s = tau_ss(j);
gammas(j) = exp(-2*tau_s) +
tau_s*trapz(z,2*z.^(4*R/M_a/c_p).*exp(-2*tau_s*z)); % calculate
integral expression for gamma using trapezium rule
end
%% Plot gamma(tau_s)
figure(1); clf;
set(gcf,'Paperpositionmode','auto','units','centimeters','position',[2
4 12 8]);
set(gcf,'DefaultAxesFontSize',12,'DefaultTextFontSize',12);
plot(tau_ss,gammas,'b-','linewidth',2);
ylim([0 1]);
hold on;
plot(tau_ss,1-2*tau_ss*4*R/(4*R+M_a*c_p),'r--'); % small tau_s
approx
plot(tau_ss,(2*tau_ss).^(-4*R/M_a/c_p).*gamma(1+4*R/M_a/c_p),'r--
'); % large tau_s approx
xlabel('Optical thickness $tau_s$','interpreter','latex');
ylabel('Greenhouse factor $gamma$','interpreter','latex');
%% Save figure
% print(gcf,'-depsc2',mfilename,'-loose');
% mountain glacier model
% IJH 18 October 2020
clear;
set(0,'DefaultTextInterpreter','latex');
set(0,'DefaultTextFontSize',12);
set(0,'DefaultAxesFontSize',12);
fn = mfilename;
% dimensionless parameters
pp.n = 3; % flow-law exponent
pp.a_fun = @(x) 1-x; % net accumulation funtion
pp.dt = 1e-2; % timestep
% steady state
x_st = linspace(0,2,101)';
H_st = ((pp.n+2)*x_st.*(1-x_st/2)).^(1/(pp.n+2));
% initial condition
t = 0;
l = 1;
% sigma = l*10.^(linspace(-6,0,101))'; % exponential spacing
n = 400; dx0 = 1e-7; r = fzero(@(r) 1/dx0-(r.^(n+1)-1)/(r-1),1.1); sigma =
l*[cumsum(dx0*r.^(0:n)')]; % geometric spacing
% sigma = [0.1*sigma(1:end-1); linspace(0.1,1,201)']; % geometric spacing +
constant spacing
x = sigma;
H = max(0,(pp.n+2)*x.*(l/2-x/2)).^(1/(pp.n+2));
x2 = linspace(-4,0,401)'; % ghost characteristics in x<0
H2 = 0*x2.^0;
x = [x2; x];
H = [H2; H];
s = zeros(size(x));
% solve characteristic equations
ts = t;
xs = x;
Hs = H;
ss = s;
i1 = 1:length(x); % indices of characeteristics
i2 = []; % indices of shocks
while t+pp.dt<3
i2 = find(s); % indices of shocks
i3 = find(isnan(x)); % indices of terminated characteristics
i4 = find(x<0); % indices of 'ghost' characteristics
i1 = setdiff(1:length(x),union(i2,[i3;i4])); % indices of characeteristics
a = pp.a_fun(x).*(x>=0); % accumulation rate
H(i1) = H(i1) + pp.dt*a(i1); % advance H along characteristics
H(i2) = H(i2) + pp.dt*a(i2); % advance H along shock
H(H<=0) = 0; % cap H = 0
x(i1) = x(i1) + pp.dt*H(i1).^(pp.n+1); % advance characteristics
x(i2) = x(i2) + pp.dt*(H(i2).^(pp.n+1)-H(s(i2)).^(pp.n+1))/(pp.n+2); %
advance shocks
x(i4) = min(x(i4)+pp.dt*1,0); % advance 'ghost' charatacteristics at speed
1 in x<0
t = t + pp.dt; % advance time
ii = union(i1,i2); % indices of characteristics and shocks
tmps = find(x(ii(1:end-1))>x(ii(2:end))); % locate intersections
% label downstream characteristics of shocks
if ~isempty(tmps)
for tmp = flip(tmps')
if s(ii(tmp+1))>0
s(ii(tmp)) = s(ii(tmp+1)); % if crashed into a shock, take
over that shock
else
s(ii(tmp)) = ii(tmp+1); % if crashed into a characteristic,
that becomes downstream characteristic
end
x(ii(tmp+1)) = NaN; % terminated characteristics
s(ii(tmp+1)) = 0;
end
end
ts = [ts t];
xs = [xs x];
Hs = [Hs H];
ss = [ss s];
end
% blank out various entries
xs(xs<=0) = NaN;
xs(Hs<=0) = NaN;
Hs(Hs<=0) = NaN;
ss(ss<=0) = NaN;
% plot solutions
figure(1); clf;
set(gcf,'Paperpositionmode','auto','Units','centimeters','Position',[2 4 20
8]);
width = 1;
ax(1) = subplot(1,2,1);
xpts = 1:10:size(xs,1);
plot(xs(xpts,:)',ts(:)','k-','linewidth',width); % characteristics curves
hold on; plot(xs'.*ss'.^0,ts(:)','r.'); % shocks
xlabel('$x$')
ylabel('$t$');
xlim([0 3]);
box off;
ax(2) = subplot(1,2,2);
xpts = 1:10:size(xs,1);
plot3(xs(xpts,:)',ts(:)',0*Hs(xpts,:)','-','color',0.8*[1 1
1],'linewidth',width); % characteristics curves
hold on; plot3(xs'.*ss'.^0,ts(:)',0*Hs','r.'); % shocks
tpts = 1:20:size(ts,2);
hold on; plot3(xs(:,tpts),ones(length(x),1)*ts(tpts),Hs(:,tpts),'b-
','linewidth',width); % solution through time
xlabel('$x$')
ylabel('$t$');
zlabel('$H$');
xlim([0 3]);
ylim([0 3]);
ax(2).Position = ax(2).Position + [0 0.05 0 0];
% axes(ax(2)); view(10,40); print(gcf,'-depsc2',[fn]);
% axes(ax(2)); view(10,40); print(gcf,'-depsc2',[fn,'_fig1']); % l = 3;
% axes(ax(2)); view(10,40); print(gcf,'-depsc2',[fn,'_fig2']); % l = 1;
function sea_ice()
% solves sea ice model
% dH/dt = - Fo - Q/(1+H) Q<=0
% - Fo - Q Q>0
% for H>=0, OR H = 0
% uses a single ODE for both cases H>=0 and H<0. Numerical errors
% causes H to go slightly below 0; dHdt is then set to zero until it
% becomes positive allowing ice to start to grow again
%% Parameters
Fo = 0;
Q0 = 0;
omega = 2*pi*.1;
Q = @(t) Q0 + cos(omega*t);
%% Solve ODE
opts = odeset('reltol',1e-8);
[t,H] = ode45(@dHdt_fun,[0 2*2*pi/omega],0,opts);
% ODE
function dHdt = dHdt_fun(t,H)
dHdt = ( -Fo-Q(t)./(1+H) ).*( Q(t)<=0 ).*( H>=0 ) + ...
( -Fo-Q(t) ).*( Q(t)>0 ).*( H>=0 ) + ...
max(0,-Fo-Q(t)./(1+H)).*( H<0 );
end
%% Plot solution
figure(1); clf; width = 2; fontsize = 14;
set(gcf,'DefaultAxesFontSize',fontsize,'DefaultTextFontSize',fontsize)
;
set(gcf,'units','centimeters','Paperpositionmode','auto','position',[2
2 20 10]);
plot(omega/2/pi*t,H,'linewidth',width);
% hold on; plot(omega/2/pi*t,dHdt_fun(t,H)); % derivative
hold on; plot(omega/2/pi*t,max(0,-1-Q(t)/Fo),'r--'); % quasi-
steady approximation (small omega)
xlabel('$omega t / 2pi$','interpreter','latex');
ylabel('$H / [H]$','interpreter','latex');
% %% Save figure
% text(0.02,0.95,['$omega/2pi =
$',num2str(omega/2/pi)],'interpreter','latex','units','normalized','ho
rizontalalignment','left','verticalalignment','top');
% print(gcf,'-
depsc2',[mfilename,'_omega',num2str(omega/2/pi),'.eps'],'-loose');
end

matlab codes.pdf

  • 1.
    function bergschrund() % solveode for steady glacier thickness with ice flux q = x*(1-x/2) %% Parameters n = 3; mu = 0.1; %% Numerical solutions of rescaled boundary layer problems opts = odeset('reltol',1e-6); xinf = 10; xeps = 1e-4; Heps = 2^(n/(2*n+2))*(n+2)^(1/(2*n+2))*xeps^(1/2); % analytical approximation of singular behaviour [xh2,Hh2] = ode45(@(x,H) ((n+2)*x.*H.^(-(n+2))).^(1/n)-1 , [xeps xinf] , Heps , opts); xinf = 10; Hinf = ((n+2)*xinf).^(1/(n+2)); % analytical approximation of far field behaviour [xh1,Hh1] = ode45(@(x,H) 1-((n+2)*x.*H.^(-(n+2))).^(1/n) , [xinf 0] , Hinf , opts); Hhstar = Hh1(end), %% Numerical solution opts = odeset('reltol',1e-6); xeps = 1e-4; Heps = mu^(- n/(2*n+2))*2^(n/(2*n+2))*(n+2)^(1/(2*n+2))*xeps^(1/2); % analytical approximation of singular behaviour at x = 2 [xn,Hn] = ode45(@ode_fun,[2-xeps 0],Heps,opts); function dHdx = ode_fun(x,H) dHdx = (1-((n+2)*x.*(1-x/2).*H.^(-(n+2))).^(1/n))/mu; end %% Outer solution x = linspace(0,2,100); H = ((n+2)*x.*(1-x/2)).^(1/(n+2)); %% Inner solutions x1 = mu^((n+2)/(n+1))*xh1; H1 = mu^(1/(n+1))*Hh1; x2 = 2-mu^((n+2)/(n+1))*xh2; H2 = mu^(1/(n+1))*Hh2; %% Plot solutions figure(1); clf; set(gcf,'Paperpositionmode','auto','units','centimeters','position',[2 4 12 8]); set(gcf,'DefaultAxesFontSize',12,'DefaultTextFontSize',12); plot(xn,Hn,'b-','linewidth',2); hold on; plot(x,H,'k--',x1,H1,'r--',x2,H2,'r--'); xlabel('$x$','interpreter','latex'); ylabel('$H$','interpreter','latex'); xlim([0 2]); % %% Save figure % print(gcf,'-depsc2',mfilename,'-loose'); %% Plot other numerical solutions of boundary layer at x = 0 figure(2); clf; set(gcf,'Paperpositionmode','auto','units','centimeters','position',[2 4 12 8]); set(gcf,'DefaultAxesFontSize',12,'DefaultTextFontSize',12); xinf = 10;
  • 2.
    x = linspace(0,xinf,100); plot(x,((n+2)*x).^(1/(n+2)),'k--','linewidth',2);% far-field behaviour hold on; xinf = 10; H0s = [0.9:.02:1.1]*Hhstar; % guesses at initial value for H0 = H0s [xh1,Hh1] = ode45(@(x,H) 1-((n+2)*x.*H.^(-(n+2))).^(1/n) , [0 xinf] , H0 ); plot(xh1,Hh1,'-'); end xlabel('$hat{x}$','interpreter','latex'); ylabel('$hat{H}$','interpreter','latex'); % %% Save figure % print(gcf,'-depsc2',[mfilename,'2'],'-loose'); end
  • 3.
    function carbon_cycles() % solvesequations for albedo and CO2 partial pressure % da/dt = B(T) - a % dp/dt = alpha*(1-w*p^mu*e^T) % T = T(a,p) % plots trajectories on phase plane % % IJH 28 Sept 2016 %% Dimensionless parameters ap = 0.58; am = 0.11; c1 = 0.2; c2 = 0.6; mu = 0.3; q = 1.37; lambda = 0.25; nu = 0.18; alpha = .01; % 1.05 / .01 w = 1; % 1 / .15 %% Scaling parameters (for plotting dimesional quantity) sc.p = 36; % [Pa] sc.p = 1; % to plot as dimensionless %% Functions B = @(theta) ap-(ap-am)/2*(1+tanh(c1+c2*theta)); Theta = @(a,p) q/nu*(1-a)-1/nu+lambda*p; dadt = @(a,p) B(Theta(a,p)) - a; dpdt = @(a,p) alpha*(1-w*p.^mu.*exp(Theta(a,p))); dydt = @(t,y) [ dadt(y(1),y(2)) ; dpdt(y(1),y(2)) ]; % y = [a,p] %% Nullclines a = linspace(am,ap,100+2); a = a(2:end-1); p = NaN*a; for i = 1:length(a) p(i) = fzero(@(x) dadt(a(i),x),[-1e3 1e3]); % root-finding for each a along a nullcline end a1 = a; p1 = p; p = NaN*a; for i = 1:length(a) p(i) = fzero(@(x) dpdt(a(i),x),[0 1e3]); % root-finding for each a along p nullcline end a2 = a; p2 = p; %% Plot phase plane with nullclines and setup axes for solutions figure(1); clf; width = 2; fontsize = 14; set(gcf,'DefaultAxesFontSize',fontsize,'DefaultTextFontSize',fontsize) ; % set(gcf,'units','centimeters','Paperpositionmode','auto','position',[2 2 20 10]); ax(1) = axes('position',[0.1 0.2 0.35 0.75]); plot(sc.p*p1,a1,'k-',sc.p*p2,a2,'b-','linewidth',width); % nullclines xlabel('$p / [p]$','interpreter','latex'); ylabel('$a$','interpreter','latex');
  • 4.
    ylim([am,ap]); xlim([0 2*sc.p]); hold on; ax(2)= axes('position',[0.6 0.6 0.35 0.35]); hold on; box on; set(gca,'XTickLabel',{}); ylabel('$a$','interpreter','latex'); ax(3) = axes('position',[0.6 0.2 0.35 0.35]); hold on; box on; xlabel('$t / [t]$','interpreter','latex'); ylabel('$p / [p]$','interpreter','latex'); %% Solve trajectories and add to figures n_trajectories = 1; length_trajectory = 10/alpha; for n = 1:n_trajectories p0 = 2*rand; a0 = am+(ap-am)*rand; % random starting point % [p0,a0] = ginput(1); p0 = p0/sc.p; % graphical input for trajectory starting point (click on phase plane) opts = odeset('reltol',1e-6); [t,y] = ode45(dydt,[0 length_trajectory],[a0,p0],opts); % use ode45 to solve equations a = y(:,1); p = y(:,2); axes(ax(1)); plot(sc.p*p,a,'r-',sc.p*p(1),a(1),'ro','linewidth',width); axes(ax(2)); plot(t,a,'r-','linewidth',width); axes(ax(3)); plot(t,sc.p*p,'r-','linewidth',width); end % %% Save figure % axes(ax(1)); text(0.95,0.95,['$alpha = $',num2str(alpha)],'units','normalized','horizontalalignment','right', 'verticalalignment','top','interpreter','latex'); % print(gcf,'-depsc2',[mfilename,'_alpha',num2str(alpha),'.eps'],'- loose'); end
  • 5.
    % greenhouse factorgamma for varying tau_s when T = T_s (tau/tau_s)^(R/M_a/c_p) % IJH 22 Sept 2018 clear; %% Parameters M_a = 29e-3; %kg/mol R = 8.3; %J/K/mol g = 9.8; %m/s^2 c_p = 10^3; %J/kg/K %% Calculate gamma(tau_s) z = linspace(0,1,101); % pts to discretise integral tau_ss = linspace(0,10,101); % values of tau_s gammas = NaN*tau_ss; for j = 1:length(tau_ss) tau_s = tau_ss(j); gammas(j) = exp(-2*tau_s) + tau_s*trapz(z,2*z.^(4*R/M_a/c_p).*exp(-2*tau_s*z)); % calculate integral expression for gamma using trapezium rule end %% Plot gamma(tau_s) figure(1); clf; set(gcf,'Paperpositionmode','auto','units','centimeters','position',[2 4 12 8]); set(gcf,'DefaultAxesFontSize',12,'DefaultTextFontSize',12); plot(tau_ss,gammas,'b-','linewidth',2); ylim([0 1]); hold on; plot(tau_ss,1-2*tau_ss*4*R/(4*R+M_a*c_p),'r--'); % small tau_s approx plot(tau_ss,(2*tau_ss).^(-4*R/M_a/c_p).*gamma(1+4*R/M_a/c_p),'r-- '); % large tau_s approx xlabel('Optical thickness $tau_s$','interpreter','latex'); ylabel('Greenhouse factor $gamma$','interpreter','latex'); %% Save figure % print(gcf,'-depsc2',mfilename,'-loose');
  • 6.
    % mountain glaciermodel % IJH 18 October 2020 clear; set(0,'DefaultTextInterpreter','latex'); set(0,'DefaultTextFontSize',12); set(0,'DefaultAxesFontSize',12); fn = mfilename; % dimensionless parameters pp.n = 3; % flow-law exponent pp.a_fun = @(x) 1-x; % net accumulation funtion pp.dt = 1e-2; % timestep % steady state x_st = linspace(0,2,101)'; H_st = ((pp.n+2)*x_st.*(1-x_st/2)).^(1/(pp.n+2)); % initial condition t = 0; l = 1; % sigma = l*10.^(linspace(-6,0,101))'; % exponential spacing n = 400; dx0 = 1e-7; r = fzero(@(r) 1/dx0-(r.^(n+1)-1)/(r-1),1.1); sigma = l*[cumsum(dx0*r.^(0:n)')]; % geometric spacing % sigma = [0.1*sigma(1:end-1); linspace(0.1,1,201)']; % geometric spacing + constant spacing x = sigma; H = max(0,(pp.n+2)*x.*(l/2-x/2)).^(1/(pp.n+2)); x2 = linspace(-4,0,401)'; % ghost characteristics in x<0 H2 = 0*x2.^0; x = [x2; x]; H = [H2; H]; s = zeros(size(x)); % solve characteristic equations ts = t; xs = x; Hs = H; ss = s; i1 = 1:length(x); % indices of characeteristics i2 = []; % indices of shocks while t+pp.dt<3 i2 = find(s); % indices of shocks i3 = find(isnan(x)); % indices of terminated characteristics i4 = find(x<0); % indices of 'ghost' characteristics i1 = setdiff(1:length(x),union(i2,[i3;i4])); % indices of characeteristics a = pp.a_fun(x).*(x>=0); % accumulation rate H(i1) = H(i1) + pp.dt*a(i1); % advance H along characteristics H(i2) = H(i2) + pp.dt*a(i2); % advance H along shock H(H<=0) = 0; % cap H = 0 x(i1) = x(i1) + pp.dt*H(i1).^(pp.n+1); % advance characteristics x(i2) = x(i2) + pp.dt*(H(i2).^(pp.n+1)-H(s(i2)).^(pp.n+1))/(pp.n+2); % advance shocks x(i4) = min(x(i4)+pp.dt*1,0); % advance 'ghost' charatacteristics at speed 1 in x<0 t = t + pp.dt; % advance time ii = union(i1,i2); % indices of characteristics and shocks tmps = find(x(ii(1:end-1))>x(ii(2:end))); % locate intersections % label downstream characteristics of shocks if ~isempty(tmps) for tmp = flip(tmps') if s(ii(tmp+1))>0 s(ii(tmp)) = s(ii(tmp+1)); % if crashed into a shock, take over that shock else
  • 7.
    s(ii(tmp)) = ii(tmp+1);% if crashed into a characteristic, that becomes downstream characteristic end x(ii(tmp+1)) = NaN; % terminated characteristics s(ii(tmp+1)) = 0; end end ts = [ts t]; xs = [xs x]; Hs = [Hs H]; ss = [ss s]; end % blank out various entries xs(xs<=0) = NaN; xs(Hs<=0) = NaN; Hs(Hs<=0) = NaN; ss(ss<=0) = NaN; % plot solutions figure(1); clf; set(gcf,'Paperpositionmode','auto','Units','centimeters','Position',[2 4 20 8]); width = 1; ax(1) = subplot(1,2,1); xpts = 1:10:size(xs,1); plot(xs(xpts,:)',ts(:)','k-','linewidth',width); % characteristics curves hold on; plot(xs'.*ss'.^0,ts(:)','r.'); % shocks xlabel('$x$') ylabel('$t$'); xlim([0 3]); box off; ax(2) = subplot(1,2,2); xpts = 1:10:size(xs,1); plot3(xs(xpts,:)',ts(:)',0*Hs(xpts,:)','-','color',0.8*[1 1 1],'linewidth',width); % characteristics curves hold on; plot3(xs'.*ss'.^0,ts(:)',0*Hs','r.'); % shocks tpts = 1:20:size(ts,2); hold on; plot3(xs(:,tpts),ones(length(x),1)*ts(tpts),Hs(:,tpts),'b- ','linewidth',width); % solution through time xlabel('$x$') ylabel('$t$'); zlabel('$H$'); xlim([0 3]); ylim([0 3]); ax(2).Position = ax(2).Position + [0 0.05 0 0]; % axes(ax(2)); view(10,40); print(gcf,'-depsc2',[fn]); % axes(ax(2)); view(10,40); print(gcf,'-depsc2',[fn,'_fig1']); % l = 3; % axes(ax(2)); view(10,40); print(gcf,'-depsc2',[fn,'_fig2']); % l = 1;
  • 8.
    function sea_ice() % solvessea ice model % dH/dt = - Fo - Q/(1+H) Q<=0 % - Fo - Q Q>0 % for H>=0, OR H = 0 % uses a single ODE for both cases H>=0 and H<0. Numerical errors % causes H to go slightly below 0; dHdt is then set to zero until it % becomes positive allowing ice to start to grow again %% Parameters Fo = 0; Q0 = 0; omega = 2*pi*.1; Q = @(t) Q0 + cos(omega*t); %% Solve ODE opts = odeset('reltol',1e-8); [t,H] = ode45(@dHdt_fun,[0 2*2*pi/omega],0,opts); % ODE function dHdt = dHdt_fun(t,H) dHdt = ( -Fo-Q(t)./(1+H) ).*( Q(t)<=0 ).*( H>=0 ) + ... ( -Fo-Q(t) ).*( Q(t)>0 ).*( H>=0 ) + ... max(0,-Fo-Q(t)./(1+H)).*( H<0 ); end %% Plot solution figure(1); clf; width = 2; fontsize = 14; set(gcf,'DefaultAxesFontSize',fontsize,'DefaultTextFontSize',fontsize) ; set(gcf,'units','centimeters','Paperpositionmode','auto','position',[2 2 20 10]); plot(omega/2/pi*t,H,'linewidth',width); % hold on; plot(omega/2/pi*t,dHdt_fun(t,H)); % derivative hold on; plot(omega/2/pi*t,max(0,-1-Q(t)/Fo),'r--'); % quasi- steady approximation (small omega) xlabel('$omega t / 2pi$','interpreter','latex'); ylabel('$H / [H]$','interpreter','latex'); % %% Save figure % text(0.02,0.95,['$omega/2pi = $',num2str(omega/2/pi)],'interpreter','latex','units','normalized','ho rizontalalignment','left','verticalalignment','top'); % print(gcf,'- depsc2',[mfilename,'_omega',num2str(omega/2/pi),'.eps'],'-loose'); end