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)); %% x1 H1 x2 H2 Inner solutions = mu^((n+2)/(n+1))*xh1; = mu^(1/(n+1))*Hh1; = 2-mu^((n+2)/(n+1))*xh2; = 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]); 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]); each a along p nullcline end a2 = a; p2 = p; % root-finding for % root-finding for %% 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 i3 i4 i1 = = = = find(s); % indices of shocks find(isnan(x)); % indices of terminated characteristics find(x<0); % indices of 'ghost' characteristics 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 xs Hs ss = = = = [ts [xs [Hs [ss end % blank out xs(xs<=0) = xs(Hs<=0) = Hs(Hs<=0) = ss(ss<=0) = t]; x]; H]; s]; various entries NaN; NaN; NaN; 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--'); % quasisteady approximation (small omega) xlabel('$\omega t / 2\pi$','interpreter','latex'); ylabel('$H / [H]$','interpreter','latex'); % %% Save figure % text(0.02,0.95,['$\omega/2\pi = $',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