source: LMDZ6/trunk/libf/phylmd/lmdz_blosno_sublimsedim.f90

Last change on this file was 6028, checked in by evignon, 2 months ago

changement de nom des routines et module de neige soufflee par coherence avec
la nomenclature de replayisation
+ passage de deux flags dans lmdz_lscp_ini

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