1 | subroutine spreadglacier_paleo(ngrid,nq,pqsurf, & |
---|
2 | phisfi0,timstep,ptsurf) |
---|
3 | |
---|
4 | use radinc_h, only : naerkind |
---|
5 | use comgeomfi_h |
---|
6 | implicit none |
---|
7 | |
---|
8 | !================================================================== |
---|
9 | ! Purpose |
---|
10 | ! ------- |
---|
11 | ! Spreading the glacier : N2, cf Umurhan et al 2017 |
---|
12 | ! |
---|
13 | ! Inputs |
---|
14 | ! ------ |
---|
15 | ! ngrid Number of vertical columns |
---|
16 | ! pqsurf(ngrid,nq) N2 ice tracer on surface kg/m2 |
---|
17 | ! phisfi0 = phisfinew the geopotential of the bedrock |
---|
18 | ! below the N2 ice |
---|
19 | ! ptsurf surface temperature |
---|
20 | ! timstep dstep = timestep in pluto day for the call of glacial flow |
---|
21 | |
---|
22 | ! Outputs |
---|
23 | ! ------- |
---|
24 | ! pqsurf(ngrid,nq) new value for N2 ice tracer on surface kg/m2 |
---|
25 | ! |
---|
26 | ! Authors |
---|
27 | ! ------- |
---|
28 | ! Tanguy Bertrand (2015,2022) |
---|
29 | ! |
---|
30 | !================================================================== |
---|
31 | |
---|
32 | #include "dimensions.h" |
---|
33 | #include "dimphys.h" |
---|
34 | #include "comcstfi.h" |
---|
35 | #include "surfdat.h" |
---|
36 | #include "comvert.h" |
---|
37 | #include "callkeys.h" |
---|
38 | #include "tracer.h" |
---|
39 | |
---|
40 | !----------------------------------------------------------------------- |
---|
41 | ! Arguments |
---|
42 | |
---|
43 | INTEGER ngrid, nq, ig, i |
---|
44 | REAL :: pqsurf(ngrid,nq) |
---|
45 | REAL :: phisfi0(ngrid) |
---|
46 | REAL :: ptsurf(ngrid) |
---|
47 | REAL timstep |
---|
48 | !----------------------------------------------------------------------- |
---|
49 | ! Local variables |
---|
50 | REAL tgla(ngrid),tbase(ngrid) !temperature at the base of glacier different of ptsurf |
---|
51 | REAL :: zdqsurf(ngrid) ! tendency of qsurf |
---|
52 | REAL massflow ! function |
---|
53 | REAL hlim,qlim,difflim,diff,stock,H0,totmasstmp |
---|
54 | INTEGER compt !compteur |
---|
55 | INTEGER slid ! option slid 0 or 1 |
---|
56 | INTEGER :: edge(4) ! index of the adjecent points, N,S,E,W |
---|
57 | INTEGER cas,inddeb,indfin |
---|
58 | REAL secu,dqch4,dqco |
---|
59 | REAL :: masstmp(ngrid) |
---|
60 | |
---|
61 | REAL :: masstot |
---|
62 | |
---|
63 | !---------------- INPUT ------------------------------------------------ |
---|
64 | |
---|
65 | difflim=0.5 ! limit height (m) between two adjacent point to start spreading the glacier |
---|
66 | zdqsurf(:)=0. |
---|
67 | !--------------- Dimensions ------------------------------------- |
---|
68 | |
---|
69 | ! distance between two adjacent latitude |
---|
70 | !distlim_lat=pi*rad/jjm/1000. ! km |
---|
71 | !distlim_diag=(distlim_lat*distlim_lat+distlim_lon*distlim_lon)**0.5 |
---|
72 | |
---|
73 | !! Threshold for ice thickness for which we activate the glacial flow |
---|
74 | hlim=10. !m |
---|
75 | qlim=hlim*1000. ! kg |
---|
76 | !! Security for not depleted all ice too fast in one timestep |
---|
77 | secu=4 |
---|
78 | |
---|
79 | !************************************* |
---|
80 | ! Loop over all points |
---|
81 | !************************************* |
---|
82 | DO ig=1,ngrid |
---|
83 | !if (ig.eq.ngrid) then |
---|
84 | ! print*, 'qpole=',pqsurf(ig,igcm_n2),qlim |
---|
85 | !endif |
---|
86 | |
---|
87 | !************************************* |
---|
88 | ! if significant amount of ice, where qsurf > qlim |
---|
89 | !************************************* |
---|
90 | IF (pqsurf(ig,igcm_n2).gt.qlim) THEN |
---|
91 | |
---|
92 | !************************************* |
---|
93 | ! temp glacier with gradient 15 K / km |
---|
94 | !************************************* |
---|
95 | ! surface temperature pts |
---|
96 | tgla(ig)=ptsurf(ig) |
---|
97 | ! temperature at the base (we neglect convection) |
---|
98 | tbase(ig)=tgla(ig)+20.*pqsurf(ig,igcm_n2)/1.e6 ! Umurhan et al. |
---|
99 | if (tbase(ig).gt.63.) then |
---|
100 | slid=1 ! activate slide |
---|
101 | else |
---|
102 | slid=0 |
---|
103 | endif |
---|
104 | |
---|
105 | !************************************* |
---|
106 | ! Selection of the adjacent index depending on the grid point |
---|
107 | !************************************* |
---|
108 | !! poles |
---|
109 | IF (ig.eq.1) then |
---|
110 | cas=0 |
---|
111 | inddeb=2 ! First adj grid point |
---|
112 | indfin=iim+1 ! Last adj grid point |
---|
113 | ELSEIF (ig.eq.ngrid) then |
---|
114 | cas=10 |
---|
115 | inddeb=ngrid-iim |
---|
116 | indfin=ngrid-1 |
---|
117 | !! 9 other cases: edges East, west, or in the center , at edges north south or in the center |
---|
118 | ELSEIF (mod(ig,iim).eq.2) then ! Edge east : N,S,W,E |
---|
119 | IF (ig.eq.2) then |
---|
120 | cas=1 |
---|
121 | edge = (/1, ig+iim,ig-1+iim,ig+1 /) |
---|
122 | ELSEIF (ig.eq.ngrid-iim) then |
---|
123 | cas=3 |
---|
124 | edge = (/ig-iim, ngrid,ig-1+iim,ig+1 /) |
---|
125 | ELSE |
---|
126 | cas=2 |
---|
127 | edge = (/ig-iim, ig+iim,ig-1+iim,ig+1 /) |
---|
128 | ENDIF |
---|
129 | ELSEIF (mod(ig,iim).eq.1) then ! Edge west |
---|
130 | IF (ig.eq.iim+1) then |
---|
131 | cas=7 |
---|
132 | edge = (/1,ig+iim,ig-1,ig+1-iim /) |
---|
133 | ELSEIF (ig.eq.ngrid-1) then |
---|
134 | cas=9 |
---|
135 | edge = (/ig-iim,ngrid,ig-1,ig+1-iim /) |
---|
136 | ELSE |
---|
137 | cas=8 |
---|
138 | edge = (/ig-iim,ig+iim,ig-1,ig+1-iim /) |
---|
139 | ENDIF |
---|
140 | ELSE |
---|
141 | IF ((ig.gt.2).and.(ig.lt.iim+1)) then |
---|
142 | cas=4 |
---|
143 | edge = (/1,ig+iim,ig-1,ig+1 /) |
---|
144 | ELSEIF ((ig.gt.ngrid-iim).and.(ig.lt.ngrid-1)) then |
---|
145 | cas=6 |
---|
146 | edge = (/ig-iim,ngrid,ig-1,ig+1 /) |
---|
147 | ELSE |
---|
148 | cas=5 |
---|
149 | edge = (/ig-iim,ig+iim,ig-1,ig+1 /) |
---|
150 | ENDIF |
---|
151 | ENDIF |
---|
152 | |
---|
153 | masstmp(:)=0. ! mass to be transferred |
---|
154 | totmasstmp=0. ! total mass to be transferred |
---|
155 | H0=phisfi0(ig)/g+pqsurf(ig,igcm_n2)/1000. ! height of ice at ig (m) |
---|
156 | |
---|
157 | !************************************* |
---|
158 | !!!!!!!!!!!!!!!!! POLE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
---|
159 | !************************************* |
---|
160 | IF ((cas.eq.0).or.(cas.eq.10)) then ! Mean over all latitudes near the pole |
---|
161 | |
---|
162 | !call testconservmass2d(ngrid,pqsurf(:,1)) |
---|
163 | !! 1) Compute Diff H0-H1 and mass to be transferred for each adjacent point |
---|
164 | DO i=inddeb,indfin |
---|
165 | diff=H0-(phisfi0(i)/g+pqsurf(i,igcm_n2)/1000.) ! Height difference between ig and adjacent points (m) |
---|
166 | if (diff.gt.difflim) then |
---|
167 | masstmp(i)=massflow(ig,i,tgla(ig),diff,pqsurf(ig,igcm_n2),timstep,slid) ! Mass to be transferred (kg/m2/s) |
---|
168 | else |
---|
169 | masstmp(i)=0. |
---|
170 | endif |
---|
171 | totmasstmp=totmasstmp+masstmp(i) ! mass totale to be transferred if assume only one adjecent point |
---|
172 | ENDDO |
---|
173 | if (totmasstmp.gt.0.) then |
---|
174 | !! 2) Available mass to be transferred |
---|
175 | stock=maxval(masstmp(:))/secu ! kg/m2/s |
---|
176 | !! 3) Real amounts of ice to be transferred : |
---|
177 | masstmp(:)=masstmp(:)/totmasstmp*stock*realarea(ig)/realarea(inddeb) !kg/m2/s all area around the pole are the same |
---|
178 | !! 4) Tendencies |
---|
179 | zdqsurf(ig)=-stock !kg/m2/s |
---|
180 | !! 5) Update PQSURF |
---|
181 | |
---|
182 | ! move CH4 and CO too |
---|
183 | if (methane) then |
---|
184 | !! Variation of CH4 ice |
---|
185 | dqch4=pqsurf(ig,igcm_ch4_ice)*(zdqsurf(ig)/pqsurf(ig,igcm_n2)*timstep) ! amout of ch4 (kg/m2) to be removed at grid ig (negative) |
---|
186 | !! remove CH4 |
---|
187 | pqsurf(ig,igcm_ch4_ice)=pqsurf(ig,igcm_ch4_ice)+dqch4 |
---|
188 | !! add CH4 |
---|
189 | do i=inddeb,indfin |
---|
190 | pqsurf(i,igcm_ch4_ice)=pqsurf(i,igcm_ch4_ice)-masstmp(i)/stock*dqch4 |
---|
191 | enddo |
---|
192 | endif |
---|
193 | if (carbox) then |
---|
194 | !! Variation of CO ice |
---|
195 | dqco=pqsurf(ig,igcm_co_ice)*(zdqsurf(ig)/pqsurf(ig,igcm_n2)*timstep) ! amout of co (kg/m2) to be removed at grid ig (negative) |
---|
196 | !! remove CO |
---|
197 | pqsurf(ig,igcm_co_ice)=pqsurf(ig,igcm_co_ice)+dqco |
---|
198 | !! add CO |
---|
199 | do i=inddeb,indfin |
---|
200 | pqsurf(i,igcm_co_ice)=pqsurf(i,igcm_co_ice)-masstmp(i)/stock*dqco |
---|
201 | enddo |
---|
202 | endif |
---|
203 | |
---|
204 | ! Add N2 |
---|
205 | do i=inddeb,indfin |
---|
206 | pqsurf(i,igcm_n2)=pqsurf(i,igcm_n2)+masstmp(i)*timstep |
---|
207 | enddo |
---|
208 | ! Remove N2 |
---|
209 | pqsurf(ig,igcm_n2)=pqsurf(ig,igcm_n2)+zdqsurf(ig)*timstep |
---|
210 | |
---|
211 | endif |
---|
212 | !call testconservmass2d(ngrid,pqsurf(:,1)) |
---|
213 | |
---|
214 | !!!!!!!!!!!!!!!!!!!! NOT THE POLE !!!!!!!!!!!!!!!!!!!!!!!! |
---|
215 | ! here: ig = grid point with large amount of ice |
---|
216 | ! Loop on each adjacent point |
---|
217 | ! looking for adjacent point |
---|
218 | ELSE |
---|
219 | |
---|
220 | !! 1) Compute Diff H0-H1 and mass to be transferred for each adjacent point |
---|
221 | DO compt=1,4 |
---|
222 | i=edge(compt) |
---|
223 | diff=H0-(phisfi0(i)/g+pqsurf(i,igcm_n2)/1000.) ! (m) |
---|
224 | if (diff.gt.difflim) then |
---|
225 | masstmp(i)=massflow(ig,i,tgla(ig),diff,pqsurf(ig,igcm_n2),timstep,slid) |
---|
226 | else |
---|
227 | masstmp(i)=0. |
---|
228 | endif |
---|
229 | totmasstmp=totmasstmp+masstmp(i) |
---|
230 | ENDDO |
---|
231 | if (totmasstmp.gt.0) then |
---|
232 | !! 2) Available mass to be transferred |
---|
233 | stock=maxval(masstmp(:))/secu ! kg/m2/s |
---|
234 | !! 3) Real amounts of ice to be transferred : |
---|
235 | DO compt=1,4 |
---|
236 | i=edge(compt) |
---|
237 | masstmp(i)=masstmp(i)/totmasstmp*stock*realarea(ig)/realarea(i) !kg/m2/s |
---|
238 | ENDDO |
---|
239 | !! 4) Tendencies |
---|
240 | zdqsurf(ig)=-stock |
---|
241 | !! 5) Update PQSURF |
---|
242 | |
---|
243 | ! move CH4 and CO too |
---|
244 | if (methane) then |
---|
245 | !! Variation of CH4 ice |
---|
246 | dqch4=pqsurf(ig,igcm_ch4_ice)*(zdqsurf(ig)/pqsurf(ig,igcm_n2)*timstep) ! amout of ch4 (kg/m2) to be removed at grid ig (negative) |
---|
247 | !! remove CH4 |
---|
248 | pqsurf(ig,igcm_ch4_ice)=pqsurf(ig,igcm_ch4_ice)+dqch4 |
---|
249 | !! add CH4 |
---|
250 | DO compt=1,4 |
---|
251 | i=edge(compt) |
---|
252 | pqsurf(i,igcm_ch4_ice)=pqsurf(i,igcm_ch4_ice)-masstmp(i)/stock*dqch4 |
---|
253 | enddo |
---|
254 | endif |
---|
255 | if (carbox) then |
---|
256 | !! Variation of CO ice |
---|
257 | dqco=pqsurf(ig,igcm_co_ice)*(zdqsurf(ig)/pqsurf(ig,igcm_n2)*timstep) ! amout of co (kg/m2) to be removed at grid ig (negative) |
---|
258 | !! remove CO |
---|
259 | pqsurf(ig,igcm_co_ice)=pqsurf(ig,igcm_co_ice)+dqco |
---|
260 | !! add CO |
---|
261 | DO compt=1,4 |
---|
262 | i=edge(compt) |
---|
263 | pqsurf(i,igcm_co_ice)=pqsurf(i,igcm_co_ice)-masstmp(i)/stock*dqco |
---|
264 | enddo |
---|
265 | endif |
---|
266 | |
---|
267 | ! Add N2 |
---|
268 | totmasstmp=0. |
---|
269 | DO compt=1,4 |
---|
270 | i=edge(compt) |
---|
271 | pqsurf(i,igcm_n2)=pqsurf(i,igcm_n2)+masstmp(i)*timstep |
---|
272 | totmasstmp=totmasstmp+masstmp(i)*realarea(i) !! TB22 tmp |
---|
273 | enddo |
---|
274 | ! Remove N2 |
---|
275 | pqsurf(ig,igcm_n2)=pqsurf(ig,igcm_n2)+zdqsurf(ig)*timstep |
---|
276 | |
---|
277 | endif |
---|
278 | |
---|
279 | if (pqsurf(ig,igcm_n2).lt.0) then |
---|
280 | print*, pqsurf(ig,igcm_n2) |
---|
281 | write(*,*) 'bug in spreadglacier' |
---|
282 | stop |
---|
283 | endif |
---|
284 | |
---|
285 | ENDIF ! cas |
---|
286 | ENDIF ! qlim |
---|
287 | |
---|
288 | ENDDO ! ig |
---|
289 | |
---|
290 | end subroutine spreadglacier_paleo |
---|
291 | |
---|
292 | real function dist_pluto(lat1,lon1,lat2,lon2) |
---|
293 | implicit none |
---|
294 | #include "comcstfi.h" |
---|
295 | real, intent(in) :: lat1,lon1,lat2,lon2 |
---|
296 | real dlon,dlat |
---|
297 | real a,c |
---|
298 | real radi |
---|
299 | radi=rad/1000. |
---|
300 | |
---|
301 | dlon = lon2 - lon1 |
---|
302 | dlat = lat2 - lat1 |
---|
303 | a = (sin(dlat/2))**2 + cos(lat1) * cos(lat2) * (sin(dlon/2))**2 |
---|
304 | c = 2 * atan2( sqrt(a), sqrt(1-a) ) |
---|
305 | dist_pluto = radi * c !! km |
---|
306 | return |
---|
307 | end function dist_pluto |
---|
308 | |
---|
309 | real function massflow(ig1,ig2,pts,dif,pqs,dt,slid) |
---|
310 | !! Mass of ice to be transferred from one grid point to another |
---|
311 | use comgeomfi_h |
---|
312 | implicit none |
---|
313 | #include "dimensions.h" |
---|
314 | #include "dimphys.h" |
---|
315 | #include "comcstfi.h" |
---|
316 | #include "surfdat.h" |
---|
317 | #include "comvert.h" |
---|
318 | #include "callkeys.h" |
---|
319 | #include "tracer.h" |
---|
320 | real, intent(in) :: pts,dif,pqs,dt |
---|
321 | integer, intent(in) :: ig1,ig2,slid |
---|
322 | real lref,ac,n,theta,hdelta,ha,tau,qdry,qsl,usl0 |
---|
323 | REAL dist_pluto ! function |
---|
324 | |
---|
325 | lref=dist_pluto(lati(ig2),long(ig2),lati(ig1),long(ig1))*1000. ! m |
---|
326 | usl0=6.3e-6 ! m/s |
---|
327 | ac=0.005*exp(9.37-422./pts) !0.005*exp(422./45.-422./pts) |
---|
328 | n=2.1+0.0155*(pts-45.) |
---|
329 | theta=atan(dif/(lref)) |
---|
330 | hdelta=pts/20. |
---|
331 | ha=pts*pts/8440. !pts*pts/20./422. |
---|
332 | qdry=ac*(rho_n2*g*1.e-6)**n*(pqs/1000.)**(n+2)/(n+2)*tan(theta)**(n-1)/(1+tan(theta)*tan(theta))**(n/2.) |
---|
333 | qdry=qdry*0.5*exp( (pqs/1000./ha) / ( 1+ pqs /hdelta) ) |
---|
334 | qsl=(pqs/1000.)/abs(tan(theta))*usl0*slid |
---|
335 | tau=pqs/1000.*lref/abs((qdry+qsl)*tan(theta)) |
---|
336 | massflow=pqs*(1.-exp(-dt/tau))/dt |
---|
337 | return |
---|
338 | end function massflow |
---|
339 | |
---|
340 | |
---|
341 | |
---|
342 | |
---|