/[lmdze]/trunk/Sources/phylmd/CV30_routines/cv30_unsat.f
ViewVC logotype

Contents of /trunk/Sources/phylmd/CV30_routines/cv30_unsat.f

Parent Directory Parent Directory | Revision Log Revision Log


Revision 195 - (show annotations)
Wed May 18 17:56:44 2016 UTC (8 years ago) by guez
File size: 11121 byte(s)
In cv30_feed, iflag1 is 0 on entry so we can simplify the test for
iflag1 = 7.

In cv30_feed, for the computation of icb, replaced sequential search
(with a useless end of loop on k) by a call to locate.

In CV30 routines, replaced len, nloc, nd, na by klon or
klev. Philosophy: no more generality than actually necessary.

Converted as many variables as possible to named constants in
cv30_param_m and downgraded pbcrit, ptcrit, dtovsh, dpbase, dttrig,
tau, delta to local objects in procedures. spfac, betad and omtrain
are useless and removed.

Instead of filling the array sigp with the constant spfac in
cv30_undilute2, just made sigp a constant in cv30_unsat.

In cv_driver, define as allocatable variables that are only
used on the range (ncum, nl).

1 module cv30_unsat_m
2
3 implicit none
4
5 contains
6
7 SUBROUTINE cv30_unsat(icb, inb, t, q, qs, gz, u, v, p, ph, th, tv, lv, cpn, &
8 ep, clw, m, ment, elij, delt, plcl, mp, qp, up, vp, wt, water, evap, b)
9
10 ! Unsaturated (precipitating) downdrafts
11
12 use cv30_param_m, only: nl, sigd
13 use cv_thermo_m, only: cpd, ginv, grav
14
15 integer, intent(in):: icb(:) ! (ncum)
16
17 integer, intent(in):: inb(:) ! (ncum)
18 ! first model level above the level of neutral buoyancy of the
19 ! parcel (1 <= inb <= nl - 1)
20
21 real, intent(in):: t(:, :), q(:, :), qs(:, :) ! (ncum, nl)
22 real, intent(in):: gz(:, :) ! (klon, klev)
23 real, intent(in):: u(:, :), v(:, :) ! (klon, klev)
24 real, intent(in):: p(:, :) ! (klon, klev) pressure at full level, in hPa
25 real, intent(in):: ph(:, :) ! (klon, klev + 1)
26 real, intent(in):: th(:, :) ! (ncum, nl - 1)
27 real, intent(in):: tv(:, :) ! (klon, klev)
28 real, intent(in):: lv(:, :) ! (klon, klev)
29 real, intent(in):: cpn(:, :) ! (klon, klev)
30 real, intent(in):: ep(:, :) ! (ncum, klev)
31 real, intent(in):: clw(:, :) ! (ncum, klev)
32 real, intent(in):: m(:, :) ! (ncum, klev)
33 real, intent(in):: ment(:, :, :) ! (ncum, klev, klev)
34 real, intent(in):: elij(:, :, :) ! (ncum, klev, klev)
35 real, intent(in):: delt
36 real, intent(in):: plcl(:) ! (klon)
37
38 real, intent(out):: mp(:, :) ! (klon, klev)
39 real, intent(out):: qp(:, :), up(:, :), vp(:, :) ! (ncum, nl)
40 real, intent(out):: wt(:, :) ! (ncum, nl)
41 real, intent(out):: water(:, :), evap(:, :) ! (ncum, nl)
42 real, intent(out):: b(:, :) ! (ncum, nl - 1)
43
44 ! Local:
45
46 real, parameter:: sigp = 0.15
47 ! fraction of precipitation falling outside of cloud, \sig_s in
48 ! Emanuel (1991 928)
49
50 integer ncum
51 integer i, il, imax
52 real tinv, delti
53 real afac, afac1, afac2, bfac
54 real pr1, pr2, sigt, b6, c6, revap, tevap, delth
55 real amfac, amp2, xf, tf, fac2, ur, sru, fac, d, af, bf
56 real ampmax
57 real lvcp(size(icb), nl) ! (ncum, nl)
58 real wdtrain(size(icb)) ! (ncum)
59 logical lwork(size(icb)) ! (ncum)
60
61 !------------------------------------------------------
62
63 ncum = size(icb)
64 delti = 1. / delt
65 tinv = 1. / 3.
66 mp = 0.
67 b = 0.
68
69 do i = 1, nl
70 do il = 1, ncum
71 qp(il, i) = q(il, i)
72 up(il, i) = u(il, i)
73 vp(il, i) = v(il, i)
74 wt(il, i) = 0.001
75 water(il, i) = 0.
76 evap(il, i) = 0.
77 lvcp(il, i) = lv(il, i) / cpn(il, i)
78 enddo
79 enddo
80
81 ! Check whether ep(inb) = 0. If so, skip precipitating downdraft
82 ! calculation.
83
84 forall (il = 1:ncum) lwork(il) = ep(il, inb(il)) >= 1e-4
85
86 imax = nl - 1
87 do while (.not. any(inb >= imax .and. lwork) .and. imax >= 1)
88 imax = imax - 1
89 end do
90
91 downdraft_loop: DO i = imax, 1, - 1
92 ! Integrate liquid water equation to find condensed water
93 ! and condensed water flux
94
95 ! Calculate detrained precipitation
96 forall (il = 1:ncum, inb(il) >= i .and. lwork(il)) wdtrain(il) = grav &
97 * (ep(il, i) * m(il, i) * clw(il, i) &
98 + sum(max(elij(il, :i - 1, i) - (1. - ep(il, i)) * clw(il, i), 0.) &
99 * ment(il, :i - 1, i)))
100
101 ! Find rain water and evaporation using provisional
102 ! estimates of qp(i) and qp(i - 1)
103
104 loop_horizontal: do il = 1, ncum
105 if (i <= inb(il) .and. lwork(il)) then
106 wt(il, i) = 45.
107
108 if (i < inb(il)) then
109 qp(il, i) = qp(il, i + 1) + (cpd * (t(il, i + 1) - t(il, i)) &
110 + gz(il, i + 1) - gz(il, i)) / lv(il, i)
111 qp(il, i) = 0.5 * (qp(il, i) + q(il, i))
112 endif
113
114 qp(il, i) = max(qp(il, i), 0.)
115 qp(il, i) = min(qp(il, i), qs(il, i))
116 qp(il, inb(il)) = q(il, inb(il))
117
118 if (i == 1) then
119 afac = p(il, 1) * (qs(il, 1) - qp(il, 1)) &
120 / (1e4 + 2000. * p(il, 1) * qs(il, 1))
121 else
122 qp(il, i - 1) = qp(il, i) + (cpd * (t(il, i) - t(il, i - 1)) &
123 + gz(il, i) - gz(il, i - 1)) / lv(il, i)
124 qp(il, i - 1) = 0.5 * (qp(il, i - 1) + q(il, i - 1))
125 qp(il, i - 1) = min(qp(il, i - 1), qs(il, i - 1))
126 qp(il, i - 1) = max(qp(il, i - 1), 0.)
127 afac1 = p(il, i) * (qs(il, i) - qp(il, i)) &
128 / (1e4 + 2000. * p(il, i) * qs(il, i))
129 afac2 = p(il, i - 1) * (qs(il, i - 1) - qp(il, i - 1)) &
130 / (1e4 + 2000. * p(il, i - 1) * qs(il, i - 1))
131 afac = 0.5 * (afac1 + afac2)
132 endif
133
134 if (i == inb(il)) afac = 0.
135 afac = max(afac, 0.)
136 bfac = 1. / (sigd * wt(il, i))
137
138 ! Prise en compte de la variation progressive de sigt dans
139 ! les couches icb et icb - 1:
140 ! pour plcl <= ph(i + 1), pr1 = 0 et pr2 = 1
141 ! pour plcl >= ph(i), pr1 = 1 et pr2 = 0
142 ! pour ph(i + 1) < plcl < ph(i), pr1 est la proportion \`a cheval
143 ! sur le nuage, et pr2 est la proportion sous la base du
144 ! nuage.
145 pr1 = max(0., min(1., &
146 (plcl(il) - ph(il, i + 1)) / (ph(il, i) - ph(il, i + 1))))
147 pr2 = max(0., min(1., &
148 (ph(il, i) - plcl(il)) / (ph(il, i) - ph(il, i + 1))))
149 sigt = sigp * pr1 + pr2
150
151 b6 = bfac * 50. * sigd * (ph(il, i) - ph(il, i + 1)) * sigt * afac
152 c6 = water(il, i + 1) + bfac * wdtrain(il) - 50. * sigd * bfac &
153 * (ph(il, i) - ph(il, i + 1)) * evap(il, i + 1)
154
155 if (c6 > 0.) then
156 revap = 0.5 * (- b6 + sqrt(b6 * b6 + 4. * c6))
157 evap(il, i) = sigt * afac * revap
158 water(il, i) = revap * revap
159 else
160 evap(il, i) = - evap(il, i + 1) + 0.02 * (wdtrain(il) + sigd &
161 * wt(il, i) * water(il, i + 1)) / (sigd * (ph(il, i) &
162 - ph(il, i + 1)))
163 end if
164
165 ! Calculate precipitating downdraft mass flux under
166 ! hydrostatic approximation
167
168 test_above_surface: if (i /= 1) then
169 tevap = max(0., evap(il, i))
170 delth = max(0.001, (th(il, i) - th(il, i - 1)))
171 mp(il, i) = 100. * ginv * lvcp(il, i) * sigd * tevap &
172 * (p(il, i - 1) - p(il, i)) / delth
173
174 ! If hydrostatic assumption fails, solve cubic
175 ! difference equation for downdraft theta and mass
176 ! flux from two simultaneous differential equations
177
178 amfac = sigd * sigd * 70. * ph(il, i) &
179 * (p(il, i - 1) - p(il, i)) &
180 * (th(il, i) - th(il, i - 1)) / (tv(il, i) * th(il, i))
181 amp2 = abs(mp(il, i + 1) * mp(il, i + 1) - mp(il, i) &
182 * mp(il, i))
183
184 if (amp2 > 0.1 * amfac) then
185 xf = 100. * sigd * sigd * sigd * (ph(il, i) - ph(il, i + 1))
186 tf = b(il, i) - 5. * (th(il, i) - th(il, i - 1)) &
187 * t(il, i) / (lvcp(il, i) * sigd * th(il, i))
188 af = xf * tf + mp(il, i + 1) * mp(il, i + 1) * tinv
189 bf = 2. * (tinv * mp(il, i + 1))**3 + tinv &
190 * mp(il, i + 1) * xf * tf + 50. * (p(il, i - 1) &
191 - p(il, i)) * xf * tevap
192 fac2 = 1.
193 if (bf < 0.) fac2 = - 1.
194 bf = abs(bf)
195 ur = 0.25 * bf * bf - af * af * af * tinv * tinv * tinv
196
197 if (ur >= 0.) then
198 sru = sqrt(ur)
199 fac = 1.
200 if ((0.5 * bf - sru) < 0.) fac = - 1.
201 mp(il, i) = mp(il, i + 1) * tinv + (0.5 * bf &
202 + sru)**tinv + fac * (abs(0.5 * bf - sru))**tinv
203 else
204 d = atan(2. * sqrt(- ur) / (bf + 1e-28))
205 if (fac2 < 0.)d = 3.14159 - d
206 mp(il, i) = mp(il, i + 1) * tinv + 2. * sqrt(af * tinv) &
207 * cos(d * tinv)
208 endif
209
210 mp(il, i) = max(0., mp(il, i))
211
212 ! Il y a vraisemblablement une erreur dans la
213 ! ligne suivante : il faut diviser par (mp(il,
214 ! i) * sigd * grav) et non par (mp(il, i) + sigd
215 ! * 0.1). Et il faut bien revoir les facteurs
216 ! 100.
217 b(il, i - 1) = b(il, i) + 100. * (p(il, i - 1) - p(il, i)) &
218 * tevap / (mp(il, i) + sigd * 0.1) - 10. * (th(il, i) &
219 - th(il, i - 1)) * t(il, i) / (lvcp(il, i) * sigd &
220 * th(il, i))
221 b(il, i - 1) = max(b(il, i - 1), 0.)
222 endif
223
224 ! Limit magnitude of mp(i) to meet CFL condition:
225 ampmax = 2. * (ph(il, i) - ph(il, i + 1)) * delti
226 amp2 = 2. * (ph(il, i - 1) - ph(il, i)) * delti
227 ampmax = min(ampmax, amp2)
228 mp(il, i) = min(mp(il, i), ampmax)
229
230 ! Force mp to decrease linearly to zero between cloud
231 ! base and the surface:
232 if (p(il, i) > p(il, icb(il))) mp(il, i) = mp(il, icb(il)) &
233 * (p(il, 1) - p(il, i)) / (p(il, 1) - p(il, icb(il)))
234 endif test_above_surface
235
236 ! Find mixing ratio of precipitating downdraft
237
238 if (i /= inb(il)) then
239 qp(il, i) = q(il, i)
240
241 if (mp(il, i) > mp(il, i + 1)) then
242 qp(il, i) = qp(il, i + 1) * mp(il, i + 1) + q(il, i) &
243 * (mp(il, i) - mp(il, i + 1)) + 100. * ginv * 0.5 &
244 * sigd * (ph(il, i) - ph(il, i + 1)) &
245 * (evap(il, i + 1) + evap(il, i))
246 qp(il, i) = qp(il, i) / mp(il, i)
247 up(il, i) = up(il, i + 1) * mp(il, i + 1) + u(il, i) &
248 * (mp(il, i) - mp(il, i + 1))
249 up(il, i) = up(il, i) / mp(il, i)
250 vp(il, i) = vp(il, i + 1) * mp(il, i + 1) + v(il, i) &
251 * (mp(il, i) - mp(il, i + 1))
252 vp(il, i) = vp(il, i) / mp(il, i)
253 else
254 if (mp(il, i + 1) > 1e-16) then
255 qp(il, i) = qp(il, i + 1) + 100. * ginv * 0.5 * sigd &
256 * (ph(il, i) - ph(il, i + 1)) * (evap(il, i + 1) &
257 + evap(il, i)) / mp(il, i + 1)
258 up(il, i) = up(il, i + 1)
259 vp(il, i) = vp(il, i + 1)
260 endif
261 endif
262
263 qp(il, i) = min(qp(il, i), qs(il, i))
264 qp(il, i) = max(qp(il, i), 0.)
265 endif
266 endif
267 end do loop_horizontal
268 end DO downdraft_loop
269
270 end SUBROUTINE cv30_unsat
271
272 end module cv30_unsat_m

  ViewVC Help
Powered by ViewVC 1.1.21