1 | module lmdz_blowing_snow_sublim_sedim |
---|
2 | |
---|
3 | contains |
---|
4 | subroutine blowing_snow_sublim_sedim(ngrid,nlay,dtime,temp,qv,qb,pplay,paprs,dtemp_bs,dqv_bs,dqb_bs,bsfl,precip_bs) |
---|
5 | |
---|
6 | !============================================================================== |
---|
7 | ! Routine that calculates the evaporation and sedimentation of blowing snow |
---|
8 | ! inspired by what is done in lscp_mod |
---|
9 | ! Etienne Vignon, October 2022 |
---|
10 | !============================================================================== |
---|
11 | |
---|
12 | |
---|
13 | use lmdz_blowing_snow_ini, only : iflag_sublim_bs, iflag_sedim_bs, coef_sub_bs,RTT,RD,RG,fallv_bs |
---|
14 | use lmdz_blowing_snow_ini, only : qbmin, RCPD, RLSTT, RLMLT, RLVTT, RVTMP2, RV, RPI, tbsmelt, taumeltbs0, rhobs, r_bs |
---|
15 | USE lmdz_lscp_tools, only : calc_qsat_ecmwf |
---|
16 | |
---|
17 | implicit none |
---|
18 | |
---|
19 | |
---|
20 | !++++++++++++++++++++++++++++++++++++++++++++++++++++ |
---|
21 | ! Declarations |
---|
22 | !++++++++++++++++++++++++++++++++++++++++++++++++++++ |
---|
23 | |
---|
24 | !INPUT |
---|
25 | !===== |
---|
26 | |
---|
27 | integer, intent(in) :: ngrid,nlay |
---|
28 | real, intent(in) :: dtime |
---|
29 | real, intent(in), dimension(ngrid,nlay) :: temp |
---|
30 | real, intent(in), dimension(ngrid,nlay) :: qv |
---|
31 | real, intent(in), dimension(ngrid,nlay) :: qb |
---|
32 | real, intent(in), dimension(ngrid,nlay) :: pplay |
---|
33 | real, intent(in), dimension(ngrid,nlay+1) :: paprs |
---|
34 | |
---|
35 | |
---|
36 | |
---|
37 | ! OUTPUT |
---|
38 | !======== |
---|
39 | |
---|
40 | |
---|
41 | real, intent(out), dimension(ngrid,nlay) :: dtemp_bs |
---|
42 | real, intent(out), dimension(ngrid,nlay) :: dqv_bs |
---|
43 | real, intent(out), dimension(ngrid,nlay) :: dqb_bs |
---|
44 | real, intent(out), dimension(ngrid,nlay+1) :: bsfl |
---|
45 | real, intent(out), dimension(ngrid) :: precip_bs |
---|
46 | |
---|
47 | |
---|
48 | ! LOCAL |
---|
49 | !====== |
---|
50 | |
---|
51 | |
---|
52 | integer :: k,i,n |
---|
53 | real :: cpd, cpw, dqbsub, maxdqbsub, dqbmelt, zmair |
---|
54 | real :: dqsedim,precbs, dqvmelt, zmelt, taumeltbs |
---|
55 | real :: maxdqvmelt, rhoair, dz, dqbsedim |
---|
56 | real :: delta_p, b_p, a_p, c_p, c_sub, qvsub |
---|
57 | real :: p0, T0, Dv, Aprime, Bprime, Ka |
---|
58 | real, dimension(ngrid) :: ztemp,zqv,zqb,zpres,qsi,dqsi,qsl,dqsl,qzero,sedim |
---|
59 | real, dimension(ngrid) :: zpaprsup, zpaprsdn, ztemp_up, zqb_up, zvelo |
---|
60 | real, dimension(ngrid,nlay) :: temp_seri, qb_seri, qv_seri |
---|
61 | |
---|
62 | !++++++++++++++++++++++++++++++++++++++++++++++++++ |
---|
63 | ! Initialisation |
---|
64 | !++++++++++++++++++++++++++++++++++++++++++++++++++ |
---|
65 | |
---|
66 | qzero(:)=0. |
---|
67 | dtemp_bs(:,:)=0. |
---|
68 | dqv_bs(:,:)=0. |
---|
69 | dqb_bs(:,:)=0. |
---|
70 | zvelo(:)=0. |
---|
71 | sedim(:)=0. |
---|
72 | precip_bs(:)=0. |
---|
73 | bsfl(:,:)=0. |
---|
74 | |
---|
75 | |
---|
76 | p0=101325.0 ! ref pressure |
---|
77 | |
---|
78 | |
---|
79 | DO k=1,nlay |
---|
80 | DO i=1,ngrid |
---|
81 | temp_seri(i,k)=temp(i,k) |
---|
82 | qv_seri(i,k)=qv(i,k) |
---|
83 | qb_seri(i,k)=qb(i,k) |
---|
84 | ENDDO |
---|
85 | ENDDO |
---|
86 | |
---|
87 | |
---|
88 | ! Sedimentation scheme |
---|
89 | !---------------------- |
---|
90 | |
---|
91 | IF (iflag_sedim_bs .GT. 0) THEN |
---|
92 | ! begin of top-down loop |
---|
93 | DO k = nlay, 1, -1 |
---|
94 | |
---|
95 | DO i=1,ngrid |
---|
96 | ztemp(i)=temp_seri(i,k) |
---|
97 | zqv(i)=qv_seri(i,k) |
---|
98 | zqb(i)=qb_seri(i,k) |
---|
99 | zpres(i)=pplay(i,k) |
---|
100 | zpaprsup(i)=paprs(i,k+1) |
---|
101 | zpaprsdn(i)=paprs(i,k) |
---|
102 | ENDDO |
---|
103 | |
---|
104 | ! thermalization of blowing snow precip coming from above |
---|
105 | IF (k.LE.nlay-1) THEN |
---|
106 | |
---|
107 | DO i = 1, ngrid |
---|
108 | zmair=(zpaprsdn(i)-zpaprsup(i))/RG |
---|
109 | ! RVTMP2=rcpv/rcpd-1 |
---|
110 | cpd=RCPD*(1.0+RVTMP2*zqv(i)) |
---|
111 | cpw=RCPD*RVTMP2 |
---|
112 | ! zqb_up: blowing snow mass that has to be thermalized with |
---|
113 | ! layer's air so that precipitation at the ground has the |
---|
114 | ! same temperature as the lowermost layer |
---|
115 | zqb_up(i) = sedim(i)*dtime/zmair |
---|
116 | ztemp_up(i)=temp_seri(i,k+1) |
---|
117 | |
---|
118 | ! t(i,k+1)+d_t(i,k+1): new temperature of the overlying layer |
---|
119 | ztemp(i) = ( ztemp_up(i)*zqb_up(i)*cpw + cpd*ztemp(i) ) & |
---|
120 | / (cpd + zqb_up(i)*cpw) |
---|
121 | ENDDO |
---|
122 | |
---|
123 | ENDIF |
---|
124 | |
---|
125 | DO i = 1, ngrid |
---|
126 | |
---|
127 | rhoair = zpres(i) / ztemp(i) / RD |
---|
128 | dz = (zpaprsdn(i)-zpaprsup(i)) / (rhoair*RG) |
---|
129 | ! BS fall velocity assumed to be constant for now |
---|
130 | zvelo(i) = fallv_bs |
---|
131 | ! dqb/dt_sedim=1/rho(sedim/dz - rho w qb/dz) |
---|
132 | ! implicit resolution |
---|
133 | dqbsedim = (sedim(i)/rhoair/dz*dtime+zqb(i))/(1.+zvelo(i)*dtime/dz) - zqb(i) |
---|
134 | ! flux and dqb update |
---|
135 | zqb(i)=zqb(i)+dqbsedim |
---|
136 | !sedim(i) = sedim(i)-dqbsedim/dtime*rhoair*dz |
---|
137 | sedim(i)=rhoair*zvelo(i)*zqb(i) |
---|
138 | |
---|
139 | |
---|
140 | ! variables update: |
---|
141 | bsfl(i,k)=sedim(i) |
---|
142 | |
---|
143 | qb_seri(i,k) = zqb(i) |
---|
144 | qv_seri(i,k) = zqv(i) |
---|
145 | temp_seri(i,k) = ztemp(i) |
---|
146 | |
---|
147 | ENDDO ! Loop on ngrid |
---|
148 | |
---|
149 | |
---|
150 | ENDDO ! vertical loop |
---|
151 | |
---|
152 | |
---|
153 | !surface bs flux |
---|
154 | DO i = 1, ngrid |
---|
155 | precip_bs(i) = sedim(i) |
---|
156 | ENDDO |
---|
157 | |
---|
158 | ENDIF |
---|
159 | |
---|
160 | |
---|
161 | |
---|
162 | |
---|
163 | !+++++++++++++++++++++++++++++++++++++++++++++++ |
---|
164 | ! Sublimation and melting |
---|
165 | !++++++++++++++++++++++++++++++++++++++++++++++ |
---|
166 | IF (iflag_sublim_bs .GT. 0) THEN |
---|
167 | |
---|
168 | DO k = 1, nlay |
---|
169 | |
---|
170 | DO i=1,ngrid |
---|
171 | ztemp(i)=temp_seri(i,k) |
---|
172 | zqv(i)=qv_seri(i,k) |
---|
173 | zqb(i)=qb_seri(i,k) |
---|
174 | zpres(i)=pplay(i,k) |
---|
175 | zpaprsup(i)=paprs(i,k+1) |
---|
176 | zpaprsdn(i)=paprs(i,k) |
---|
177 | ENDDO |
---|
178 | |
---|
179 | ! calulation saturation specific humidity |
---|
180 | CALL CALC_QSAT_ECMWF(ngrid,ztemp(:),qzero(:),zpres(:),RTT,2,.false.,qsi(:),dqsi(:)) |
---|
181 | |
---|
182 | |
---|
183 | DO i = 1, ngrid |
---|
184 | |
---|
185 | rhoair = zpres(i) / ztemp(i) / RD |
---|
186 | dz = (zpaprsdn(i)-zpaprsup(i)) / (rhoair*RG) |
---|
187 | ! BS fall velocity assumed to be constant for now |
---|
188 | zvelo(i) = fallv_bs |
---|
189 | |
---|
190 | |
---|
191 | IF (ztemp(i) .GT. RTT) THEN |
---|
192 | |
---|
193 | ! if temperature is positive, we assume that part of the blowing snow |
---|
194 | ! already present melts and evaporates with a typical time |
---|
195 | ! constant taumeltbs |
---|
196 | |
---|
197 | taumeltbs=taumeltbs0*exp(-max(0.,(ztemp(i)-RTT)/(tbsmelt-RTT))) |
---|
198 | dqvmelt=min(zqb(i),-1.*zqb(i)*(exp(-dtime/taumeltbs)-1.)) |
---|
199 | maxdqvmelt= max(RCPD*(1.0+RVTMP2*(zqv(i)+zqb(i)))*(ztemp(i)-RTT)/(RLMLT+RLVTT),0.) |
---|
200 | dqvmelt=min(dqvmelt,maxdqvmelt) |
---|
201 | ! qv update, melting + evaporation |
---|
202 | zqv(i) = zqv(i) + dqvmelt |
---|
203 | ! temp update melting + evaporation |
---|
204 | ztemp(i) = ztemp(i) - dqvmelt * (RLMLT+RLVTT)/RCPD/(1.0+RVTMP2*(zqv(i)+zqb(i))) |
---|
205 | ! qb update melting + evaporation |
---|
206 | zqb(i)=zqb(i)-dqvmelt |
---|
207 | |
---|
208 | ELSE |
---|
209 | ! negative celcius temperature |
---|
210 | ! Sublimation scheme |
---|
211 | |
---|
212 | |
---|
213 | ! Sublimation formulation for ice crystals from Pruppacher & Klett, Rutledge & Hobbs 1983 |
---|
214 | ! assuming monodispered crystal distrib |
---|
215 | ! dqb/dt_sub=-coef_sub_bs*(1-qv/qsi)*nc*8*r_bs/(Aprime+Bprime) |
---|
216 | ! assuming Mi=rhobs*4/3*pi*r_bs**3 |
---|
217 | ! rhoair qb=nc*Mi -> nc=rhoair qb/Mi |
---|
218 | ! dqb/dt_sub=-coef_sub_bs*(1-qv/qsi)*6*rhoair*qb/(rhobs*pi*r_bs**2)/(Aprime+Bprime) |
---|
219 | ! dqb/dt_sub=-c_sub(1-qv/qsi)*qb |
---|
220 | ! c_sub=coef_sub_bs*6*rhoair/(rhobs*pi*r_bs**2)/(Aprime+Bprime) |
---|
221 | ! |
---|
222 | ! Note the strong coupling between specific contents of water vapor and blowing snow during sublimation |
---|
223 | ! equations dqv/dt_sub and dqb/dt_sub must be solved jointly to prevent irrealistic increase of water vapor |
---|
224 | ! at typical physics time steps |
---|
225 | ! we thus solve the differential equation using an implicit scheme for both qb and qv |
---|
226 | |
---|
227 | ! we do not consider deposition, only sublimation |
---|
228 | IF (zqv(i) .LT. qsi(i)) THEN |
---|
229 | rhoair=zpres(i)/ztemp(i)/RD |
---|
230 | Dv=0.0001*0.211*(p0/zpres(i))*((ztemp(i)/RTT)**1.94) ! water vapor diffusivity in air, SI |
---|
231 | Ka=(5.69+0.017*(ztemp(i)-RTT))*1.e-5*100.*4.184 ! thermal conductivity of the air, SI |
---|
232 | Aprime=RLSTT/Ka/ztemp(i)*(RLSTT/RV/ztemp(i) -1.) |
---|
233 | Bprime=1./(rhoair*Dv*qsi(i)) |
---|
234 | c_sub=coef_sub_bs*6.*rhoair/(rhobs*RPI*r_bs**2)/(Aprime+Bprime) |
---|
235 | c_p=-zqb(i) |
---|
236 | b_p=1.+c_sub*dtime-c_sub*dtime/qsi(i)*zqb(i)-c_sub*dtime/qsi(i)*zqv(i) |
---|
237 | a_p=c_sub*dtime/qsi(i) |
---|
238 | delta_p=(b_p**2)-4.*a_p*c_p |
---|
239 | dqbsub=(-b_p+sqrt(delta_p))/(2.*a_p) - zqb(i) |
---|
240 | dqbsub = MIN(0.0,MAX(dqbsub,-zqb(i))) |
---|
241 | ! Sublimation limit: we ensure that the whole mesh does not exceed saturation wrt ice |
---|
242 | maxdqbsub = MAX(0.0, qsi(i)-zqv(i)) |
---|
243 | dqbsub = MAX(dqbsub,-maxdqbsub) |
---|
244 | ELSE |
---|
245 | dqbsub=0. |
---|
246 | ENDIF |
---|
247 | |
---|
248 | ! vapor, temperature, precip fluxes update following sublimation |
---|
249 | zqv(i) = zqv(i) - dqbsub |
---|
250 | zqb(i) = zqb(i) + dqbsub |
---|
251 | ztemp(i) = ztemp(i) + dqbsub*RLSTT/RCPD/(1.0+RVTMP2*(zqv(i)+zqb(i))) |
---|
252 | |
---|
253 | ENDIF |
---|
254 | |
---|
255 | ! if qb<qbmin, sublimate or melt and evaporate qb |
---|
256 | ! see Gerber et al. 2023, JGR Atmos for the choice of qbmin |
---|
257 | |
---|
258 | IF (zqb(i) .LT. qbmin) THEN |
---|
259 | zqv(i) = zqv(i)+zqb(i) |
---|
260 | IF (ztemp(i) .LT. RTT) THEN |
---|
261 | ztemp(i) = ztemp(i) - zqb(i) * RLSTT/RCPD/(1.0+RVTMP2*(zqv(i))) |
---|
262 | ELSE |
---|
263 | ztemp(i) = ztemp(i) - zqb(i) * (RLVTT+RLMLT)/RCPD/(1.0+RVTMP2*(zqv(i))) |
---|
264 | ENDIF |
---|
265 | zqb(i)=0. |
---|
266 | ENDIF |
---|
267 | |
---|
268 | ! variables update |
---|
269 | temp_seri(i,k)=ztemp(i) |
---|
270 | qv_seri(i,k)=zqv(i) |
---|
271 | qb_seri(i,k)=zqb(i) |
---|
272 | ENDDO |
---|
273 | ENDDO |
---|
274 | |
---|
275 | ENDIF |
---|
276 | |
---|
277 | |
---|
278 | ! OUTPUTS |
---|
279 | !++++++++++ |
---|
280 | |
---|
281 | ! 3D variables |
---|
282 | DO k=1,nlay |
---|
283 | DO i=1,ngrid |
---|
284 | dqb_bs(i,k) = qb_seri(i,k) - qb(i,k) |
---|
285 | dqv_bs(i,k) = qv_seri(i,k) - qv(i,k) |
---|
286 | dtemp_bs(i,k) = temp_seri(i,k) - temp(i,k) |
---|
287 | ENDDO |
---|
288 | ENDDO |
---|
289 | |
---|
290 | |
---|
291 | |
---|
292 | return |
---|
293 | |
---|
294 | end subroutine blowing_snow_sublim_sedim |
---|
295 | end module lmdz_blowing_snow_sublim_sedim |
---|