1 | #define WRF_PORT |
---|
2 | |
---|
3 | module module_cu_camzm |
---|
4 | |
---|
5 | !Based on zm_conv.F90 from CAM |
---|
6 | |
---|
7 | !--------------------------------------------------------------------------------- |
---|
8 | ! Purpose: |
---|
9 | ! |
---|
10 | ! Interface from Zhang-McFarlane convection scheme, includes evaporation of convective |
---|
11 | ! precip from the ZM scheme |
---|
12 | ! |
---|
13 | ! Apr 2006: RBN: Code added to perform a dilute ascent for closure of the CM mass flux |
---|
14 | ! based on an entraining plume a la Raymond and Blythe (1992) |
---|
15 | ! |
---|
16 | ! Author: Byron Boville, from code in tphysbc |
---|
17 | ! Ported from CAM to WRF by William.Gustafson@pnl.gov, Nov. 2009 |
---|
18 | ! updated to CESM1_0_1, Nov. 2010 |
---|
19 | ! |
---|
20 | !--------------------------------------------------------------------------------- |
---|
21 | |
---|
22 | use shr_kind_mod, only: r8 => shr_kind_r8 |
---|
23 | use cldwat, only: cldwat_fice |
---|
24 | use physconst, only: cpair, epsilo, gravit, latice, latvap, tmelt, rair, & |
---|
25 | cpwv, cpliq, rh2o |
---|
26 | #ifndef WRF_PORT |
---|
27 | use spmd_utils, only: masterproc |
---|
28 | use ppgrid, only: pcols, pver, pverp |
---|
29 | |
---|
30 | use abortutils, only: endrun |
---|
31 | use cam_logfile, only: iulog |
---|
32 | |
---|
33 | #else |
---|
34 | use module_cam_support, only: masterproc, & |
---|
35 | pcols, pver, pverp, & |
---|
36 | endrun, & |
---|
37 | iulog |
---|
38 | use module_wrf_error |
---|
39 | #endif |
---|
40 | |
---|
41 | implicit none |
---|
42 | |
---|
43 | save |
---|
44 | private ! Make default type private to the module |
---|
45 | ! |
---|
46 | ! PUBLIC: interfaces |
---|
47 | ! |
---|
48 | public zmconv_readnl ! read zmconv_nl namelist |
---|
49 | public zm_convi ! ZM schemea |
---|
50 | public zm_convr ! ZM schemea |
---|
51 | public zm_conv_evap ! evaporation of precip from ZM schemea |
---|
52 | public convtran ! convective transport |
---|
53 | public momtran ! convective momentum transport |
---|
54 | |
---|
55 | ! |
---|
56 | ! Private data |
---|
57 | ! |
---|
58 | real(r8), parameter :: unset_r8 = huge(1.0_r8) |
---|
59 | real(r8) :: zmconv_c0_lnd = unset_r8 |
---|
60 | real(r8) :: zmconv_c0_ocn = unset_r8 |
---|
61 | real(r8) :: zmconv_ke = unset_r8 |
---|
62 | real(r8) rl ! wg latent heat of vaporization. |
---|
63 | real(r8) cpres ! specific heat at constant pressure in j/kg-degk. |
---|
64 | real(r8), parameter :: capelmt = 70._r8 ! threshold value for cape for deep convection. |
---|
65 | real(r8) :: ke ! Tunable evaporation efficiency set from namelist input zmconv_ke |
---|
66 | real(r8) :: c0_lnd ! set from namelist input zmconv_c0_lnd |
---|
67 | real(r8) :: c0_ocn ! set from namelist input zmconv_c0_ocn |
---|
68 | real(r8) tau ! convective time scale |
---|
69 | real(r8),parameter :: a = 21.656_r8 |
---|
70 | real(r8),parameter :: b = 5418._r8 |
---|
71 | real(r8),parameter :: c1 = 6.112_r8 |
---|
72 | real(r8),parameter :: c2 = 17.67_r8 |
---|
73 | real(r8),parameter :: c3 = 243.5_r8 |
---|
74 | real(r8) :: tfreez |
---|
75 | real(r8) :: eps1 |
---|
76 | |
---|
77 | |
---|
78 | logical :: no_deep_pbl ! default = .false. |
---|
79 | ! no_deep_pbl = .true. eliminates deep convection entirely within PBL |
---|
80 | |
---|
81 | |
---|
82 | !moved from moistconvection.F90 |
---|
83 | real(r8) :: rgrav ! reciprocal of grav |
---|
84 | real(r8) :: rgas ! gas constant for dry air |
---|
85 | real(r8) :: grav ! = gravit |
---|
86 | real(r8) :: cp ! = cpres = cpair |
---|
87 | |
---|
88 | integer limcnv ! top interface level limit for convection |
---|
89 | real(r8),parameter :: tiedke_add = 0.5_r8 |
---|
90 | contains |
---|
91 | |
---|
92 | subroutine zmconv_readnl(nlfile) |
---|
93 | #ifndef WRF_PORT |
---|
94 | use namelist_utils, only: find_group_name |
---|
95 | use units, only: getunit, freeunit |
---|
96 | use mpishorthand |
---|
97 | #endif |
---|
98 | |
---|
99 | character(len=*), intent(in) :: nlfile ! filepath for file containing namelist input |
---|
100 | |
---|
101 | #ifndef WRF_PORT |
---|
102 | ! Local variables |
---|
103 | integer :: unitn, ierr |
---|
104 | character(len=*), parameter :: subname = 'zmconv_readnl' |
---|
105 | |
---|
106 | namelist /zmconv_nl/ zmconv_c0_lnd, zmconv_c0_ocn, zmconv_ke |
---|
107 | !----------------------------------------------------------------------------- |
---|
108 | |
---|
109 | if (masterproc) then |
---|
110 | unitn = getunit() |
---|
111 | open( unitn, file=trim(nlfile), status='old' ) |
---|
112 | call find_group_name(unitn, 'zmconv_nl', status=ierr) |
---|
113 | if (ierr == 0) then |
---|
114 | read(unitn, zmconv_nl, iostat=ierr) |
---|
115 | if (ierr /= 0) then |
---|
116 | call endrun(subname // ':: ERROR reading namelist') |
---|
117 | end if |
---|
118 | end if |
---|
119 | close(unitn) |
---|
120 | call freeunit(unitn) |
---|
121 | |
---|
122 | ! set local variables |
---|
123 | c0_lnd = zmconv_c0_lnd |
---|
124 | c0_ocn = zmconv_c0_ocn |
---|
125 | ke = zmconv_ke |
---|
126 | |
---|
127 | end if |
---|
128 | |
---|
129 | #ifdef SPMD |
---|
130 | ! Broadcast namelist variables |
---|
131 | call mpibcast(c0_lnd, 1, mpir8, 0, mpicom) |
---|
132 | call mpibcast(c0_ocn, 1, mpir8, 0, mpicom) |
---|
133 | call mpibcast(ke, 1, mpir8, 0, mpicom) |
---|
134 | #endif |
---|
135 | |
---|
136 | #else |
---|
137 | ! WRF_PORT currently uses hard-wired values for the namelist input. The |
---|
138 | ! values could easily be setup to come from the Registry in the future. |
---|
139 | ! The hard-wired values are the defaults for the fv core. They should be |
---|
140 | ! verified by somebody knowledgable on the matter. |
---|
141 | c0_lnd = 0.0035d0 |
---|
142 | c0_ocn = 0.0035d0 |
---|
143 | ke = 1.0e-6 |
---|
144 | #endif |
---|
145 | |
---|
146 | end subroutine zmconv_readnl |
---|
147 | |
---|
148 | |
---|
149 | subroutine zm_convi(limcnv_in, no_deep_pbl_in) |
---|
150 | |
---|
151 | #ifndef WRF_PORT |
---|
152 | use dycore, only: dycore_is, get_resolution |
---|
153 | #endif |
---|
154 | |
---|
155 | integer, intent(in) :: limcnv_in ! top interface level limit for convection |
---|
156 | logical, intent(in), optional :: no_deep_pbl_in ! no_deep_pbl = .true. eliminates ZM convection entirely within PBL |
---|
157 | |
---|
158 | ! local variables |
---|
159 | character(len=32) :: hgrid ! horizontal grid specifier |
---|
160 | |
---|
161 | ! Initialization of ZM constants |
---|
162 | limcnv = limcnv_in |
---|
163 | tfreez = tmelt |
---|
164 | eps1 = epsilo |
---|
165 | rl = latvap |
---|
166 | cpres = cpair |
---|
167 | rgrav = 1.0_r8/gravit |
---|
168 | rgas = rair |
---|
169 | grav = gravit |
---|
170 | cp = cpres |
---|
171 | |
---|
172 | if ( present(no_deep_pbl_in) ) then |
---|
173 | no_deep_pbl = no_deep_pbl_in |
---|
174 | else |
---|
175 | no_deep_pbl = .false. |
---|
176 | endif |
---|
177 | |
---|
178 | ! tau=4800. were used in canadian climate center. however, in echam3 t42, |
---|
179 | ! convection is too weak, thus adjusted to 2400. |
---|
180 | |
---|
181 | #ifndef WRF_PORT |
---|
182 | hgrid = get_resolution() |
---|
183 | #endif |
---|
184 | tau = 3600._r8 |
---|
185 | |
---|
186 | if ( masterproc ) then |
---|
187 | write(iulog,*) 'tuning parameters zm_convi: tau',tau |
---|
188 | #ifdef WRF_PORT |
---|
189 | call wrf_debug(100,iulog) |
---|
190 | #endif |
---|
191 | write(iulog,*) 'tuning parameters zm_convi: c0_lnd',c0_lnd, ', c0_ocn', c0_ocn |
---|
192 | #ifdef WRF_PORT |
---|
193 | call wrf_debug(100,iulog) |
---|
194 | #endif |
---|
195 | write(iulog,*) 'tuning parameters zm_convi: ke',ke |
---|
196 | #ifdef WRF_PORT |
---|
197 | call wrf_debug(100,iulog) |
---|
198 | #endif |
---|
199 | write(iulog,*) 'tuning parameters zm_convi: no_deep_pbl',no_deep_pbl |
---|
200 | #ifdef WRF_PORT |
---|
201 | call wrf_debug(100,iulog) |
---|
202 | endif |
---|
203 | #endif |
---|
204 | |
---|
205 | if (masterproc) then |
---|
206 | write(iulog,*)'**** ZM: DILUTE Buoyancy Calculation ****' |
---|
207 | #ifdef WRF_PORT |
---|
208 | call wrf_debug(100,iulog) |
---|
209 | #endif |
---|
210 | end if |
---|
211 | |
---|
212 | end subroutine zm_convi |
---|
213 | |
---|
214 | |
---|
215 | |
---|
216 | subroutine zm_convr(lchnk ,ncol , & |
---|
217 | t ,qh ,prec ,jctop ,jcbot , & |
---|
218 | pblh ,zm ,geos ,zi ,qtnd , & |
---|
219 | heat ,pap ,paph ,dpp , & |
---|
220 | delt ,mcon ,cme ,cape , & |
---|
221 | tpert ,dlf ,pflx ,zdu ,rprd , & |
---|
222 | mu ,md ,du ,eu ,ed , & |
---|
223 | dp ,dsubcld ,jt ,maxg ,ideep , & |
---|
224 | lengath ,ql ,rliq ,landfrac) |
---|
225 | !----------------------------------------------------------------------- |
---|
226 | ! |
---|
227 | ! Purpose: |
---|
228 | ! Main driver for zhang-mcfarlane convection scheme |
---|
229 | ! |
---|
230 | ! Method: |
---|
231 | ! performs deep convective adjustment based on mass-flux closure |
---|
232 | ! algorithm. |
---|
233 | ! |
---|
234 | ! Author:guang jun zhang, m.lazare, n.mcfarlane. CAM Contact: P. Rasch |
---|
235 | ! |
---|
236 | ! This is contributed code not fully standardized by the CAM core group. |
---|
237 | ! All variables have been typed, where most are identified in comments |
---|
238 | ! The current procedure will be reimplemented in a subsequent version |
---|
239 | ! of the CAM where it will include a more straightforward formulation |
---|
240 | ! and will make use of the standard CAM nomenclature |
---|
241 | ! |
---|
242 | !----------------------------------------------------------------------- |
---|
243 | #ifdef WRF_PORT |
---|
244 | use module_cam_support, only: pcnst |
---|
245 | #else |
---|
246 | use constituents, only: pcnst |
---|
247 | #endif |
---|
248 | |
---|
249 | ! |
---|
250 | ! ************************ index of variables ********************** |
---|
251 | ! |
---|
252 | ! wg * alpha array of vertical differencing used (=1. for upstream). |
---|
253 | ! w * cape convective available potential energy. |
---|
254 | ! wg * capeg gathered convective available potential energy. |
---|
255 | ! c * capelmt threshold value for cape for deep convection. |
---|
256 | ! ic * cpres specific heat at constant pressure in j/kg-degk. |
---|
257 | ! i * dpp |
---|
258 | ! ic * delt length of model time-step in seconds. |
---|
259 | ! wg * dp layer thickness in mbs (between upper/lower interface). |
---|
260 | ! wg * dqdt mixing ratio tendency at gathered points. |
---|
261 | ! wg * dsdt dry static energy ("temp") tendency at gathered points. |
---|
262 | ! wg * dudt u-wind tendency at gathered points. |
---|
263 | ! wg * dvdt v-wind tendency at gathered points. |
---|
264 | ! wg * dsubcld layer thickness in mbs between lcl and maxi. |
---|
265 | ! ic * grav acceleration due to gravity in m/sec2. |
---|
266 | ! wg * du detrainment in updraft. specified in mid-layer |
---|
267 | ! wg * ed entrainment in downdraft. |
---|
268 | ! wg * eu entrainment in updraft. |
---|
269 | ! wg * hmn moist static energy. |
---|
270 | ! wg * hsat saturated moist static energy. |
---|
271 | ! w * ideep holds position of gathered points vs longitude index. |
---|
272 | ! ic * pver number of model levels. |
---|
273 | ! wg * j0 detrainment initiation level index. |
---|
274 | ! wg * jd downdraft initiation level index. |
---|
275 | ! ic * jlatpr gaussian latitude index for printing grids (if needed). |
---|
276 | ! wg * jt top level index of deep cumulus convection. |
---|
277 | ! w * lcl base level index of deep cumulus convection. |
---|
278 | ! wg * lclg gathered values of lcl. |
---|
279 | ! w * lel index of highest theoretical convective plume. |
---|
280 | ! wg * lelg gathered values of lel. |
---|
281 | ! w * lon index of onset level for deep convection. |
---|
282 | ! w * maxi index of level with largest moist static energy. |
---|
283 | ! wg * maxg gathered values of maxi. |
---|
284 | ! wg * mb cloud base mass flux. |
---|
285 | ! wg * mc net upward (scaled by mb) cloud mass flux. |
---|
286 | ! wg * md downward cloud mass flux (positive up). |
---|
287 | ! wg * mu upward cloud mass flux (positive up). specified |
---|
288 | ! at interface |
---|
289 | ! ic * msg number of missing moisture levels at the top of model. |
---|
290 | ! w * p grid slice of ambient mid-layer pressure in mbs. |
---|
291 | ! i * pblt row of pbl top indices. |
---|
292 | ! w * pcpdh scaled surface pressure. |
---|
293 | ! w * pf grid slice of ambient interface pressure in mbs. |
---|
294 | ! wg * pg grid slice of gathered values of p. |
---|
295 | ! w * q grid slice of mixing ratio. |
---|
296 | ! wg * qd grid slice of mixing ratio in downdraft. |
---|
297 | ! wg * qg grid slice of gathered values of q. |
---|
298 | ! i/o * qh grid slice of specific humidity. |
---|
299 | ! w * qh0 grid slice of initial specific humidity. |
---|
300 | ! wg * qhat grid slice of upper interface mixing ratio. |
---|
301 | ! wg * ql grid slice of cloud liquid water. |
---|
302 | ! wg * qs grid slice of saturation mixing ratio. |
---|
303 | ! w * qstp grid slice of parcel temp. saturation mixing ratio. |
---|
304 | ! wg * qstpg grid slice of gathered values of qstp. |
---|
305 | ! wg * qu grid slice of mixing ratio in updraft. |
---|
306 | ! ic * rgas dry air gas constant. |
---|
307 | ! wg * rl latent heat of vaporization. |
---|
308 | ! w * s grid slice of scaled dry static energy (t+gz/cp). |
---|
309 | ! wg * sd grid slice of dry static energy in downdraft. |
---|
310 | ! wg * sg grid slice of gathered values of s. |
---|
311 | ! wg * shat grid slice of upper interface dry static energy. |
---|
312 | ! wg * su grid slice of dry static energy in updraft. |
---|
313 | ! i/o * t |
---|
314 | ! o * jctop row of top-of-deep-convection indices passed out. |
---|
315 | ! O * jcbot row of base of cloud indices passed out. |
---|
316 | ! wg * tg grid slice of gathered values of t. |
---|
317 | ! w * tl row of parcel temperature at lcl. |
---|
318 | ! wg * tlg grid slice of gathered values of tl. |
---|
319 | ! w * tp grid slice of parcel temperatures. |
---|
320 | ! wg * tpg grid slice of gathered values of tp. |
---|
321 | ! i/o * u grid slice of u-wind (real). |
---|
322 | ! wg * ug grid slice of gathered values of u. |
---|
323 | ! i/o * utg grid slice of u-wind tendency (real). |
---|
324 | ! i/o * v grid slice of v-wind (real). |
---|
325 | ! w * va work array re-used by called subroutines. |
---|
326 | ! wg * vg grid slice of gathered values of v. |
---|
327 | ! i/o * vtg grid slice of v-wind tendency (real). |
---|
328 | ! i * w grid slice of diagnosed large-scale vertical velocity. |
---|
329 | ! w * z grid slice of ambient mid-layer height in metres. |
---|
330 | ! w * zf grid slice of ambient interface height in metres. |
---|
331 | ! wg * zfg grid slice of gathered values of zf. |
---|
332 | ! wg * zg grid slice of gathered values of z. |
---|
333 | ! |
---|
334 | !----------------------------------------------------------------------- |
---|
335 | ! |
---|
336 | ! multi-level i/o fields: |
---|
337 | ! i => input arrays. |
---|
338 | ! i/o => input/output arrays. |
---|
339 | ! w => work arrays. |
---|
340 | ! wg => work arrays operating only on gathered points. |
---|
341 | ! ic => input data constants. |
---|
342 | ! c => data constants pertaining to subroutine itself. |
---|
343 | ! |
---|
344 | ! input arguments |
---|
345 | ! |
---|
346 | integer, intent(in) :: lchnk ! chunk identifier |
---|
347 | integer, intent(in) :: ncol ! number of atmospheric columns |
---|
348 | |
---|
349 | real(r8), intent(in) :: t(pcols,pver) ! grid slice of temperature at mid-layer. |
---|
350 | real(r8), intent(in) :: qh(pcols,pver,pcnst) ! grid slice of specific humidity. |
---|
351 | real(r8), intent(in) :: pap(pcols,pver) |
---|
352 | real(r8), intent(in) :: paph(pcols,pver+1) |
---|
353 | real(r8), intent(in) :: dpp(pcols,pver) ! local sigma half-level thickness (i.e. dshj). |
---|
354 | real(r8), intent(in) :: zm(pcols,pver) |
---|
355 | real(r8), intent(in) :: geos(pcols) |
---|
356 | real(r8), intent(in) :: zi(pcols,pver+1) |
---|
357 | real(r8), intent(in) :: pblh(pcols) |
---|
358 | real(r8), intent(in) :: tpert(pcols) |
---|
359 | real(r8), intent(in) :: landfrac(pcols) ! RBN Landfrac |
---|
360 | ! |
---|
361 | ! output arguments |
---|
362 | ! |
---|
363 | real(r8), intent(out) :: qtnd(pcols,pver) ! specific humidity tendency (kg/kg/s) |
---|
364 | real(r8), intent(out) :: heat(pcols,pver) ! heating rate (dry static energy tendency, W/kg) |
---|
365 | real(r8), intent(out) :: mcon(pcols,pverp) |
---|
366 | real(r8), intent(out) :: dlf(pcols,pver) ! scattrd version of the detraining cld h2o tend |
---|
367 | real(r8), intent(out) :: pflx(pcols,pverp) ! scattered precip flux at each level |
---|
368 | real(r8), intent(out) :: cme(pcols,pver) |
---|
369 | real(r8), intent(out) :: cape(pcols) ! w convective available potential energy. |
---|
370 | real(r8), intent(out) :: zdu(pcols,pver) |
---|
371 | real(r8), intent(out) :: rprd(pcols,pver) ! rain production rate |
---|
372 | ! move these vars from local storage to output so that convective |
---|
373 | ! transports can be done in outside of conv_cam. |
---|
374 | real(r8), intent(out) :: mu(pcols,pver) |
---|
375 | real(r8), intent(out) :: eu(pcols,pver) |
---|
376 | real(r8), intent(out) :: du(pcols,pver) |
---|
377 | real(r8), intent(out) :: md(pcols,pver) |
---|
378 | real(r8), intent(out) :: ed(pcols,pver) |
---|
379 | real(r8), intent(out) :: dp(pcols,pver) ! wg layer thickness in mbs (between upper/lower interface). |
---|
380 | real(r8), intent(out) :: dsubcld(pcols) ! wg layer thickness in mbs between lcl and maxi. |
---|
381 | real(r8), intent(out) :: jctop(pcols) ! o row of top-of-deep-convection indices passed out. |
---|
382 | real(r8), intent(out) :: jcbot(pcols) ! o row of base of cloud indices passed out. |
---|
383 | real(r8), intent(out) :: prec(pcols) |
---|
384 | real(r8), intent(out) :: rliq(pcols) ! reserved liquid (not yet in cldliq) for energy integrals |
---|
385 | |
---|
386 | real(r8) zs(pcols) |
---|
387 | real(r8) dlg(pcols,pver) ! gathrd version of the detraining cld h2o tend |
---|
388 | real(r8) pflxg(pcols,pverp) ! gather precip flux at each level |
---|
389 | real(r8) cug(pcols,pver) ! gathered condensation rate |
---|
390 | real(r8) evpg(pcols,pver) ! gathered evap rate of rain in downdraft |
---|
391 | real(r8) mumax(pcols) |
---|
392 | integer jt(pcols) ! wg top level index of deep cumulus convection. |
---|
393 | integer maxg(pcols) ! wg gathered values of maxi. |
---|
394 | integer ideep(pcols) ! w holds position of gathered points vs longitude index. |
---|
395 | integer lengath |
---|
396 | ! diagnostic field used by chem/wetdep codes |
---|
397 | real(r8) ql(pcols,pver) ! wg grid slice of cloud liquid water. |
---|
398 | ! |
---|
399 | real(r8) pblt(pcols) ! i row of pbl top indices. |
---|
400 | |
---|
401 | ! |
---|
402 | !----------------------------------------------------------------------- |
---|
403 | ! |
---|
404 | ! general work fields (local variables): |
---|
405 | ! |
---|
406 | real(r8) q(pcols,pver) ! w grid slice of mixing ratio. |
---|
407 | real(r8) p(pcols,pver) ! w grid slice of ambient mid-layer pressure in mbs. |
---|
408 | real(r8) z(pcols,pver) ! w grid slice of ambient mid-layer height in metres. |
---|
409 | real(r8) s(pcols,pver) ! w grid slice of scaled dry static energy (t+gz/cp). |
---|
410 | real(r8) tp(pcols,pver) ! w grid slice of parcel temperatures. |
---|
411 | real(r8) zf(pcols,pver+1) ! w grid slice of ambient interface height in metres. |
---|
412 | real(r8) pf(pcols,pver+1) ! w grid slice of ambient interface pressure in mbs. |
---|
413 | real(r8) qstp(pcols,pver) ! w grid slice of parcel temp. saturation mixing ratio. |
---|
414 | |
---|
415 | real(r8) tl(pcols) ! w row of parcel temperature at lcl. |
---|
416 | |
---|
417 | integer lcl(pcols) ! w base level index of deep cumulus convection. |
---|
418 | integer lel(pcols) ! w index of highest theoretical convective plume. |
---|
419 | integer lon(pcols) ! w index of onset level for deep convection. |
---|
420 | integer maxi(pcols) ! w index of level with largest moist static energy. |
---|
421 | integer index(pcols) |
---|
422 | real(r8) precip |
---|
423 | ! |
---|
424 | ! gathered work fields: |
---|
425 | ! |
---|
426 | real(r8) qg(pcols,pver) ! wg grid slice of gathered values of q. |
---|
427 | real(r8) tg(pcols,pver) ! w grid slice of temperature at interface. |
---|
428 | real(r8) pg(pcols,pver) ! wg grid slice of gathered values of p. |
---|
429 | real(r8) zg(pcols,pver) ! wg grid slice of gathered values of z. |
---|
430 | real(r8) sg(pcols,pver) ! wg grid slice of gathered values of s. |
---|
431 | real(r8) tpg(pcols,pver) ! wg grid slice of gathered values of tp. |
---|
432 | real(r8) zfg(pcols,pver+1) ! wg grid slice of gathered values of zf. |
---|
433 | real(r8) qstpg(pcols,pver) ! wg grid slice of gathered values of qstp. |
---|
434 | real(r8) ug(pcols,pver) ! wg grid slice of gathered values of u. |
---|
435 | real(r8) vg(pcols,pver) ! wg grid slice of gathered values of v. |
---|
436 | real(r8) cmeg(pcols,pver) |
---|
437 | |
---|
438 | real(r8) rprdg(pcols,pver) ! wg gathered rain production rate |
---|
439 | real(r8) capeg(pcols) ! wg gathered convective available potential energy. |
---|
440 | real(r8) tlg(pcols) ! wg grid slice of gathered values of tl. |
---|
441 | real(r8) landfracg(pcols) ! wg grid slice of landfrac |
---|
442 | |
---|
443 | integer lclg(pcols) ! wg gathered values of lcl. |
---|
444 | integer lelg(pcols) |
---|
445 | ! |
---|
446 | ! work fields arising from gathered calculations. |
---|
447 | ! |
---|
448 | real(r8) dqdt(pcols,pver) ! wg mixing ratio tendency at gathered points. |
---|
449 | real(r8) dsdt(pcols,pver) ! wg dry static energy ("temp") tendency at gathered points. |
---|
450 | ! real(r8) alpha(pcols,pver) ! array of vertical differencing used (=1. for upstream). |
---|
451 | real(r8) sd(pcols,pver) ! wg grid slice of dry static energy in downdraft. |
---|
452 | real(r8) qd(pcols,pver) ! wg grid slice of mixing ratio in downdraft. |
---|
453 | real(r8) mc(pcols,pver) ! wg net upward (scaled by mb) cloud mass flux. |
---|
454 | real(r8) qhat(pcols,pver) ! wg grid slice of upper interface mixing ratio. |
---|
455 | real(r8) qu(pcols,pver) ! wg grid slice of mixing ratio in updraft. |
---|
456 | real(r8) su(pcols,pver) ! wg grid slice of dry static energy in updraft. |
---|
457 | real(r8) qs(pcols,pver) ! wg grid slice of saturation mixing ratio. |
---|
458 | real(r8) shat(pcols,pver) ! wg grid slice of upper interface dry static energy. |
---|
459 | real(r8) hmn(pcols,pver) ! wg moist static energy. |
---|
460 | real(r8) hsat(pcols,pver) ! wg saturated moist static energy. |
---|
461 | real(r8) qlg(pcols,pver) |
---|
462 | real(r8) dudt(pcols,pver) ! wg u-wind tendency at gathered points. |
---|
463 | real(r8) dvdt(pcols,pver) ! wg v-wind tendency at gathered points. |
---|
464 | ! real(r8) ud(pcols,pver) |
---|
465 | ! real(r8) vd(pcols,pver) |
---|
466 | |
---|
467 | real(r8) mb(pcols) ! wg cloud base mass flux. |
---|
468 | |
---|
469 | integer jlcl(pcols) |
---|
470 | integer j0(pcols) ! wg detrainment initiation level index. |
---|
471 | integer jd(pcols) ! wg downdraft initiation level index. |
---|
472 | |
---|
473 | real(r8) delt ! length of model time-step in seconds. |
---|
474 | |
---|
475 | integer i |
---|
476 | integer ii |
---|
477 | integer k |
---|
478 | integer msg ! ic number of missing moisture levels at the top of model. |
---|
479 | real(r8) qdifr |
---|
480 | real(r8) sdifr |
---|
481 | ! |
---|
482 | !--------------------------Data statements------------------------------ |
---|
483 | ! |
---|
484 | ! Set internal variable "msg" (convection limit) to "limcnv-1" |
---|
485 | ! |
---|
486 | msg = limcnv - 1 |
---|
487 | ! |
---|
488 | ! initialize necessary arrays. |
---|
489 | ! zero out variables not used in cam |
---|
490 | ! |
---|
491 | qtnd(:,:) = 0._r8 |
---|
492 | heat(:,:) = 0._r8 |
---|
493 | mcon(:,:) = 0._r8 |
---|
494 | rliq(:ncol) = 0._r8 |
---|
495 | ! |
---|
496 | ! initialize convective tendencies |
---|
497 | ! |
---|
498 | prec(:ncol) = 0._r8 |
---|
499 | do k = 1,pver |
---|
500 | do i = 1,ncol |
---|
501 | dqdt(i,k) = 0._r8 |
---|
502 | dsdt(i,k) = 0._r8 |
---|
503 | dudt(i,k) = 0._r8 |
---|
504 | dvdt(i,k) = 0._r8 |
---|
505 | pflx(i,k) = 0._r8 |
---|
506 | pflxg(i,k) = 0._r8 |
---|
507 | cme(i,k) = 0._r8 |
---|
508 | rprd(i,k) = 0._r8 |
---|
509 | zdu(i,k) = 0._r8 |
---|
510 | ql(i,k) = 0._r8 |
---|
511 | qlg(i,k) = 0._r8 |
---|
512 | dlf(i,k) = 0._r8 |
---|
513 | dlg(i,k) = 0._r8 |
---|
514 | end do |
---|
515 | end do |
---|
516 | do i = 1,ncol |
---|
517 | pflx(i,pverp) = 0 |
---|
518 | pflxg(i,pverp) = 0 |
---|
519 | end do |
---|
520 | ! |
---|
521 | do i = 1,ncol |
---|
522 | pblt(i) = pver |
---|
523 | dsubcld(i) = 0._r8 |
---|
524 | |
---|
525 | jctop(i) = pver |
---|
526 | jcbot(i) = 1 |
---|
527 | end do |
---|
528 | ! |
---|
529 | ! calculate local pressure (mbs) and height (m) for both interface |
---|
530 | ! and mid-layer locations. |
---|
531 | ! |
---|
532 | do i = 1,ncol |
---|
533 | zs(i) = geos(i)*rgrav |
---|
534 | pf(i,pver+1) = paph(i,pver+1)*0.01_r8 |
---|
535 | zf(i,pver+1) = zi(i,pver+1) + zs(i) |
---|
536 | end do |
---|
537 | do k = 1,pver |
---|
538 | do i = 1,ncol |
---|
539 | p(i,k) = pap(i,k)*0.01_r8 |
---|
540 | pf(i,k) = paph(i,k)*0.01_r8 |
---|
541 | z(i,k) = zm(i,k) + zs(i) |
---|
542 | zf(i,k) = zi(i,k) + zs(i) |
---|
543 | end do |
---|
544 | end do |
---|
545 | ! |
---|
546 | do k = pver - 1,msg + 1,-1 |
---|
547 | do i = 1,ncol |
---|
548 | if (abs(z(i,k)-zs(i)-pblh(i)) < (zf(i,k)-zf(i,k+1))*0.5_r8) pblt(i) = k |
---|
549 | end do |
---|
550 | end do |
---|
551 | ! |
---|
552 | ! store incoming specific humidity field for subsequent calculation |
---|
553 | ! of precipitation (through change in storage). |
---|
554 | ! define dry static energy (normalized by cp). |
---|
555 | ! |
---|
556 | do k = 1,pver |
---|
557 | do i = 1,ncol |
---|
558 | q(i,k) = qh(i,k,1) |
---|
559 | s(i,k) = t(i,k) + (grav/cpres)*z(i,k) |
---|
560 | tp(i,k)=0.0_r8 |
---|
561 | shat(i,k) = s(i,k) |
---|
562 | qhat(i,k) = q(i,k) |
---|
563 | end do |
---|
564 | end do |
---|
565 | |
---|
566 | do i = 1,ncol |
---|
567 | capeg(i) = 0._r8 |
---|
568 | lclg(i) = 1 |
---|
569 | lelg(i) = pver |
---|
570 | maxg(i) = 1 |
---|
571 | tlg(i) = 400._r8 |
---|
572 | dsubcld(i) = 0._r8 |
---|
573 | end do |
---|
574 | |
---|
575 | ! Evaluate Tparcel, qsat(Tparcel), buoyancy and CAPE, |
---|
576 | ! lcl, lel, parcel launch level at index maxi()=hmax |
---|
577 | |
---|
578 | call buoyan_dilute(lchnk ,ncol , & |
---|
579 | q ,t ,p ,z ,pf , & |
---|
580 | tp ,qstp ,tl ,rl ,cape , & |
---|
581 | pblt ,lcl ,lel ,lon ,maxi , & |
---|
582 | rgas ,grav ,cpres ,msg , & |
---|
583 | tpert ) |
---|
584 | |
---|
585 | ! |
---|
586 | ! determine whether grid points will undergo some deep convection |
---|
587 | ! (ideep=1) or not (ideep=0), based on values of cape,lcl,lel |
---|
588 | ! (require cape.gt. 0 and lel<lcl as minimum conditions). |
---|
589 | ! |
---|
590 | lengath = 0 |
---|
591 | do i=1,ncol |
---|
592 | if (cape(i) > capelmt) then |
---|
593 | lengath = lengath + 1 |
---|
594 | index(lengath) = i |
---|
595 | end if |
---|
596 | end do |
---|
597 | |
---|
598 | if (lengath.eq.0) return |
---|
599 | do ii=1,lengath |
---|
600 | i=index(ii) |
---|
601 | ideep(ii)=i |
---|
602 | end do |
---|
603 | ! |
---|
604 | ! obtain gathered arrays necessary for ensuing calculations. |
---|
605 | ! |
---|
606 | do k = 1,pver |
---|
607 | do i = 1,lengath |
---|
608 | dp(i,k) = 0.01_r8*dpp(ideep(i),k) |
---|
609 | qg(i,k) = q(ideep(i),k) |
---|
610 | tg(i,k) = t(ideep(i),k) |
---|
611 | pg(i,k) = p(ideep(i),k) |
---|
612 | zg(i,k) = z(ideep(i),k) |
---|
613 | sg(i,k) = s(ideep(i),k) |
---|
614 | tpg(i,k) = tp(ideep(i),k) |
---|
615 | zfg(i,k) = zf(ideep(i),k) |
---|
616 | qstpg(i,k) = qstp(ideep(i),k) |
---|
617 | ug(i,k) = 0._r8 |
---|
618 | vg(i,k) = 0._r8 |
---|
619 | end do |
---|
620 | end do |
---|
621 | ! |
---|
622 | do i = 1,lengath |
---|
623 | zfg(i,pver+1) = zf(ideep(i),pver+1) |
---|
624 | end do |
---|
625 | do i = 1,lengath |
---|
626 | capeg(i) = cape(ideep(i)) |
---|
627 | lclg(i) = lcl(ideep(i)) |
---|
628 | lelg(i) = lel(ideep(i)) |
---|
629 | maxg(i) = maxi(ideep(i)) |
---|
630 | tlg(i) = tl(ideep(i)) |
---|
631 | landfracg(i) = landfrac(ideep(i)) |
---|
632 | end do |
---|
633 | ! |
---|
634 | ! calculate sub-cloud layer pressure "thickness" for use in |
---|
635 | ! closure and tendency routines. |
---|
636 | ! |
---|
637 | do k = msg + 1,pver |
---|
638 | do i = 1,lengath |
---|
639 | if (k >= maxg(i)) then |
---|
640 | dsubcld(i) = dsubcld(i) + dp(i,k) |
---|
641 | end if |
---|
642 | end do |
---|
643 | end do |
---|
644 | ! |
---|
645 | ! define array of factors (alpha) which defines interfacial |
---|
646 | ! values, as well as interfacial values for (q,s) used in |
---|
647 | ! subsequent routines. |
---|
648 | ! |
---|
649 | do k = msg + 2,pver |
---|
650 | do i = 1,lengath |
---|
651 | ! alpha(i,k) = 0.5 |
---|
652 | sdifr = 0._r8 |
---|
653 | qdifr = 0._r8 |
---|
654 | if (sg(i,k) > 0._r8 .or. sg(i,k-1) > 0._r8) & |
---|
655 | sdifr = abs((sg(i,k)-sg(i,k-1))/max(sg(i,k-1),sg(i,k))) |
---|
656 | if (qg(i,k) > 0._r8 .or. qg(i,k-1) > 0._r8) & |
---|
657 | qdifr = abs((qg(i,k)-qg(i,k-1))/max(qg(i,k-1),qg(i,k))) |
---|
658 | if (sdifr > 1.E-6_r8) then |
---|
659 | shat(i,k) = log(sg(i,k-1)/sg(i,k))*sg(i,k-1)*sg(i,k)/(sg(i,k-1)-sg(i,k)) |
---|
660 | else |
---|
661 | shat(i,k) = 0.5_r8* (sg(i,k)+sg(i,k-1)) |
---|
662 | end if |
---|
663 | if (qdifr > 1.E-6_r8) then |
---|
664 | qhat(i,k) = log(qg(i,k-1)/qg(i,k))*qg(i,k-1)*qg(i,k)/(qg(i,k-1)-qg(i,k)) |
---|
665 | else |
---|
666 | qhat(i,k) = 0.5_r8* (qg(i,k)+qg(i,k-1)) |
---|
667 | end if |
---|
668 | end do |
---|
669 | end do |
---|
670 | ! |
---|
671 | ! obtain cloud properties. |
---|
672 | ! |
---|
673 | |
---|
674 | call cldprp(lchnk , & |
---|
675 | qg ,tg ,ug ,vg ,pg , & |
---|
676 | zg ,sg ,mu ,eu ,du , & |
---|
677 | md ,ed ,sd ,qd ,mc , & |
---|
678 | qu ,su ,zfg ,qs ,hmn , & |
---|
679 | hsat ,shat ,qlg , & |
---|
680 | cmeg ,maxg ,lelg ,jt ,jlcl , & |
---|
681 | maxg ,j0 ,jd ,rl ,lengath , & |
---|
682 | rgas ,grav ,cpres ,msg , & |
---|
683 | pflxg ,evpg ,cug ,rprdg ,limcnv ,landfracg) |
---|
684 | ! |
---|
685 | ! convert detrainment from units of "1/m" to "1/mb". |
---|
686 | ! |
---|
687 | do k = msg + 1,pver |
---|
688 | do i = 1,lengath |
---|
689 | du (i,k) = du (i,k)* (zfg(i,k)-zfg(i,k+1))/dp(i,k) |
---|
690 | eu (i,k) = eu (i,k)* (zfg(i,k)-zfg(i,k+1))/dp(i,k) |
---|
691 | ed (i,k) = ed (i,k)* (zfg(i,k)-zfg(i,k+1))/dp(i,k) |
---|
692 | cug (i,k) = cug (i,k)* (zfg(i,k)-zfg(i,k+1))/dp(i,k) |
---|
693 | cmeg (i,k) = cmeg (i,k)* (zfg(i,k)-zfg(i,k+1))/dp(i,k) |
---|
694 | rprdg(i,k) = rprdg(i,k)* (zfg(i,k)-zfg(i,k+1))/dp(i,k) |
---|
695 | evpg (i,k) = evpg (i,k)* (zfg(i,k)-zfg(i,k+1))/dp(i,k) |
---|
696 | end do |
---|
697 | end do |
---|
698 | |
---|
699 | call closure(lchnk , & |
---|
700 | qg ,tg ,pg ,zg ,sg , & |
---|
701 | tpg ,qs ,qu ,su ,mc , & |
---|
702 | du ,mu ,md ,qd ,sd , & |
---|
703 | qhat ,shat ,dp ,qstpg ,zfg , & |
---|
704 | qlg ,dsubcld ,mb ,capeg ,tlg , & |
---|
705 | lclg ,lelg ,jt ,maxg ,1 , & |
---|
706 | lengath ,rgas ,grav ,cpres ,rl , & |
---|
707 | msg ,capelmt ) |
---|
708 | ! |
---|
709 | ! limit cloud base mass flux to theoretical upper bound. |
---|
710 | ! |
---|
711 | do i=1,lengath |
---|
712 | mumax(i) = 0 |
---|
713 | end do |
---|
714 | do k=msg + 2,pver |
---|
715 | do i=1,lengath |
---|
716 | mumax(i) = max(mumax(i), mu(i,k)/dp(i,k)) |
---|
717 | end do |
---|
718 | end do |
---|
719 | |
---|
720 | do i=1,lengath |
---|
721 | if (mumax(i) > 0._r8) then |
---|
722 | mb(i) = min(mb(i),0.5_r8/(delt*mumax(i))) |
---|
723 | else |
---|
724 | mb(i) = 0._r8 |
---|
725 | endif |
---|
726 | end do |
---|
727 | ! If no_deep_pbl = .true., don't allow convection entirely |
---|
728 | ! within PBL (suggestion of Bjorn Stevens, 8-2000) |
---|
729 | |
---|
730 | if (no_deep_pbl) then |
---|
731 | do i=1,lengath |
---|
732 | if (zm(ideep(i),jt(i)) < pblh(ideep(i))) mb(i) = 0 |
---|
733 | end do |
---|
734 | end if |
---|
735 | |
---|
736 | |
---|
737 | do k=msg+1,pver |
---|
738 | do i=1,lengath |
---|
739 | mu (i,k) = mu (i,k)*mb(i) |
---|
740 | md (i,k) = md (i,k)*mb(i) |
---|
741 | mc (i,k) = mc (i,k)*mb(i) |
---|
742 | du (i,k) = du (i,k)*mb(i) |
---|
743 | eu (i,k) = eu (i,k)*mb(i) |
---|
744 | ed (i,k) = ed (i,k)*mb(i) |
---|
745 | cmeg (i,k) = cmeg (i,k)*mb(i) |
---|
746 | rprdg(i,k) = rprdg(i,k)*mb(i) |
---|
747 | cug (i,k) = cug (i,k)*mb(i) |
---|
748 | evpg (i,k) = evpg (i,k)*mb(i) |
---|
749 | pflxg(i,k+1)= pflxg(i,k+1)*mb(i)*100._r8/grav |
---|
750 | end do |
---|
751 | end do |
---|
752 | ! |
---|
753 | ! compute temperature and moisture changes due to convection. |
---|
754 | ! |
---|
755 | call q1q2_pjr(lchnk , & |
---|
756 | dqdt ,dsdt ,qg ,qs ,qu , & |
---|
757 | su ,du ,qhat ,shat ,dp , & |
---|
758 | mu ,md ,sd ,qd ,qlg , & |
---|
759 | dsubcld ,jt ,maxg ,1 ,lengath , & |
---|
760 | cpres ,rl ,msg , & |
---|
761 | dlg ,evpg ,cug ) |
---|
762 | ! |
---|
763 | ! gather back temperature and mixing ratio. |
---|
764 | ! |
---|
765 | do k = msg + 1,pver |
---|
766 | !DIR$ CONCURRENT |
---|
767 | do i = 1,lengath |
---|
768 | ! |
---|
769 | ! q is updated to compute net precip. |
---|
770 | ! |
---|
771 | q(ideep(i),k) = qh(ideep(i),k,1) + 2._r8*delt*dqdt(i,k) |
---|
772 | qtnd(ideep(i),k) = dqdt (i,k) |
---|
773 | cme (ideep(i),k) = cmeg (i,k) |
---|
774 | rprd(ideep(i),k) = rprdg(i,k) |
---|
775 | zdu (ideep(i),k) = du (i,k) |
---|
776 | mcon(ideep(i),k) = mc (i,k) |
---|
777 | heat(ideep(i),k) = dsdt (i,k)*cpres |
---|
778 | dlf (ideep(i),k) = dlg (i,k) |
---|
779 | pflx(ideep(i),k) = pflxg(i,k) |
---|
780 | ql (ideep(i),k) = qlg (i,k) |
---|
781 | end do |
---|
782 | end do |
---|
783 | ! |
---|
784 | !DIR$ CONCURRENT |
---|
785 | do i = 1,lengath |
---|
786 | jctop(ideep(i)) = jt(i) |
---|
787 | !++bee |
---|
788 | jcbot(ideep(i)) = maxg(i) |
---|
789 | !--bee |
---|
790 | pflx(ideep(i),pverp) = pflxg(i,pverp) |
---|
791 | end do |
---|
792 | |
---|
793 | ! Compute precip by integrating change in water vapor minus detrained cloud water |
---|
794 | do k = pver,msg + 1,-1 |
---|
795 | do i = 1,ncol |
---|
796 | prec(i) = prec(i) - dpp(i,k)* (q(i,k)-qh(i,k,1)) - dpp(i,k)*dlf(i,k)*2*delt |
---|
797 | end do |
---|
798 | end do |
---|
799 | |
---|
800 | ! obtain final precipitation rate in m/s. |
---|
801 | do i = 1,ncol |
---|
802 | prec(i) = rgrav*max(prec(i),0._r8)/ (2._r8*delt)/1000._r8 |
---|
803 | end do |
---|
804 | |
---|
805 | ! Compute reserved liquid (not yet in cldliq) for energy integrals. |
---|
806 | ! Treat rliq as flux out bottom, to be added back later. |
---|
807 | do k = 1, pver |
---|
808 | do i = 1, ncol |
---|
809 | rliq(i) = rliq(i) + dlf(i,k)*dpp(i,k)/gravit |
---|
810 | end do |
---|
811 | end do |
---|
812 | rliq(:ncol) = rliq(:ncol) /1000._r8 |
---|
813 | |
---|
814 | return |
---|
815 | end subroutine zm_convr |
---|
816 | |
---|
817 | !=============================================================================== |
---|
818 | subroutine zm_conv_evap(ncol,lchnk, & |
---|
819 | t,pmid,pdel,q, & |
---|
820 | tend_s, tend_s_snwprd, tend_s_snwevmlt, tend_q, & |
---|
821 | prdprec, cldfrc, deltat, & |
---|
822 | prec, snow, ntprprd, ntsnprd, flxprec, flxsnow ) |
---|
823 | |
---|
824 | !----------------------------------------------------------------------- |
---|
825 | ! Compute tendencies due to evaporation of rain from ZM scheme |
---|
826 | !-- |
---|
827 | ! Compute the total precipitation and snow fluxes at the surface. |
---|
828 | ! Add in the latent heat of fusion for snow formation and melt, since it not dealt with |
---|
829 | ! in the Zhang-MacFarlane parameterization. |
---|
830 | ! Evaporate some of the precip directly into the environment using a Sundqvist type algorithm |
---|
831 | !----------------------------------------------------------------------- |
---|
832 | |
---|
833 | use wv_saturation, only: aqsat |
---|
834 | #ifndef WRF_PORT |
---|
835 | use phys_grid, only: get_rlat_all_p |
---|
836 | #endif |
---|
837 | |
---|
838 | !------------------------------Arguments-------------------------------- |
---|
839 | integer,intent(in) :: ncol, lchnk ! number of columns and chunk index |
---|
840 | real(r8),intent(in), dimension(pcols,pver) :: t ! temperature (K) |
---|
841 | real(r8),intent(in), dimension(pcols,pver) :: pmid ! midpoint pressure (Pa) |
---|
842 | real(r8),intent(in), dimension(pcols,pver) :: pdel ! layer thickness (Pa) |
---|
843 | real(r8),intent(in), dimension(pcols,pver) :: q ! water vapor (kg/kg) |
---|
844 | real(r8),intent(inout), dimension(pcols,pver) :: tend_s ! heating rate (J/kg/s) |
---|
845 | real(r8),intent(inout), dimension(pcols,pver) :: tend_q ! water vapor tendency (kg/kg/s) |
---|
846 | real(r8),intent(out ), dimension(pcols,pver) :: tend_s_snwprd ! Heating rate of snow production |
---|
847 | real(r8),intent(out ), dimension(pcols,pver) :: tend_s_snwevmlt ! Heating rate of evap/melting of snow |
---|
848 | |
---|
849 | |
---|
850 | |
---|
851 | real(r8), intent(in ) :: prdprec(pcols,pver)! precipitation production (kg/ks/s) |
---|
852 | real(r8), intent(in ) :: cldfrc(pcols,pver) ! cloud fraction |
---|
853 | real(r8), intent(in ) :: deltat ! time step |
---|
854 | |
---|
855 | real(r8), intent(inout) :: prec(pcols) ! Convective-scale preciptn rate |
---|
856 | real(r8), intent(out) :: snow(pcols) ! Convective-scale snowfall rate |
---|
857 | ! |
---|
858 | !---------------------------Local storage------------------------------- |
---|
859 | |
---|
860 | real(r8) :: est (pcols,pver) ! Saturation vapor pressure |
---|
861 | real(r8) :: fice (pcols,pver) ! ice fraction in precip production |
---|
862 | real(r8) :: fsnow_conv(pcols,pver) ! snow fraction in precip production |
---|
863 | real(r8) :: qsat (pcols,pver) ! saturation specific humidity |
---|
864 | real(r8),intent(out) :: flxprec(pcols,pverp) ! Convective-scale flux of precip at interfaces (kg/m2/s) |
---|
865 | real(r8),intent(out) :: flxsnow(pcols,pverp) ! Convective-scale flux of snow at interfaces (kg/m2/s) |
---|
866 | real(r8),intent(out) :: ntprprd(pcols,pver) ! net precip production in layer |
---|
867 | real(r8),intent(out) :: ntsnprd(pcols,pver) ! net snow production in layer |
---|
868 | real(r8) :: work1 ! temp variable (pjr) |
---|
869 | real(r8) :: work2 ! temp variable (pjr) |
---|
870 | |
---|
871 | real(r8) :: evpvint(pcols) ! vertical integral of evaporation |
---|
872 | real(r8) :: evpprec(pcols) ! evaporation of precipitation (kg/kg/s) |
---|
873 | real(r8) :: evpsnow(pcols) ! evaporation of snowfall (kg/kg/s) |
---|
874 | real(r8) :: snowmlt(pcols) ! snow melt tendency in layer |
---|
875 | real(r8) :: flxsntm(pcols) ! flux of snow into layer, after melting |
---|
876 | |
---|
877 | real(r8) :: evplimit ! temp variable for evaporation limits |
---|
878 | real(r8) :: rlat(pcols) |
---|
879 | |
---|
880 | integer :: i,k ! longitude,level indices |
---|
881 | |
---|
882 | |
---|
883 | !----------------------------------------------------------------------- |
---|
884 | |
---|
885 | ! convert input precip to kg/m2/s |
---|
886 | prec(:ncol) = prec(:ncol)*1000._r8 |
---|
887 | |
---|
888 | ! determine saturation vapor pressure |
---|
889 | call aqsat (t ,pmid ,est ,qsat ,pcols , & |
---|
890 | ncol ,pver ,1 ,pver ) |
---|
891 | |
---|
892 | ! determine ice fraction in rain production (use cloud water parameterization fraction at present) |
---|
893 | call cldwat_fice(ncol, t, fice, fsnow_conv) |
---|
894 | |
---|
895 | ! zero the flux integrals on the top boundary |
---|
896 | flxprec(:ncol,1) = 0._r8 |
---|
897 | flxsnow(:ncol,1) = 0._r8 |
---|
898 | evpvint(:ncol) = 0._r8 |
---|
899 | |
---|
900 | do k = 1, pver |
---|
901 | do i = 1, ncol |
---|
902 | |
---|
903 | ! Melt snow falling into layer, if necessary. |
---|
904 | if (t(i,k) > tmelt) then |
---|
905 | flxsntm(i) = 0._r8 |
---|
906 | snowmlt(i) = flxsnow(i,k) * gravit/ pdel(i,k) |
---|
907 | else |
---|
908 | flxsntm(i) = flxsnow(i,k) |
---|
909 | snowmlt(i) = 0._r8 |
---|
910 | end if |
---|
911 | |
---|
912 | ! relative humidity depression must be > 0 for evaporation |
---|
913 | evplimit = max(1._r8 - q(i,k)/qsat(i,k), 0._r8) |
---|
914 | |
---|
915 | ! total evaporation depends on flux in the top of the layer |
---|
916 | ! flux prec is the net production above layer minus evaporation into environmet |
---|
917 | evpprec(i) = ke * (1._r8 - cldfrc(i,k)) * evplimit * sqrt(flxprec(i,k)) |
---|
918 | !********************************************************** |
---|
919 | !! evpprec(i) = 0. ! turn off evaporation for now |
---|
920 | !********************************************************** |
---|
921 | |
---|
922 | ! Don't let evaporation supersaturate layer (approx). Layer may already be saturated. |
---|
923 | ! Currently does not include heating/cooling change to qsat |
---|
924 | evplimit = max(0._r8, (qsat(i,k)-q(i,k)) / deltat) |
---|
925 | |
---|
926 | ! Don't evaporate more than is falling into the layer - do not evaporate rain formed |
---|
927 | ! in this layer but if precip production is negative, remove from the available precip |
---|
928 | ! Negative precip production occurs because of evaporation in downdrafts. |
---|
929 | !!$ evplimit = flxprec(i,k) * gravit / pdel(i,k) + min(prdprec(i,k), 0.) |
---|
930 | evplimit = min(evplimit, flxprec(i,k) * gravit / pdel(i,k)) |
---|
931 | |
---|
932 | ! Total evaporation cannot exceed input precipitation |
---|
933 | evplimit = min(evplimit, (prec(i) - evpvint(i)) * gravit / pdel(i,k)) |
---|
934 | |
---|
935 | evpprec(i) = min(evplimit, evpprec(i)) |
---|
936 | |
---|
937 | ! evaporation of snow depends on snow fraction of total precipitation in the top after melting |
---|
938 | if (flxprec(i,k) > 0._r8) then |
---|
939 | ! evpsnow(i) = evpprec(i) * flxsntm(i) / flxprec(i,k) |
---|
940 | ! prevent roundoff problems |
---|
941 | work1 = min(max(0._r8,flxsntm(i)/flxprec(i,k)),1._r8) |
---|
942 | evpsnow(i) = evpprec(i) * work1 |
---|
943 | else |
---|
944 | evpsnow(i) = 0._r8 |
---|
945 | end if |
---|
946 | |
---|
947 | ! vertically integrated evaporation |
---|
948 | evpvint(i) = evpvint(i) + evpprec(i) * pdel(i,k)/gravit |
---|
949 | |
---|
950 | ! net precip production is production - evaporation |
---|
951 | ntprprd(i,k) = prdprec(i,k) - evpprec(i) |
---|
952 | ! net snow production is precip production * ice fraction - evaporation - melting |
---|
953 | !pjrworks ntsnprd(i,k) = prdprec(i,k)*fice(i,k) - evpsnow(i) - snowmlt(i) |
---|
954 | !pjrwrks2 ntsnprd(i,k) = prdprec(i,k)*fsnow_conv(i,k) - evpsnow(i) - snowmlt(i) |
---|
955 | ! the small amount added to flxprec in the work1 expression has been increased from |
---|
956 | ! 1e-36 to 8.64e-11 (1e-5 mm/day). This causes the temperature based partitioning |
---|
957 | ! scheme to be used for small flxprec amounts. This is to address error growth problems. |
---|
958 | #ifdef PERGRO |
---|
959 | work1 = min(max(0._r8,flxsnow(i,k)/(flxprec(i,k)+8.64e-11_r8)),1._r8) |
---|
960 | #else |
---|
961 | if (flxprec(i,k).gt.0._r8) then |
---|
962 | work1 = min(max(0._r8,flxsnow(i,k)/flxprec(i,k)),1._r8) |
---|
963 | else |
---|
964 | work1 = 0._r8 |
---|
965 | endif |
---|
966 | #endif |
---|
967 | work2 = max(fsnow_conv(i,k), work1) |
---|
968 | if (snowmlt(i).gt.0._r8) work2 = 0._r8 |
---|
969 | ! work2 = fsnow_conv(i,k) |
---|
970 | ntsnprd(i,k) = prdprec(i,k)*work2 - evpsnow(i) - snowmlt(i) |
---|
971 | tend_s_snwprd (i,k) = prdprec(i,k)*work2*latice |
---|
972 | tend_s_snwevmlt(i,k) = - ( evpsnow(i) + snowmlt(i) )*latice |
---|
973 | |
---|
974 | ! precipitation fluxes |
---|
975 | flxprec(i,k+1) = flxprec(i,k) + ntprprd(i,k) * pdel(i,k)/gravit |
---|
976 | flxsnow(i,k+1) = flxsnow(i,k) + ntsnprd(i,k) * pdel(i,k)/gravit |
---|
977 | |
---|
978 | ! protect against rounding error |
---|
979 | flxprec(i,k+1) = max(flxprec(i,k+1), 0._r8) |
---|
980 | flxsnow(i,k+1) = max(flxsnow(i,k+1), 0._r8) |
---|
981 | ! more protection (pjr) |
---|
982 | ! flxsnow(i,k+1) = min(flxsnow(i,k+1), flxprec(i,k+1)) |
---|
983 | |
---|
984 | ! heating (cooling) and moistening due to evaporation |
---|
985 | ! - latent heat of vaporization for precip production has already been accounted for |
---|
986 | ! - snow is contained in prec |
---|
987 | tend_s(i,k) =-evpprec(i)*latvap + ntsnprd(i,k)*latice |
---|
988 | tend_q(i,k) = evpprec(i) |
---|
989 | end do |
---|
990 | end do |
---|
991 | |
---|
992 | ! set output precipitation rates (m/s) |
---|
993 | prec(:ncol) = flxprec(:ncol,pver+1) / 1000._r8 |
---|
994 | snow(:ncol) = flxsnow(:ncol,pver+1) / 1000._r8 |
---|
995 | |
---|
996 | !********************************************************** |
---|
997 | !!$ tend_s(:ncol,:) = 0. ! turn heating off |
---|
998 | !********************************************************** |
---|
999 | |
---|
1000 | end subroutine zm_conv_evap |
---|
1001 | |
---|
1002 | |
---|
1003 | |
---|
1004 | subroutine convtran(lchnk , & |
---|
1005 | doconvtran,q ,ncnst ,mu ,md , & |
---|
1006 | du ,eu ,ed ,dp ,dsubcld , & |
---|
1007 | jt ,mx ,ideep ,il1g ,il2g , & |
---|
1008 | nstep ,fracis ,dqdt ,dpdry ) |
---|
1009 | !----------------------------------------------------------------------- |
---|
1010 | ! |
---|
1011 | ! Purpose: |
---|
1012 | ! Convective transport of trace species |
---|
1013 | ! |
---|
1014 | ! Mixing ratios may be with respect to either dry or moist air |
---|
1015 | ! |
---|
1016 | ! Method: |
---|
1017 | ! <Describe the algorithm(s) used in the routine.> |
---|
1018 | ! <Also include any applicable external references.> |
---|
1019 | ! |
---|
1020 | ! Author: P. Rasch |
---|
1021 | ! |
---|
1022 | !----------------------------------------------------------------------- |
---|
1023 | use shr_kind_mod, only: r8 => shr_kind_r8 |
---|
1024 | use constituents, only: cnst_get_type_byind |
---|
1025 | #ifndef WRF_PORT |
---|
1026 | use ppgrid |
---|
1027 | use abortutils, only: endrun |
---|
1028 | !~~~#else |
---|
1029 | ! use module_cam_support, only: cnst_get_type_byind |
---|
1030 | #endif |
---|
1031 | |
---|
1032 | implicit none |
---|
1033 | !----------------------------------------------------------------------- |
---|
1034 | ! |
---|
1035 | ! Input arguments |
---|
1036 | ! |
---|
1037 | integer, intent(in) :: lchnk ! chunk identifier |
---|
1038 | integer, intent(in) :: ncnst ! number of tracers to transport |
---|
1039 | logical, intent(in) :: doconvtran(ncnst) ! flag for doing convective transport |
---|
1040 | real(r8), intent(in) :: q(pcols,pver,ncnst) ! Tracer array including moisture |
---|
1041 | real(r8), intent(in) :: mu(pcols,pver) ! Mass flux up |
---|
1042 | real(r8), intent(in) :: md(pcols,pver) ! Mass flux down |
---|
1043 | real(r8), intent(in) :: du(pcols,pver) ! Mass detraining from updraft |
---|
1044 | real(r8), intent(in) :: eu(pcols,pver) ! Mass entraining from updraft |
---|
1045 | real(r8), intent(in) :: ed(pcols,pver) ! Mass entraining from downdraft |
---|
1046 | real(r8), intent(in) :: dp(pcols,pver) ! Delta pressure between interfaces |
---|
1047 | real(r8), intent(in) :: dsubcld(pcols) ! Delta pressure from cloud base to sfc |
---|
1048 | real(r8), intent(in) :: fracis(pcols,pver,ncnst) ! fraction of tracer that is insoluble |
---|
1049 | |
---|
1050 | integer, intent(in) :: jt(pcols) ! Index of cloud top for each column |
---|
1051 | integer, intent(in) :: mx(pcols) ! Index of cloud top for each column |
---|
1052 | integer, intent(in) :: ideep(pcols) ! Gathering array |
---|
1053 | integer, intent(in) :: il1g ! Gathered min lon indices over which to operate |
---|
1054 | integer, intent(in) :: il2g ! Gathered max lon indices over which to operate |
---|
1055 | integer, intent(in) :: nstep ! Time step index |
---|
1056 | |
---|
1057 | real(r8), intent(in) :: dpdry(pcols,pver) ! Delta pressure between interfaces |
---|
1058 | |
---|
1059 | |
---|
1060 | ! input/output |
---|
1061 | |
---|
1062 | real(r8), intent(out) :: dqdt(pcols,pver,ncnst) ! Tracer tendency array |
---|
1063 | |
---|
1064 | !--------------------------Local Variables------------------------------ |
---|
1065 | |
---|
1066 | integer i ! Work index |
---|
1067 | integer k ! Work index |
---|
1068 | integer kbm ! Highest altitude index of cloud base |
---|
1069 | integer kk ! Work index |
---|
1070 | integer kkp1 ! Work index |
---|
1071 | integer km1 ! Work index |
---|
1072 | integer kp1 ! Work index |
---|
1073 | integer ktm ! Highest altitude index of cloud top |
---|
1074 | integer m ! Work index |
---|
1075 | |
---|
1076 | real(r8) cabv ! Mix ratio of constituent above |
---|
1077 | real(r8) cbel ! Mix ratio of constituent below |
---|
1078 | real(r8) cdifr ! Normalized diff between cabv and cbel |
---|
1079 | real(r8) chat(pcols,pver) ! Mix ratio in env at interfaces |
---|
1080 | real(r8) cond(pcols,pver) ! Mix ratio in downdraft at interfaces |
---|
1081 | real(r8) const(pcols,pver) ! Gathered tracer array |
---|
1082 | real(r8) fisg(pcols,pver) ! gathered insoluble fraction of tracer |
---|
1083 | real(r8) conu(pcols,pver) ! Mix ratio in updraft at interfaces |
---|
1084 | real(r8) dcondt(pcols,pver) ! Gathered tend array |
---|
1085 | real(r8) small ! A small number |
---|
1086 | real(r8) mbsth ! Threshold for mass fluxes |
---|
1087 | real(r8) mupdudp ! A work variable |
---|
1088 | real(r8) minc ! A work variable |
---|
1089 | real(r8) maxc ! A work variable |
---|
1090 | real(r8) fluxin ! A work variable |
---|
1091 | real(r8) fluxout ! A work variable |
---|
1092 | real(r8) netflux ! A work variable |
---|
1093 | |
---|
1094 | real(r8) dutmp(pcols,pver) ! Mass detraining from updraft |
---|
1095 | real(r8) eutmp(pcols,pver) ! Mass entraining from updraft |
---|
1096 | real(r8) edtmp(pcols,pver) ! Mass entraining from downdraft |
---|
1097 | real(r8) dptmp(pcols,pver) ! Delta pressure between interfaces |
---|
1098 | !----------------------------------------------------------------------- |
---|
1099 | ! |
---|
1100 | small = 1.e-36_r8 |
---|
1101 | |
---|
1102 | ! mbsth is the threshold below which we treat the mass fluxes as zero (in mb/s) |
---|
1103 | mbsth = 1.e-15_r8 |
---|
1104 | |
---|
1105 | ! Find the highest level top and bottom levels of convection |
---|
1106 | ktm = pver |
---|
1107 | kbm = pver |
---|
1108 | do i = il1g, il2g |
---|
1109 | ktm = min(ktm,jt(i)) |
---|
1110 | kbm = min(kbm,mx(i)) |
---|
1111 | end do |
---|
1112 | |
---|
1113 | ! Loop ever each constituent |
---|
1114 | do m = 2, ncnst |
---|
1115 | if (doconvtran(m)) then |
---|
1116 | |
---|
1117 | if (cnst_get_type_byind(m).eq.'dry') then |
---|
1118 | do k = 1,pver |
---|
1119 | do i =il1g,il2g |
---|
1120 | dptmp(i,k) = dpdry(i,k) |
---|
1121 | dutmp(i,k) = du(i,k)*dp(i,k)/dpdry(i,k) |
---|
1122 | eutmp(i,k) = eu(i,k)*dp(i,k)/dpdry(i,k) |
---|
1123 | edtmp(i,k) = ed(i,k)*dp(i,k)/dpdry(i,k) |
---|
1124 | end do |
---|
1125 | end do |
---|
1126 | else |
---|
1127 | do k = 1,pver |
---|
1128 | do i =il1g,il2g |
---|
1129 | dptmp(i,k) = dp(i,k) |
---|
1130 | dutmp(i,k) = du(i,k) |
---|
1131 | eutmp(i,k) = eu(i,k) |
---|
1132 | edtmp(i,k) = ed(i,k) |
---|
1133 | end do |
---|
1134 | end do |
---|
1135 | endif |
---|
1136 | ! dptmp = dp |
---|
1137 | |
---|
1138 | ! Gather up the constituent and set tend to zero |
---|
1139 | do k = 1,pver |
---|
1140 | do i =il1g,il2g |
---|
1141 | const(i,k) = q(ideep(i),k,m) |
---|
1142 | fisg(i,k) = fracis(ideep(i),k,m) |
---|
1143 | end do |
---|
1144 | end do |
---|
1145 | |
---|
1146 | ! From now on work only with gathered data |
---|
1147 | |
---|
1148 | ! Interpolate environment tracer values to interfaces |
---|
1149 | do k = 1,pver |
---|
1150 | km1 = max(1,k-1) |
---|
1151 | do i = il1g, il2g |
---|
1152 | minc = min(const(i,km1),const(i,k)) |
---|
1153 | maxc = max(const(i,km1),const(i,k)) |
---|
1154 | if (minc < 0) then |
---|
1155 | cdifr = 0._r8 |
---|
1156 | else |
---|
1157 | cdifr = abs(const(i,k)-const(i,km1))/max(maxc,small) |
---|
1158 | endif |
---|
1159 | |
---|
1160 | ! If the two layers differ significantly use a geometric averaging |
---|
1161 | ! procedure |
---|
1162 | if (cdifr > 1.E-6_r8) then |
---|
1163 | cabv = max(const(i,km1),maxc*1.e-12_r8) |
---|
1164 | cbel = max(const(i,k),maxc*1.e-12_r8) |
---|
1165 | chat(i,k) = log(cabv/cbel)/(cabv-cbel)*cabv*cbel |
---|
1166 | |
---|
1167 | else ! Small diff, so just arithmetic mean |
---|
1168 | chat(i,k) = 0.5_r8* (const(i,k)+const(i,km1)) |
---|
1169 | end if |
---|
1170 | |
---|
1171 | ! Provisional up and down draft values |
---|
1172 | conu(i,k) = chat(i,k) |
---|
1173 | cond(i,k) = chat(i,k) |
---|
1174 | |
---|
1175 | ! provisional tends |
---|
1176 | dcondt(i,k) = 0._r8 |
---|
1177 | |
---|
1178 | end do |
---|
1179 | end do |
---|
1180 | |
---|
1181 | ! Do levels adjacent to top and bottom |
---|
1182 | k = 2 |
---|
1183 | km1 = 1 |
---|
1184 | kk = pver |
---|
1185 | do i = il1g,il2g |
---|
1186 | mupdudp = mu(i,kk) + dutmp(i,kk)*dptmp(i,kk) |
---|
1187 | if (mupdudp > mbsth) then |
---|
1188 | conu(i,kk) = (+eutmp(i,kk)*fisg(i,kk)*const(i,kk)*dptmp(i,kk))/mupdudp |
---|
1189 | endif |
---|
1190 | if (md(i,k) < -mbsth) then |
---|
1191 | cond(i,k) = (-edtmp(i,km1)*fisg(i,km1)*const(i,km1)*dptmp(i,km1))/md(i,k) |
---|
1192 | endif |
---|
1193 | end do |
---|
1194 | |
---|
1195 | ! Updraft from bottom to top |
---|
1196 | do kk = pver-1,1,-1 |
---|
1197 | kkp1 = min(pver,kk+1) |
---|
1198 | do i = il1g,il2g |
---|
1199 | mupdudp = mu(i,kk) + dutmp(i,kk)*dptmp(i,kk) |
---|
1200 | if (mupdudp > mbsth) then |
---|
1201 | conu(i,kk) = ( mu(i,kkp1)*conu(i,kkp1)+eutmp(i,kk)*fisg(i,kk)* & |
---|
1202 | const(i,kk)*dptmp(i,kk) )/mupdudp |
---|
1203 | endif |
---|
1204 | end do |
---|
1205 | end do |
---|
1206 | |
---|
1207 | ! Downdraft from top to bottom |
---|
1208 | do k = 3,pver |
---|
1209 | km1 = max(1,k-1) |
---|
1210 | do i = il1g,il2g |
---|
1211 | if (md(i,k) < -mbsth) then |
---|
1212 | cond(i,k) = ( md(i,km1)*cond(i,km1)-edtmp(i,km1)*fisg(i,km1)*const(i,km1) & |
---|
1213 | *dptmp(i,km1) )/md(i,k) |
---|
1214 | endif |
---|
1215 | end do |
---|
1216 | end do |
---|
1217 | |
---|
1218 | |
---|
1219 | do k = ktm,pver |
---|
1220 | km1 = max(1,k-1) |
---|
1221 | kp1 = min(pver,k+1) |
---|
1222 | do i = il1g,il2g |
---|
1223 | |
---|
1224 | ! version 1 hard to check for roundoff errors |
---|
1225 | ! dcondt(i,k) = |
---|
1226 | ! $ +(+mu(i,kp1)* (conu(i,kp1)-chat(i,kp1)) |
---|
1227 | ! $ -mu(i,k)* (conu(i,k)-chat(i,k)) |
---|
1228 | ! $ +md(i,kp1)* (cond(i,kp1)-chat(i,kp1)) |
---|
1229 | ! $ -md(i,k)* (cond(i,k)-chat(i,k)) |
---|
1230 | ! $ )/dp(i,k) |
---|
1231 | |
---|
1232 | ! version 2 hard to limit fluxes |
---|
1233 | ! fluxin = mu(i,kp1)*conu(i,kp1) + mu(i,k)*chat(i,k) |
---|
1234 | ! $ -(md(i,k) *cond(i,k) + md(i,kp1)*chat(i,kp1)) |
---|
1235 | ! fluxout = mu(i,k)*conu(i,k) + mu(i,kp1)*chat(i,kp1) |
---|
1236 | ! $ -(md(i,kp1)*cond(i,kp1) + md(i,k)*chat(i,k)) |
---|
1237 | |
---|
1238 | ! version 3 limit fluxes outside convection to mass in appropriate layer |
---|
1239 | ! these limiters are probably only safe for positive definite quantitities |
---|
1240 | ! it assumes that mu and md already satify a courant number limit of 1 |
---|
1241 | fluxin = mu(i,kp1)*conu(i,kp1)+ mu(i,k)*min(chat(i,k),const(i,km1)) & |
---|
1242 | -(md(i,k) *cond(i,k) + md(i,kp1)*min(chat(i,kp1),const(i,kp1))) |
---|
1243 | fluxout = mu(i,k)*conu(i,k) + mu(i,kp1)*min(chat(i,kp1),const(i,k)) & |
---|
1244 | -(md(i,kp1)*cond(i,kp1) + md(i,k)*min(chat(i,k),const(i,k))) |
---|
1245 | |
---|
1246 | netflux = fluxin - fluxout |
---|
1247 | if (abs(netflux) < max(fluxin,fluxout)*1.e-12_r8) then |
---|
1248 | netflux = 0._r8 |
---|
1249 | endif |
---|
1250 | dcondt(i,k) = netflux/dptmp(i,k) |
---|
1251 | end do |
---|
1252 | end do |
---|
1253 | ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
1254 | ! |
---|
1255 | !DIR$ NOINTERCHANGE |
---|
1256 | do k = kbm,pver |
---|
1257 | km1 = max(1,k-1) |
---|
1258 | do i = il1g,il2g |
---|
1259 | if (k == mx(i)) then |
---|
1260 | |
---|
1261 | ! version 1 |
---|
1262 | ! dcondt(i,k) = (1./dsubcld(i))* |
---|
1263 | ! $ (-mu(i,k)*(conu(i,k)-chat(i,k)) |
---|
1264 | ! $ -md(i,k)*(cond(i,k)-chat(i,k)) |
---|
1265 | ! $ ) |
---|
1266 | |
---|
1267 | ! version 2 |
---|
1268 | ! fluxin = mu(i,k)*chat(i,k) - md(i,k)*cond(i,k) |
---|
1269 | ! fluxout = mu(i,k)*conu(i,k) - md(i,k)*chat(i,k) |
---|
1270 | ! version 3 |
---|
1271 | fluxin = mu(i,k)*min(chat(i,k),const(i,km1)) - md(i,k)*cond(i,k) |
---|
1272 | fluxout = mu(i,k)*conu(i,k) - md(i,k)*min(chat(i,k),const(i,k)) |
---|
1273 | |
---|
1274 | netflux = fluxin - fluxout |
---|
1275 | if (abs(netflux) < max(fluxin,fluxout)*1.e-12_r8) then |
---|
1276 | netflux = 0._r8 |
---|
1277 | endif |
---|
1278 | ! dcondt(i,k) = netflux/dsubcld(i) |
---|
1279 | dcondt(i,k) = netflux/dptmp(i,k) |
---|
1280 | else if (k > mx(i)) then |
---|
1281 | ! dcondt(i,k) = dcondt(i,k-1) |
---|
1282 | dcondt(i,k) = 0._r8 |
---|
1283 | end if |
---|
1284 | end do |
---|
1285 | end do |
---|
1286 | |
---|
1287 | ! Initialize to zero everywhere, then scatter tendency back to full array |
---|
1288 | dqdt(:,:,m) = 0._r8 |
---|
1289 | do k = 1,pver |
---|
1290 | kp1 = min(pver,k+1) |
---|
1291 | !DIR$ CONCURRENT |
---|
1292 | do i = il1g,il2g |
---|
1293 | dqdt(ideep(i),k,m) = dcondt(i,k) |
---|
1294 | end do |
---|
1295 | end do |
---|
1296 | |
---|
1297 | end if ! for doconvtran |
---|
1298 | |
---|
1299 | end do |
---|
1300 | |
---|
1301 | return |
---|
1302 | end subroutine convtran |
---|
1303 | |
---|
1304 | !========================================================================================= |
---|
1305 | |
---|
1306 | subroutine momtran(lchnk, ncol, & |
---|
1307 | domomtran,q ,ncnst ,mu ,md , & |
---|
1308 | du ,eu ,ed ,dp ,dsubcld , & |
---|
1309 | jt ,mx ,ideep ,il1g ,il2g , & |
---|
1310 | nstep ,dqdt ,pguall ,pgdall, icwu, icwd, dt, seten ) |
---|
1311 | !----------------------------------------------------------------------- |
---|
1312 | ! |
---|
1313 | ! Purpose: |
---|
1314 | ! Convective transport of momentum |
---|
1315 | ! |
---|
1316 | ! Mixing ratios may be with respect to either dry or moist air |
---|
1317 | ! |
---|
1318 | ! Method: |
---|
1319 | ! Based on the convtran subroutine by P. Rasch |
---|
1320 | ! <Also include any applicable external references.> |
---|
1321 | ! |
---|
1322 | ! Author: J. Richter and P. Rasch |
---|
1323 | ! |
---|
1324 | !----------------------------------------------------------------------- |
---|
1325 | use shr_kind_mod, only: r8 => shr_kind_r8 |
---|
1326 | #ifndef WRF_PORT |
---|
1327 | use constituents, only: cnst_get_type_byind |
---|
1328 | use ppgrid |
---|
1329 | use abortutils, only: endrun |
---|
1330 | #endif |
---|
1331 | implicit none |
---|
1332 | !----------------------------------------------------------------------- |
---|
1333 | ! |
---|
1334 | ! Input arguments |
---|
1335 | ! |
---|
1336 | integer, intent(in) :: lchnk ! chunk identifier |
---|
1337 | integer, intent(in) :: ncol ! number of atmospheric columns |
---|
1338 | integer, intent(in) :: ncnst ! number of tracers to transport |
---|
1339 | logical, intent(in) :: domomtran(ncnst) ! flag for doing convective transport |
---|
1340 | real(r8), intent(in) :: q(pcols,pver,ncnst) ! Wind array |
---|
1341 | real(r8), intent(in) :: mu(pcols,pver) ! Mass flux up |
---|
1342 | real(r8), intent(in) :: md(pcols,pver) ! Mass flux down |
---|
1343 | real(r8), intent(in) :: du(pcols,pver) ! Mass detraining from updraft |
---|
1344 | real(r8), intent(in) :: eu(pcols,pver) ! Mass entraining from updraft |
---|
1345 | real(r8), intent(in) :: ed(pcols,pver) ! Mass entraining from downdraft |
---|
1346 | real(r8), intent(in) :: dp(pcols,pver) ! Delta pressure between interfaces |
---|
1347 | real(r8), intent(in) :: dsubcld(pcols) ! Delta pressure from cloud base to sfc |
---|
1348 | real(r8), intent(in) :: dt ! time step in seconds : 2*delta_t |
---|
1349 | |
---|
1350 | integer, intent(in) :: jt(pcols) ! Index of cloud top for each column |
---|
1351 | integer, intent(in) :: mx(pcols) ! Index of cloud top for each column |
---|
1352 | integer, intent(in) :: ideep(pcols) ! Gathering array |
---|
1353 | integer, intent(in) :: il1g ! Gathered min lon indices over which to operate |
---|
1354 | integer, intent(in) :: il2g ! Gathered max lon indices over which to operate |
---|
1355 | integer, intent(in) :: nstep ! Time step index |
---|
1356 | |
---|
1357 | |
---|
1358 | |
---|
1359 | ! input/output |
---|
1360 | |
---|
1361 | real(r8), intent(out) :: dqdt(pcols,pver,ncnst) ! Tracer tendency array |
---|
1362 | |
---|
1363 | !--------------------------Local Variables------------------------------ |
---|
1364 | |
---|
1365 | integer i ! Work index |
---|
1366 | integer k ! Work index |
---|
1367 | integer kbm ! Highest altitude index of cloud base |
---|
1368 | integer kk ! Work index |
---|
1369 | integer kkp1 ! Work index |
---|
1370 | integer kkm1 ! Work index |
---|
1371 | integer km1 ! Work index |
---|
1372 | integer kp1 ! Work index |
---|
1373 | integer ktm ! Highest altitude index of cloud top |
---|
1374 | integer m ! Work index |
---|
1375 | integer ii ! Work index |
---|
1376 | |
---|
1377 | real(r8) cabv ! Mix ratio of constituent above |
---|
1378 | real(r8) cbel ! Mix ratio of constituent below |
---|
1379 | real(r8) cdifr ! Normalized diff between cabv and cbel |
---|
1380 | real(r8) chat(pcols,pver) ! Mix ratio in env at interfaces |
---|
1381 | real(r8) cond(pcols,pver) ! Mix ratio in downdraft at interfaces |
---|
1382 | real(r8) const(pcols,pver) ! Gathered wind array |
---|
1383 | real(r8) conu(pcols,pver) ! Mix ratio in updraft at interfaces |
---|
1384 | real(r8) dcondt(pcols,pver) ! Gathered tend array |
---|
1385 | real(r8) small ! A small number |
---|
1386 | real(r8) mbsth ! Threshold for mass fluxes |
---|
1387 | real(r8) mupdudp ! A work variable |
---|
1388 | real(r8) minc ! A work variable |
---|
1389 | real(r8) maxc ! A work variable |
---|
1390 | real(r8) fluxin ! A work variable |
---|
1391 | real(r8) fluxout ! A work variable |
---|
1392 | real(r8) netflux ! A work variable |
---|
1393 | |
---|
1394 | real(r8) momcu ! constant for updraft pressure gradient term |
---|
1395 | real(r8) momcd ! constant for downdraft pressure gradient term |
---|
1396 | real(r8) sum ! sum |
---|
1397 | real(r8) sum2 ! sum2 |
---|
1398 | |
---|
1399 | real(r8) mududp(pcols,pver) ! working variable |
---|
1400 | real(r8) mddudp(pcols,pver) ! working variable |
---|
1401 | |
---|
1402 | real(r8) pgu(pcols,pver) ! Pressure gradient term for updraft |
---|
1403 | real(r8) pgd(pcols,pver) ! Pressure gradient term for downdraft |
---|
1404 | |
---|
1405 | real(r8),intent(out) :: pguall(pcols,pver,ncnst) ! Apparent force from updraft PG |
---|
1406 | real(r8),intent(out) :: pgdall(pcols,pver,ncnst) ! Apparent force from downdraft PG |
---|
1407 | |
---|
1408 | real(r8),intent(out) :: icwu(pcols,pver,ncnst) ! In-cloud winds in updraft |
---|
1409 | real(r8),intent(out) :: icwd(pcols,pver,ncnst) ! In-cloud winds in downdraft |
---|
1410 | |
---|
1411 | real(r8),intent(out) :: seten(pcols,pver) ! Dry static energy tendency |
---|
1412 | real(r8) gseten(pcols,pver) ! Gathered dry static energy tendency |
---|
1413 | |
---|
1414 | real(r8) mflux(pcols,pverp,ncnst) ! Gathered momentum flux |
---|
1415 | |
---|
1416 | real(r8) wind0(pcols,pver,ncnst) ! gathered wind before time step |
---|
1417 | real(r8) windf(pcols,pver,ncnst) ! gathered wind after time step |
---|
1418 | real(r8) fkeb, fket, ketend_cons, ketend, utop, ubot, vtop, vbot, gset2 |
---|
1419 | |
---|
1420 | |
---|
1421 | !----------------------------------------------------------------------- |
---|
1422 | ! |
---|
1423 | |
---|
1424 | ! Initialize outgoing fields |
---|
1425 | pguall(:,:,:) = 0.0_r8 |
---|
1426 | pgdall(:,:,:) = 0.0_r8 |
---|
1427 | ! Initialize in-cloud winds to environmental wind |
---|
1428 | icwu(:ncol,:,:) = q(:ncol,:,:) |
---|
1429 | icwd(:ncol,:,:) = q(:ncol,:,:) |
---|
1430 | |
---|
1431 | ! Initialize momentum flux and final winds |
---|
1432 | mflux(:,:,:) = 0.0_r8 |
---|
1433 | wind0(:,:,:) = 0.0_r8 |
---|
1434 | windf(:,:,:) = 0.0_r8 |
---|
1435 | |
---|
1436 | ! Initialize dry static energy |
---|
1437 | |
---|
1438 | seten(:,:) = 0.0_r8 |
---|
1439 | gseten(:,:) = 0.0_r8 |
---|
1440 | |
---|
1441 | ! Define constants for parameterization |
---|
1442 | |
---|
1443 | momcu = 0.4_r8 |
---|
1444 | momcd = 0.4_r8 |
---|
1445 | |
---|
1446 | small = 1.e-36_r8 |
---|
1447 | ! mbsth is the threshold below which we treat the mass fluxes as zero (in mb/s) |
---|
1448 | mbsth = 1.e-15_r8 |
---|
1449 | |
---|
1450 | ! Find the highest level top and bottom levels of convection |
---|
1451 | ktm = pver |
---|
1452 | kbm = pver |
---|
1453 | do i = il1g, il2g |
---|
1454 | ktm = min(ktm,jt(i)) |
---|
1455 | kbm = min(kbm,mx(i)) |
---|
1456 | end do |
---|
1457 | |
---|
1458 | ! Loop ever each wind component |
---|
1459 | do m = 1, ncnst !start at m = 1 to transport momentum |
---|
1460 | if (domomtran(m)) then |
---|
1461 | |
---|
1462 | ! Gather up the winds and set tend to zero |
---|
1463 | do k = 1,pver |
---|
1464 | do i =il1g,il2g |
---|
1465 | const(i,k) = q(ideep(i),k,m) |
---|
1466 | wind0(i,k,m) = const(i,k) |
---|
1467 | end do |
---|
1468 | end do |
---|
1469 | |
---|
1470 | |
---|
1471 | ! From now on work only with gathered data |
---|
1472 | |
---|
1473 | ! Interpolate winds to interfaces |
---|
1474 | |
---|
1475 | do k = 1,pver |
---|
1476 | km1 = max(1,k-1) |
---|
1477 | do i = il1g, il2g |
---|
1478 | |
---|
1479 | ! use arithmetic mean |
---|
1480 | chat(i,k) = 0.5_r8* (const(i,k)+const(i,km1)) |
---|
1481 | |
---|
1482 | ! Provisional up and down draft values |
---|
1483 | conu(i,k) = chat(i,k) |
---|
1484 | cond(i,k) = chat(i,k) |
---|
1485 | |
---|
1486 | ! provisional tends |
---|
1487 | dcondt(i,k) = 0._r8 |
---|
1488 | |
---|
1489 | end do |
---|
1490 | end do |
---|
1491 | |
---|
1492 | |
---|
1493 | ! |
---|
1494 | ! Pressure Perturbation Term |
---|
1495 | ! |
---|
1496 | |
---|
1497 | !Top boundary: assume mu is zero |
---|
1498 | |
---|
1499 | k=1 |
---|
1500 | pgu(:il2g,k) = 0.0_r8 |
---|
1501 | pgd(:il2g,k) = 0.0_r8 |
---|
1502 | |
---|
1503 | do k=2,pver-1 |
---|
1504 | km1 = max(1,k-1) |
---|
1505 | kp1 = min(pver,k+1) |
---|
1506 | do i = il1g,il2g |
---|
1507 | |
---|
1508 | !interior points |
---|
1509 | |
---|
1510 | mududp(i,k) = ( mu(i,k) * (const(i,k)- const(i,km1))/dp(i,km1) & |
---|
1511 | + mu(i,kp1) * (const(i,kp1) - const(i,k))/dp(i,k)) |
---|
1512 | |
---|
1513 | pgu(i,k) = - momcu * 0.5_r8 * mududp(i,k) |
---|
1514 | |
---|
1515 | |
---|
1516 | mddudp(i,k) = ( md(i,k) * (const(i,k)- const(i,km1))/dp(i,km1) & |
---|
1517 | + md(i,kp1) * (const(i,kp1) - const(i,k))/dp(i,k)) |
---|
1518 | |
---|
1519 | pgd(i,k) = - momcd * 0.5_r8 * mddudp(i,k) |
---|
1520 | |
---|
1521 | |
---|
1522 | end do |
---|
1523 | end do |
---|
1524 | |
---|
1525 | ! bottom boundary |
---|
1526 | k = pver |
---|
1527 | km1 = max(1,k-1) |
---|
1528 | do i=il1g,il2g |
---|
1529 | |
---|
1530 | mududp(i,k) = mu(i,k) * (const(i,k)- const(i,km1))/dp(i,km1) |
---|
1531 | pgu(i,k) = - momcu * mududp(i,k) |
---|
1532 | |
---|
1533 | mddudp(i,k) = md(i,k) * (const(i,k)- const(i,km1))/dp(i,km1) |
---|
1534 | |
---|
1535 | pgd(i,k) = - momcd * mddudp(i,k) |
---|
1536 | |
---|
1537 | end do |
---|
1538 | |
---|
1539 | |
---|
1540 | ! |
---|
1541 | ! In-cloud velocity calculations |
---|
1542 | ! |
---|
1543 | |
---|
1544 | ! Do levels adjacent to top and bottom |
---|
1545 | k = 2 |
---|
1546 | km1 = 1 |
---|
1547 | kk = pver |
---|
1548 | kkm1 = max(1,kk-1) |
---|
1549 | do i = il1g,il2g |
---|
1550 | mupdudp = mu(i,kk) + du(i,kk)*dp(i,kk) |
---|
1551 | if (mupdudp > mbsth) then |
---|
1552 | |
---|
1553 | conu(i,kk) = (+eu(i,kk)*const(i,kk)*dp(i,kk)+pgu(i,kk)*dp(i,kk))/mupdudp |
---|
1554 | endif |
---|
1555 | if (md(i,k) < -mbsth) then |
---|
1556 | cond(i,k) = (-ed(i,km1)*const(i,km1)*dp(i,km1))-pgd(i,km1)*dp(i,km1)/md(i,k) |
---|
1557 | endif |
---|
1558 | |
---|
1559 | |
---|
1560 | end do |
---|
1561 | |
---|
1562 | |
---|
1563 | |
---|
1564 | ! Updraft from bottom to top |
---|
1565 | do kk = pver-1,1,-1 |
---|
1566 | kkm1 = max(1,kk-1) |
---|
1567 | kkp1 = min(pver,kk+1) |
---|
1568 | do i = il1g,il2g |
---|
1569 | mupdudp = mu(i,kk) + du(i,kk)*dp(i,kk) |
---|
1570 | if (mupdudp > mbsth) then |
---|
1571 | |
---|
1572 | conu(i,kk) = ( mu(i,kkp1)*conu(i,kkp1)+eu(i,kk)* & |
---|
1573 | const(i,kk)*dp(i,kk)+pgu(i,kk)*dp(i,kk))/mupdudp |
---|
1574 | endif |
---|
1575 | end do |
---|
1576 | |
---|
1577 | end do |
---|
1578 | |
---|
1579 | |
---|
1580 | ! Downdraft from top to bottom |
---|
1581 | do k = 3,pver |
---|
1582 | km1 = max(1,k-1) |
---|
1583 | do i = il1g,il2g |
---|
1584 | if (md(i,k) < -mbsth) then |
---|
1585 | |
---|
1586 | cond(i,k) = ( md(i,km1)*cond(i,km1)-ed(i,km1)*const(i,km1) & |
---|
1587 | *dp(i,km1)-pgd(i,km1)*dp(i,km1) )/md(i,k) |
---|
1588 | |
---|
1589 | endif |
---|
1590 | end do |
---|
1591 | end do |
---|
1592 | |
---|
1593 | |
---|
1594 | sum = 0._r8 |
---|
1595 | sum2 = 0._r8 |
---|
1596 | |
---|
1597 | |
---|
1598 | do k = ktm,pver |
---|
1599 | km1 = max(1,k-1) |
---|
1600 | kp1 = min(pver,k+1) |
---|
1601 | do i = il1g,il2g |
---|
1602 | ii = ideep(i) |
---|
1603 | |
---|
1604 | ! version 1 hard to check for roundoff errors |
---|
1605 | dcondt(i,k) = & |
---|
1606 | +(mu(i,kp1)* (conu(i,kp1)-chat(i,kp1)) & |
---|
1607 | -mu(i,k)* (conu(i,k)-chat(i,k)) & |
---|
1608 | +md(i,kp1)* (cond(i,kp1)-chat(i,kp1)) & |
---|
1609 | -md(i,k)* (cond(i,k)-chat(i,k)) & |
---|
1610 | )/dp(i,k) |
---|
1611 | |
---|
1612 | end do |
---|
1613 | end do |
---|
1614 | |
---|
1615 | ! dcont for bottom layer |
---|
1616 | ! |
---|
1617 | !DIR$ NOINTERCHANGE |
---|
1618 | do k = kbm,pver |
---|
1619 | km1 = max(1,k-1) |
---|
1620 | do i = il1g,il2g |
---|
1621 | if (k == mx(i)) then |
---|
1622 | |
---|
1623 | ! version 1 |
---|
1624 | dcondt(i,k) = (1./dp(i,k))* & |
---|
1625 | (-mu(i,k)*(conu(i,k)-chat(i,k)) & |
---|
1626 | -md(i,k)*(cond(i,k)-chat(i,k)) & |
---|
1627 | ) |
---|
1628 | end if |
---|
1629 | end do |
---|
1630 | end do |
---|
1631 | |
---|
1632 | ! Initialize to zero everywhere, then scatter tendency back to full array |
---|
1633 | dqdt(:,:,m) = 0._r8 |
---|
1634 | |
---|
1635 | do k = 1,pver |
---|
1636 | do i = il1g,il2g |
---|
1637 | ii = ideep(i) |
---|
1638 | dqdt(ii,k,m) = dcondt(i,k) |
---|
1639 | ! Output apparent force on the mean flow from pressure gradient |
---|
1640 | pguall(ii,k,m) = -pgu(i,k) |
---|
1641 | pgdall(ii,k,m) = -pgd(i,k) |
---|
1642 | icwu(ii,k,m) = conu(i,k) |
---|
1643 | icwd(ii,k,m) = cond(i,k) |
---|
1644 | end do |
---|
1645 | end do |
---|
1646 | |
---|
1647 | ! Calculate momentum flux in units of mb*m/s2 |
---|
1648 | |
---|
1649 | do k = ktm,pver |
---|
1650 | do i = il1g,il2g |
---|
1651 | ii = ideep(i) |
---|
1652 | mflux(i,k,m) = & |
---|
1653 | -mu(i,k)* (conu(i,k)-chat(i,k)) & |
---|
1654 | -md(i,k)* (cond(i,k)-chat(i,k)) |
---|
1655 | end do |
---|
1656 | end do |
---|
1657 | |
---|
1658 | |
---|
1659 | ! Calculate winds at the end of the time step |
---|
1660 | |
---|
1661 | do k = ktm,pver |
---|
1662 | do i = il1g,il2g |
---|
1663 | ii = ideep(i) |
---|
1664 | km1 = max(1,k-1) |
---|
1665 | kp1 = k+1 |
---|
1666 | windf(i,k,m) = const(i,k) - (mflux(i,kp1,m) - mflux(i,k,m)) * dt /dp(i,k) |
---|
1667 | |
---|
1668 | end do |
---|
1669 | end do |
---|
1670 | |
---|
1671 | end if ! for domomtran |
---|
1672 | end do |
---|
1673 | |
---|
1674 | ! Need to add an energy fix to account for the dissipation of kinetic energy |
---|
1675 | ! Formulation follows from Boville and Bretherton (2003) |
---|
1676 | ! formulation by PJR |
---|
1677 | |
---|
1678 | do k = ktm,pver |
---|
1679 | km1 = max(1,k-1) |
---|
1680 | kp1 = min(pver,k+1) |
---|
1681 | do i = il1g,il2g |
---|
1682 | |
---|
1683 | ii = ideep(i) |
---|
1684 | |
---|
1685 | ! calculate the KE fluxes at top and bot of layer |
---|
1686 | ! based on a discrete approximation to b&b eq(35) F_KE = u*F_u + v*F_v at interface |
---|
1687 | utop = (wind0(i,k,1)+wind0(i,km1,1))/2. |
---|
1688 | vtop = (wind0(i,k,2)+wind0(i,km1,2))/2. |
---|
1689 | ubot = (wind0(i,kp1,1)+wind0(i,k,1))/2. |
---|
1690 | vbot = (wind0(i,kp1,2)+wind0(i,k,2))/2. |
---|
1691 | fket = utop*mflux(i,k,1) + vtop*mflux(i,k,2) ! top of layer |
---|
1692 | fkeb = ubot*mflux(i,k+1,1) + vbot*mflux(i,k+1,2) ! bot of layer |
---|
1693 | |
---|
1694 | ! divergence of these fluxes should give a conservative redistribution of KE |
---|
1695 | ketend_cons = (fket-fkeb)/dp(i,k) |
---|
1696 | |
---|
1697 | ! tendency in kinetic energy resulting from the momentum transport |
---|
1698 | ketend = ((windf(i,k,1)**2 + windf(i,k,2)**2) - (wind0(i,k,1)**2 + wind0(i,k,2)**2))*0.5/dt |
---|
1699 | |
---|
1700 | ! the difference should be the dissipation |
---|
1701 | gset2 = ketend_cons - ketend |
---|
1702 | gseten(i,k) = gset2 |
---|
1703 | |
---|
1704 | end do |
---|
1705 | |
---|
1706 | end do |
---|
1707 | |
---|
1708 | ! Scatter dry static energy to full array |
---|
1709 | do k = 1,pver |
---|
1710 | do i = il1g,il2g |
---|
1711 | ii = ideep(i) |
---|
1712 | seten(ii,k) = gseten(i,k) |
---|
1713 | |
---|
1714 | end do |
---|
1715 | end do |
---|
1716 | |
---|
1717 | return |
---|
1718 | end subroutine momtran |
---|
1719 | |
---|
1720 | #ifndef WRF_PORT |
---|
1721 | !========================================================================================= |
---|
1722 | |
---|
1723 | subroutine buoyan(lchnk ,ncol , & |
---|
1724 | q ,t ,p ,z ,pf , & |
---|
1725 | tp ,qstp ,tl ,rl ,cape , & |
---|
1726 | pblt ,lcl ,lel ,lon ,mx , & |
---|
1727 | rd ,grav ,cp ,msg , & |
---|
1728 | tpert ) |
---|
1729 | !----------------------------------------------------------------------- |
---|
1730 | ! |
---|
1731 | ! Purpose: |
---|
1732 | ! <Say what the routine does> |
---|
1733 | ! |
---|
1734 | ! Method: |
---|
1735 | ! <Describe the algorithm(s) used in the routine.> |
---|
1736 | ! <Also include any applicable external references.> |
---|
1737 | ! |
---|
1738 | ! Author: |
---|
1739 | ! This is contributed code not fully standardized by the CCM core group. |
---|
1740 | ! The documentation has been enhanced to the degree that we are able. |
---|
1741 | ! Reviewed: P. Rasch, April 1996 |
---|
1742 | ! |
---|
1743 | !----------------------------------------------------------------------- |
---|
1744 | implicit none |
---|
1745 | !----------------------------------------------------------------------- |
---|
1746 | ! |
---|
1747 | ! input arguments |
---|
1748 | ! |
---|
1749 | integer, intent(in) :: lchnk ! chunk identifier |
---|
1750 | integer, intent(in) :: ncol ! number of atmospheric columns |
---|
1751 | |
---|
1752 | real(r8), intent(in) :: q(pcols,pver) ! spec. humidity |
---|
1753 | real(r8), intent(in) :: t(pcols,pver) ! temperature |
---|
1754 | real(r8), intent(in) :: p(pcols,pver) ! pressure |
---|
1755 | real(r8), intent(in) :: z(pcols,pver) ! height |
---|
1756 | real(r8), intent(in) :: pf(pcols,pver+1) ! pressure at interfaces |
---|
1757 | real(r8), intent(in) :: pblt(pcols) ! index of pbl depth |
---|
1758 | real(r8), intent(in) :: tpert(pcols) ! perturbation temperature by pbl processes |
---|
1759 | |
---|
1760 | ! |
---|
1761 | ! output arguments |
---|
1762 | ! |
---|
1763 | real(r8), intent(out) :: tp(pcols,pver) ! parcel temperature |
---|
1764 | real(r8), intent(out) :: qstp(pcols,pver) ! saturation mixing ratio of parcel |
---|
1765 | real(r8), intent(out) :: tl(pcols) ! parcel temperature at lcl |
---|
1766 | real(r8), intent(out) :: cape(pcols) ! convective aval. pot. energy. |
---|
1767 | integer lcl(pcols) ! |
---|
1768 | integer lel(pcols) ! |
---|
1769 | integer lon(pcols) ! level of onset of deep convection |
---|
1770 | integer mx(pcols) ! level of max moist static energy |
---|
1771 | ! |
---|
1772 | !--------------------------Local Variables------------------------------ |
---|
1773 | ! |
---|
1774 | real(r8) capeten(pcols,5) ! provisional value of cape |
---|
1775 | real(r8) tv(pcols,pver) ! |
---|
1776 | real(r8) tpv(pcols,pver) ! |
---|
1777 | real(r8) buoy(pcols,pver) |
---|
1778 | |
---|
1779 | real(r8) a1(pcols) |
---|
1780 | real(r8) a2(pcols) |
---|
1781 | real(r8) estp(pcols) |
---|
1782 | real(r8) pl(pcols) |
---|
1783 | real(r8) plexp(pcols) |
---|
1784 | real(r8) hmax(pcols) |
---|
1785 | real(r8) hmn(pcols) |
---|
1786 | real(r8) y(pcols) |
---|
1787 | |
---|
1788 | logical plge600(pcols) |
---|
1789 | integer knt(pcols) |
---|
1790 | integer lelten(pcols,5) |
---|
1791 | |
---|
1792 | real(r8) cp |
---|
1793 | real(r8) e |
---|
1794 | real(r8) grav |
---|
1795 | |
---|
1796 | integer i |
---|
1797 | integer k |
---|
1798 | integer msg |
---|
1799 | integer n |
---|
1800 | |
---|
1801 | real(r8) rd |
---|
1802 | real(r8) rl |
---|
1803 | #ifdef PERGRO |
---|
1804 | real(r8) rhd |
---|
1805 | #endif |
---|
1806 | ! |
---|
1807 | !----------------------------------------------------------------------- |
---|
1808 | ! |
---|
1809 | do n = 1,5 |
---|
1810 | do i = 1,ncol |
---|
1811 | lelten(i,n) = pver |
---|
1812 | capeten(i,n) = 0._r8 |
---|
1813 | end do |
---|
1814 | end do |
---|
1815 | ! |
---|
1816 | do i = 1,ncol |
---|
1817 | lon(i) = pver |
---|
1818 | knt(i) = 0 |
---|
1819 | lel(i) = pver |
---|
1820 | mx(i) = lon(i) |
---|
1821 | cape(i) = 0._r8 |
---|
1822 | hmax(i) = 0._r8 |
---|
1823 | end do |
---|
1824 | |
---|
1825 | tp(:ncol,:) = t(:ncol,:) |
---|
1826 | qstp(:ncol,:) = q(:ncol,:) |
---|
1827 | |
---|
1828 | !!! RBN - Initialize tv and buoy for output. |
---|
1829 | !!! tv=tv : tpv=tpv : qstp=q : buoy=0. |
---|
1830 | tv(:ncol,:) = t(:ncol,:) *(1._r8+1.608*q(:ncol,:))/ (1._r8+q(:ncol,:)) |
---|
1831 | tpv(:ncol,:) = tv(:ncol,:) |
---|
1832 | buoy(:ncol,:) = 0._r8 |
---|
1833 | |
---|
1834 | ! |
---|
1835 | ! set "launching" level(mx) to be at maximum moist static energy. |
---|
1836 | ! search for this level stops at planetary boundary layer top. |
---|
1837 | ! |
---|
1838 | #ifdef PERGRO |
---|
1839 | do k = pver,msg + 1,-1 |
---|
1840 | do i = 1,ncol |
---|
1841 | hmn(i) = cp*t(i,k) + grav*z(i,k) + rl*q(i,k) |
---|
1842 | ! |
---|
1843 | ! Reset max moist static energy level when relative difference exceeds 1.e-4 |
---|
1844 | ! |
---|
1845 | rhd = (hmn(i) - hmax(i))/(hmn(i) + hmax(i)) |
---|
1846 | if (k >= nint(pblt(i)) .and. k <= lon(i) .and. rhd > -1.e-4_r8) then |
---|
1847 | hmax(i) = hmn(i) |
---|
1848 | mx(i) = k |
---|
1849 | end if |
---|
1850 | end do |
---|
1851 | end do |
---|
1852 | #else |
---|
1853 | do k = pver,msg + 1,-1 |
---|
1854 | do i = 1,ncol |
---|
1855 | hmn(i) = cp*t(i,k) + grav*z(i,k) + rl*q(i,k) |
---|
1856 | if (k >= nint(pblt(i)) .and. k <= lon(i) .and. hmn(i) > hmax(i)) then |
---|
1857 | hmax(i) = hmn(i) |
---|
1858 | mx(i) = k |
---|
1859 | end if |
---|
1860 | end do |
---|
1861 | end do |
---|
1862 | #endif |
---|
1863 | ! |
---|
1864 | do i = 1,ncol |
---|
1865 | lcl(i) = mx(i) |
---|
1866 | e = p(i,mx(i))*q(i,mx(i))/ (eps1+q(i,mx(i))) |
---|
1867 | tl(i) = 2840._r8/ (3.5_r8*log(t(i,mx(i)))-log(e)-4.805_r8) + 55._r8 |
---|
1868 | if (tl(i) < t(i,mx(i))) then |
---|
1869 | plexp(i) = (1._r8/ (0.2854_r8* (1._r8-0.28_r8*q(i,mx(i))))) |
---|
1870 | pl(i) = p(i,mx(i))* (tl(i)/t(i,mx(i)))**plexp(i) |
---|
1871 | else |
---|
1872 | tl(i) = t(i,mx(i)) |
---|
1873 | pl(i) = p(i,mx(i)) |
---|
1874 | end if |
---|
1875 | end do |
---|
1876 | |
---|
1877 | ! |
---|
1878 | ! calculate lifting condensation level (lcl). |
---|
1879 | ! |
---|
1880 | do k = pver,msg + 2,-1 |
---|
1881 | do i = 1,ncol |
---|
1882 | if (k <= mx(i) .and. (p(i,k) > pl(i) .and. p(i,k-1) <= pl(i))) then |
---|
1883 | lcl(i) = k - 1 |
---|
1884 | end if |
---|
1885 | end do |
---|
1886 | end do |
---|
1887 | ! |
---|
1888 | ! if lcl is above the nominal level of non-divergence (600 mbs), |
---|
1889 | ! no deep convection is permitted (ensuing calculations |
---|
1890 | ! skipped and cape retains initialized value of zero). |
---|
1891 | ! |
---|
1892 | do i = 1,ncol |
---|
1893 | plge600(i) = pl(i).ge.600._r8 |
---|
1894 | end do |
---|
1895 | ! |
---|
1896 | ! initialize parcel properties in sub-cloud layer below lcl. |
---|
1897 | ! |
---|
1898 | do k = pver,msg + 1,-1 |
---|
1899 | do i=1,ncol |
---|
1900 | if (k > lcl(i) .and. k <= mx(i) .and. plge600(i)) then |
---|
1901 | tv(i,k) = t(i,k)* (1._r8+1.608_r8*q(i,k))/ (1._r8+q(i,k)) |
---|
1902 | qstp(i,k) = q(i,mx(i)) |
---|
1903 | tp(i,k) = t(i,mx(i))* (p(i,k)/p(i,mx(i)))**(0.2854_r8* (1._r8-0.28_r8*q(i,mx(i)))) |
---|
1904 | ! |
---|
1905 | ! buoyancy is increased by 0.5 k as in tiedtke |
---|
1906 | ! |
---|
1907 | !-jjh tpv (i,k)=tp(i,k)*(1.+1.608*q(i,mx(i)))/ |
---|
1908 | !-jjh 1 (1.+q(i,mx(i))) |
---|
1909 | tpv(i,k) = (tp(i,k)+tpert(i))*(1._r8+1.608_r8*q(i,mx(i)))/ (1._r8+q(i,mx(i))) |
---|
1910 | buoy(i,k) = tpv(i,k) - tv(i,k) + tiedke_add |
---|
1911 | end if |
---|
1912 | end do |
---|
1913 | end do |
---|
1914 | |
---|
1915 | ! |
---|
1916 | ! define parcel properties at lcl (i.e. level immediately above pl). |
---|
1917 | ! |
---|
1918 | do k = pver,msg + 1,-1 |
---|
1919 | do i=1,ncol |
---|
1920 | if (k == lcl(i) .and. plge600(i)) then |
---|
1921 | tv(i,k) = t(i,k)* (1._r8+1.608_r8*q(i,k))/ (1._r8+q(i,k)) |
---|
1922 | qstp(i,k) = q(i,mx(i)) |
---|
1923 | tp(i,k) = tl(i)* (p(i,k)/pl(i))**(0.2854_r8* (1._r8-0.28_r8*qstp(i,k))) |
---|
1924 | ! estp(i) =exp(a-b/tp(i,k)) |
---|
1925 | ! use of different formulas for est has about 1 g/kg difference |
---|
1926 | ! in qs at t= 300k, and 0.02 g/kg at t=263k, with the formula |
---|
1927 | ! above giving larger qs. |
---|
1928 | ! |
---|
1929 | estp(i) = c1*exp((c2* (tp(i,k)-tfreez))/((tp(i,k)-tfreez)+c3)) |
---|
1930 | |
---|
1931 | qstp(i,k) = eps1*estp(i)/ (p(i,k)-estp(i)) |
---|
1932 | a1(i) = cp / rl + qstp(i,k) * (1._r8+ qstp(i,k) / eps1) * rl * eps1 / & |
---|
1933 | (rd * tp(i,k) ** 2) |
---|
1934 | a2(i) = .5_r8* (qstp(i,k)* (1._r8+2._r8/eps1*qstp(i,k))* & |
---|
1935 | (1._r8+qstp(i,k)/eps1)*eps1**2*rl*rl/ & |
---|
1936 | (rd**2*tp(i,k)**4)-qstp(i,k)* & |
---|
1937 | (1._r8+qstp(i,k)/eps1)*2._r8*eps1*rl/ & |
---|
1938 | (rd*tp(i,k)**3)) |
---|
1939 | a1(i) = 1._r8/a1(i) |
---|
1940 | a2(i) = -a2(i)*a1(i)**3 |
---|
1941 | y(i) = q(i,mx(i)) - qstp(i,k) |
---|
1942 | tp(i,k) = tp(i,k) + a1(i)*y(i) + a2(i)*y(i)**2 |
---|
1943 | ! estp(i) =exp(a-b/tp(i,k)) |
---|
1944 | estp(i) = c1*exp((c2* (tp(i,k)-tfreez))/ ((tp(i,k)-tfreez)+c3)) |
---|
1945 | |
---|
1946 | qstp(i,k) = eps1*estp(i) / (p(i,k)-estp(i)) |
---|
1947 | ! |
---|
1948 | ! buoyancy is increased by 0.5 k in cape calculation. |
---|
1949 | ! dec. 9, 1994 |
---|
1950 | !-jjh tpv(i,k) =tp(i,k)*(1.+1.608*qstp(i,k))/(1.+q(i,mx(i))) |
---|
1951 | ! |
---|
1952 | tpv(i,k) = (tp(i,k)+tpert(i))* (1._r8+1.608_r8*qstp(i,k)) / (1._r8+q(i,mx(i))) |
---|
1953 | buoy(i,k) = tpv(i,k) - tv(i,k) + tiedke_add |
---|
1954 | end if |
---|
1955 | end do |
---|
1956 | end do |
---|
1957 | ! |
---|
1958 | ! main buoyancy calculation. |
---|
1959 | ! |
---|
1960 | do k = pver - 1,msg + 1,-1 |
---|
1961 | do i=1,ncol |
---|
1962 | if (k < lcl(i) .and. plge600(i)) then |
---|
1963 | tv(i,k) = t(i,k)* (1._r8+1.608_r8*q(i,k))/ (1._r8+q(i,k)) |
---|
1964 | qstp(i,k) = qstp(i,k+1) |
---|
1965 | tp(i,k) = tp(i,k+1)* (p(i,k)/p(i,k+1))**(0.2854_r8* (1._r8-0.28_r8*qstp(i,k))) |
---|
1966 | ! estp(i) = exp(a-b/tp(i,k)) |
---|
1967 | estp(i) = c1*exp((c2* (tp(i,k)-tfreez))/((tp(i,k)-tfreez)+c3)) |
---|
1968 | |
---|
1969 | qstp(i,k) = eps1*estp(i)/ (p(i,k)-estp(i)) |
---|
1970 | a1(i) = cp/rl + qstp(i,k)* (1._r8+qstp(i,k)/eps1)*rl*eps1/ (rd*tp(i,k)**2) |
---|
1971 | a2(i) = .5_r8* (qstp(i,k)* (1._r8+2._r8/eps1*qstp(i,k))* & |
---|
1972 | (1._r8+qstp(i,k)/eps1)*eps1**2*rl*rl/ & |
---|
1973 | (rd**2*tp(i,k)**4)-qstp(i,k)* & |
---|
1974 | (1._r8+qstp(i,k)/eps1)*2._r8*eps1*rl/ & |
---|
1975 | (rd*tp(i,k)**3)) |
---|
1976 | a1(i) = 1._r8/a1(i) |
---|
1977 | a2(i) = -a2(i)*a1(i)**3 |
---|
1978 | y(i) = qstp(i,k+1) - qstp(i,k) |
---|
1979 | tp(i,k) = tp(i,k) + a1(i)*y(i) + a2(i)*y(i)**2 |
---|
1980 | ! estp(i) =exp(a-b/tp(i,k)) |
---|
1981 | estp(i) = c1*exp((c2* (tp(i,k)-tfreez))/ ((tp(i,k)-tfreez)+c3)) |
---|
1982 | |
---|
1983 | qstp(i,k) = eps1*estp(i)/ (p(i,k)-estp(i)) |
---|
1984 | !-jjh tpv(i,k) =tp(i,k)*(1.+1.608*qstp(i,k))/ |
---|
1985 | !jt (1.+q(i,mx(i))) |
---|
1986 | tpv(i,k) = (tp(i,k)+tpert(i))* (1._r8+1.608_r8*qstp(i,k))/(1._r8+q(i,mx(i))) |
---|
1987 | buoy(i,k) = tpv(i,k) - tv(i,k) + tiedke_add |
---|
1988 | end if |
---|
1989 | end do |
---|
1990 | end do |
---|
1991 | |
---|
1992 | ! |
---|
1993 | do k = msg + 2,pver |
---|
1994 | do i = 1,ncol |
---|
1995 | if (k < lcl(i) .and. plge600(i)) then |
---|
1996 | if (buoy(i,k+1) > 0._r8 .and. buoy(i,k) <= 0._r8) then |
---|
1997 | knt(i) = min(5,knt(i) + 1) |
---|
1998 | lelten(i,knt(i)) = k |
---|
1999 | end if |
---|
2000 | end if |
---|
2001 | end do |
---|
2002 | end do |
---|
2003 | ! |
---|
2004 | ! calculate convective available potential energy (cape). |
---|
2005 | ! |
---|
2006 | do n = 1,5 |
---|
2007 | do k = msg + 1,pver |
---|
2008 | do i = 1,ncol |
---|
2009 | if (plge600(i) .and. k <= mx(i) .and. k > lelten(i,n)) then |
---|
2010 | capeten(i,n) = capeten(i,n) + rd*buoy(i,k)*log(pf(i,k+1)/pf(i,k)) |
---|
2011 | end if |
---|
2012 | end do |
---|
2013 | end do |
---|
2014 | end do |
---|
2015 | ! |
---|
2016 | ! find maximum cape from all possible tentative capes from |
---|
2017 | ! one sounding, |
---|
2018 | ! and use it as the final cape, april 26, 1995 |
---|
2019 | ! |
---|
2020 | do n = 1,5 |
---|
2021 | do i = 1,ncol |
---|
2022 | if (capeten(i,n) > cape(i)) then |
---|
2023 | cape(i) = capeten(i,n) |
---|
2024 | lel(i) = lelten(i,n) |
---|
2025 | end if |
---|
2026 | end do |
---|
2027 | end do |
---|
2028 | ! |
---|
2029 | ! put lower bound on cape for diagnostic purposes. |
---|
2030 | ! |
---|
2031 | do i = 1,ncol |
---|
2032 | cape(i) = max(cape(i), 0._r8) |
---|
2033 | end do |
---|
2034 | ! |
---|
2035 | return |
---|
2036 | end subroutine buoyan |
---|
2037 | |
---|
2038 | #endif |
---|
2039 | |
---|
2040 | subroutine cldprp(lchnk , & |
---|
2041 | q ,t ,u ,v ,p , & |
---|
2042 | z ,s ,mu ,eu ,du , & |
---|
2043 | md ,ed ,sd ,qd ,mc , & |
---|
2044 | qu ,su ,zf ,qst ,hmn , & |
---|
2045 | hsat ,shat ,ql , & |
---|
2046 | cmeg ,jb ,lel ,jt ,jlcl , & |
---|
2047 | mx ,j0 ,jd ,rl ,il2g , & |
---|
2048 | rd ,grav ,cp ,msg , & |
---|
2049 | pflx ,evp ,cu ,rprd ,limcnv ,landfrac) |
---|
2050 | !----------------------------------------------------------------------- |
---|
2051 | ! |
---|
2052 | ! Purpose: |
---|
2053 | ! <Say what the routine does> |
---|
2054 | ! |
---|
2055 | ! Method: |
---|
2056 | ! may 09/91 - guang jun zhang, m.lazare, n.mcfarlane. |
---|
2057 | ! original version cldprop. |
---|
2058 | ! |
---|
2059 | ! Author: See above, modified by P. Rasch |
---|
2060 | ! This is contributed code not fully standardized by the CCM core group. |
---|
2061 | ! |
---|
2062 | ! this code is very much rougher than virtually anything else in the CCM |
---|
2063 | ! there are debug statements left strewn about and code segments disabled |
---|
2064 | ! these are to facilitate future development. We expect to release a |
---|
2065 | ! cleaner code in a future release |
---|
2066 | ! |
---|
2067 | ! the documentation has been enhanced to the degree that we are able |
---|
2068 | ! |
---|
2069 | !----------------------------------------------------------------------- |
---|
2070 | |
---|
2071 | implicit none |
---|
2072 | |
---|
2073 | !------------------------------------------------------------------------------ |
---|
2074 | ! |
---|
2075 | ! Input arguments |
---|
2076 | ! |
---|
2077 | integer, intent(in) :: lchnk ! chunk identifier |
---|
2078 | |
---|
2079 | real(r8), intent(in) :: q(pcols,pver) ! spec. humidity of env |
---|
2080 | real(r8), intent(in) :: t(pcols,pver) ! temp of env |
---|
2081 | real(r8), intent(in) :: p(pcols,pver) ! pressure of env |
---|
2082 | real(r8), intent(in) :: z(pcols,pver) ! height of env |
---|
2083 | real(r8), intent(in) :: s(pcols,pver) ! normalized dry static energy of env |
---|
2084 | real(r8), intent(in) :: zf(pcols,pverp) ! height of interfaces |
---|
2085 | real(r8), intent(in) :: u(pcols,pver) ! zonal velocity of env |
---|
2086 | real(r8), intent(in) :: v(pcols,pver) ! merid. velocity of env |
---|
2087 | real(r8), intent(in) :: landfrac(pcols) ! RBN Landfrac |
---|
2088 | |
---|
2089 | integer, intent(in) :: jb(pcols) ! updraft base level |
---|
2090 | integer, intent(in) :: lel(pcols) ! updraft launch level |
---|
2091 | integer, intent(out) :: jt(pcols) ! updraft plume top |
---|
2092 | integer, intent(out) :: jlcl(pcols) ! updraft lifting cond level |
---|
2093 | integer, intent(in) :: mx(pcols) ! updraft base level (same is jb) |
---|
2094 | integer, intent(out) :: j0(pcols) ! level where updraft begins detraining |
---|
2095 | integer, intent(out) :: jd(pcols) ! level of downdraft |
---|
2096 | integer, intent(in) :: limcnv ! convection limiting level |
---|
2097 | integer, intent(in) :: il2g !CORE GROUP REMOVE |
---|
2098 | integer, intent(in) :: msg ! missing moisture vals (always 0) |
---|
2099 | real(r8), intent(in) :: rl ! latent heat of vap |
---|
2100 | real(r8), intent(in) :: shat(pcols,pver) ! interface values of dry stat energy |
---|
2101 | ! |
---|
2102 | ! output |
---|
2103 | ! |
---|
2104 | real(r8), intent(out) :: rprd(pcols,pver) ! rate of production of precip at that layer |
---|
2105 | real(r8), intent(out) :: du(pcols,pver) ! detrainement rate of updraft |
---|
2106 | real(r8), intent(out) :: ed(pcols,pver) ! entrainment rate of downdraft |
---|
2107 | real(r8), intent(out) :: eu(pcols,pver) ! entrainment rate of updraft |
---|
2108 | real(r8), intent(out) :: hmn(pcols,pver) ! moist stat energy of env |
---|
2109 | real(r8), intent(out) :: hsat(pcols,pver) ! sat moist stat energy of env |
---|
2110 | real(r8), intent(out) :: mc(pcols,pver) ! net mass flux |
---|
2111 | real(r8), intent(out) :: md(pcols,pver) ! downdraft mass flux |
---|
2112 | real(r8), intent(out) :: mu(pcols,pver) ! updraft mass flux |
---|
2113 | real(r8), intent(out) :: pflx(pcols,pverp) ! precipitation flux thru layer |
---|
2114 | real(r8), intent(out) :: qd(pcols,pver) ! spec humidity of downdraft |
---|
2115 | real(r8), intent(out) :: ql(pcols,pver) ! liq water of updraft |
---|
2116 | real(r8), intent(out) :: qst(pcols,pver) ! saturation spec humidity of env. |
---|
2117 | real(r8), intent(out) :: qu(pcols,pver) ! spec hum of updraft |
---|
2118 | real(r8), intent(out) :: sd(pcols,pver) ! normalized dry stat energy of downdraft |
---|
2119 | real(r8), intent(out) :: su(pcols,pver) ! normalized dry stat energy of updraft |
---|
2120 | |
---|
2121 | |
---|
2122 | real(r8) rd ! gas constant for dry air |
---|
2123 | real(r8) grav ! gravity |
---|
2124 | real(r8) cp ! heat capacity of dry air |
---|
2125 | |
---|
2126 | ! |
---|
2127 | ! Local workspace |
---|
2128 | ! |
---|
2129 | real(r8) gamma(pcols,pver) |
---|
2130 | real(r8) dz(pcols,pver) |
---|
2131 | real(r8) iprm(pcols,pver) |
---|
2132 | real(r8) hu(pcols,pver) |
---|
2133 | real(r8) hd(pcols,pver) |
---|
2134 | real(r8) eps(pcols,pver) |
---|
2135 | real(r8) f(pcols,pver) |
---|
2136 | real(r8) k1(pcols,pver) |
---|
2137 | real(r8) i2(pcols,pver) |
---|
2138 | real(r8) ihat(pcols,pver) |
---|
2139 | real(r8) i3(pcols,pver) |
---|
2140 | real(r8) idag(pcols,pver) |
---|
2141 | real(r8) i4(pcols,pver) |
---|
2142 | real(r8) qsthat(pcols,pver) |
---|
2143 | real(r8) hsthat(pcols,pver) |
---|
2144 | real(r8) gamhat(pcols,pver) |
---|
2145 | real(r8) cu(pcols,pver) |
---|
2146 | real(r8) evp(pcols,pver) |
---|
2147 | real(r8) cmeg(pcols,pver) |
---|
2148 | real(r8) qds(pcols,pver) |
---|
2149 | ! RBN For c0mask |
---|
2150 | real(r8) c0mask(pcols) |
---|
2151 | real(r8) hmin(pcols) |
---|
2152 | real(r8) expdif(pcols) |
---|
2153 | real(r8) expnum(pcols) |
---|
2154 | real(r8) ftemp(pcols) |
---|
2155 | real(r8) eps0(pcols) |
---|
2156 | real(r8) rmue(pcols) |
---|
2157 | real(r8) zuef(pcols) |
---|
2158 | real(r8) zdef(pcols) |
---|
2159 | real(r8) epsm(pcols) |
---|
2160 | real(r8) ratmjb(pcols) |
---|
2161 | real(r8) est(pcols) |
---|
2162 | real(r8) totpcp(pcols) |
---|
2163 | real(r8) totevp(pcols) |
---|
2164 | real(r8) alfa(pcols) |
---|
2165 | real(r8) ql1 |
---|
2166 | real(r8) tu |
---|
2167 | real(r8) estu |
---|
2168 | real(r8) qstu |
---|
2169 | |
---|
2170 | real(r8) small |
---|
2171 | real(r8) mdt |
---|
2172 | |
---|
2173 | integer khighest |
---|
2174 | integer klowest |
---|
2175 | integer kount |
---|
2176 | integer i,k |
---|
2177 | |
---|
2178 | logical doit(pcols) |
---|
2179 | logical done(pcols) |
---|
2180 | ! |
---|
2181 | !------------------------------------------------------------------------------ |
---|
2182 | ! |
---|
2183 | do i = 1,il2g |
---|
2184 | ftemp(i) = 0._r8 |
---|
2185 | expnum(i) = 0._r8 |
---|
2186 | expdif(i) = 0._r8 |
---|
2187 | c0mask(i) = c0_ocn * (1._r8-landfrac(i)) + c0_lnd * landfrac(i) |
---|
2188 | end do |
---|
2189 | ! |
---|
2190 | !jr Change from msg+1 to 1 to prevent blowup |
---|
2191 | ! |
---|
2192 | do k = 1,pver |
---|
2193 | do i = 1,il2g |
---|
2194 | dz(i,k) = zf(i,k) - zf(i,k+1) |
---|
2195 | end do |
---|
2196 | end do |
---|
2197 | |
---|
2198 | ! |
---|
2199 | ! initialize many output and work variables to zero |
---|
2200 | ! |
---|
2201 | pflx(:il2g,1) = 0 |
---|
2202 | |
---|
2203 | do k = 1,pver |
---|
2204 | do i = 1,il2g |
---|
2205 | k1(i,k) = 0._r8 |
---|
2206 | i2(i,k) = 0._r8 |
---|
2207 | i3(i,k) = 0._r8 |
---|
2208 | i4(i,k) = 0._r8 |
---|
2209 | mu(i,k) = 0._r8 |
---|
2210 | f(i,k) = 0._r8 |
---|
2211 | eps(i,k) = 0._r8 |
---|
2212 | eu(i,k) = 0._r8 |
---|
2213 | du(i,k) = 0._r8 |
---|
2214 | ql(i,k) = 0._r8 |
---|
2215 | cu(i,k) = 0._r8 |
---|
2216 | evp(i,k) = 0._r8 |
---|
2217 | cmeg(i,k) = 0._r8 |
---|
2218 | qds(i,k) = q(i,k) |
---|
2219 | md(i,k) = 0._r8 |
---|
2220 | ed(i,k) = 0._r8 |
---|
2221 | sd(i,k) = s(i,k) |
---|
2222 | qd(i,k) = q(i,k) |
---|
2223 | mc(i,k) = 0._r8 |
---|
2224 | qu(i,k) = q(i,k) |
---|
2225 | su(i,k) = s(i,k) |
---|
2226 | ! est(i)=exp(a-b/t(i,k)) |
---|
2227 | est(i) = c1*exp((c2* (t(i,k)-tfreez))/((t(i,k)-tfreez)+c3)) |
---|
2228 | !++bee |
---|
2229 | if ( p(i,k)-est(i) > 0._r8 ) then |
---|
2230 | qst(i,k) = eps1*est(i)/ (p(i,k)-est(i)) |
---|
2231 | else |
---|
2232 | qst(i,k) = 1.0_r8 |
---|
2233 | end if |
---|
2234 | !--bee |
---|
2235 | gamma(i,k) = qst(i,k)*(1._r8 + qst(i,k)/eps1)*eps1*rl/(rd*t(i,k)**2)*rl/cp |
---|
2236 | hmn(i,k) = cp*t(i,k) + grav*z(i,k) + rl*q(i,k) |
---|
2237 | hsat(i,k) = cp*t(i,k) + grav*z(i,k) + rl*qst(i,k) |
---|
2238 | hu(i,k) = hmn(i,k) |
---|
2239 | hd(i,k) = hmn(i,k) |
---|
2240 | rprd(i,k) = 0._r8 |
---|
2241 | end do |
---|
2242 | end do |
---|
2243 | ! |
---|
2244 | !jr Set to zero things which make this routine blow up |
---|
2245 | ! |
---|
2246 | do k=1,msg |
---|
2247 | do i=1,il2g |
---|
2248 | rprd(i,k) = 0._r8 |
---|
2249 | end do |
---|
2250 | end do |
---|
2251 | ! |
---|
2252 | ! interpolate the layer values of qst, hsat and gamma to |
---|
2253 | ! layer interfaces |
---|
2254 | ! |
---|
2255 | do i = 1,il2g |
---|
2256 | hsthat(i,msg+1) = hsat(i,msg+1) |
---|
2257 | qsthat(i,msg+1) = qst(i,msg+1) |
---|
2258 | gamhat(i,msg+1) = gamma(i,msg+1) |
---|
2259 | totpcp(i) = 0._r8 |
---|
2260 | totevp(i) = 0._r8 |
---|
2261 | end do |
---|
2262 | do k = msg + 2,pver |
---|
2263 | do i = 1,il2g |
---|
2264 | if (abs(qst(i,k-1)-qst(i,k)) > 1.E-6_r8) then |
---|
2265 | qsthat(i,k) = log(qst(i,k-1)/qst(i,k))*qst(i,k-1)*qst(i,k)/ (qst(i,k-1)-qst(i,k)) |
---|
2266 | else |
---|
2267 | qsthat(i,k) = qst(i,k) |
---|
2268 | end if |
---|
2269 | hsthat(i,k) = cp*shat(i,k) + rl*qsthat(i,k) |
---|
2270 | if (abs(gamma(i,k-1)-gamma(i,k)) > 1.E-6_r8) then |
---|
2271 | gamhat(i,k) = log(gamma(i,k-1)/gamma(i,k))*gamma(i,k-1)*gamma(i,k)/ & |
---|
2272 | (gamma(i,k-1)-gamma(i,k)) |
---|
2273 | else |
---|
2274 | gamhat(i,k) = gamma(i,k) |
---|
2275 | end if |
---|
2276 | end do |
---|
2277 | end do |
---|
2278 | ! |
---|
2279 | ! initialize cloud top to highest plume top. |
---|
2280 | !jr changed hard-wired 4 to limcnv+1 (not to exceed pver) |
---|
2281 | ! |
---|
2282 | jt(:) = pver |
---|
2283 | do i = 1,il2g |
---|
2284 | jt(i) = max(lel(i),limcnv+1) |
---|
2285 | jt(i) = min(jt(i),pver) |
---|
2286 | jd(i) = pver |
---|
2287 | jlcl(i) = lel(i) |
---|
2288 | hmin(i) = 1.E6_r8 |
---|
2289 | end do |
---|
2290 | ! |
---|
2291 | ! find the level of minimum hsat, where detrainment starts |
---|
2292 | ! |
---|
2293 | do k = msg + 1,pver |
---|
2294 | do i = 1,il2g |
---|
2295 | if (hsat(i,k) <= hmin(i) .and. k >= jt(i) .and. k <= jb(i)) then |
---|
2296 | hmin(i) = hsat(i,k) |
---|
2297 | j0(i) = k |
---|
2298 | end if |
---|
2299 | end do |
---|
2300 | end do |
---|
2301 | do i = 1,il2g |
---|
2302 | j0(i) = min(j0(i),jb(i)-2) |
---|
2303 | j0(i) = max(j0(i),jt(i)+2) |
---|
2304 | ! |
---|
2305 | ! Fix from Guang Zhang to address out of bounds array reference |
---|
2306 | ! |
---|
2307 | j0(i) = min(j0(i),pver) |
---|
2308 | end do |
---|
2309 | ! |
---|
2310 | ! Initialize certain arrays inside cloud |
---|
2311 | ! |
---|
2312 | do k = msg + 1,pver |
---|
2313 | do i = 1,il2g |
---|
2314 | if (k >= jt(i) .and. k <= jb(i)) then |
---|
2315 | hu(i,k) = hmn(i,mx(i)) + cp*tiedke_add |
---|
2316 | su(i,k) = s(i,mx(i)) + tiedke_add |
---|
2317 | end if |
---|
2318 | end do |
---|
2319 | end do |
---|
2320 | ! |
---|
2321 | ! ********************************************************* |
---|
2322 | ! compute taylor series for approximate eps(z) below |
---|
2323 | ! ********************************************************* |
---|
2324 | ! |
---|
2325 | do k = pver - 1,msg + 1,-1 |
---|
2326 | do i = 1,il2g |
---|
2327 | if (k < jb(i) .and. k >= jt(i)) then |
---|
2328 | k1(i,k) = k1(i,k+1) + (hmn(i,mx(i))-hmn(i,k))*dz(i,k) |
---|
2329 | ihat(i,k) = 0.5_r8* (k1(i,k+1)+k1(i,k)) |
---|
2330 | i2(i,k) = i2(i,k+1) + ihat(i,k)*dz(i,k) |
---|
2331 | idag(i,k) = 0.5_r8* (i2(i,k+1)+i2(i,k)) |
---|
2332 | i3(i,k) = i3(i,k+1) + idag(i,k)*dz(i,k) |
---|
2333 | iprm(i,k) = 0.5_r8* (i3(i,k+1)+i3(i,k)) |
---|
2334 | i4(i,k) = i4(i,k+1) + iprm(i,k)*dz(i,k) |
---|
2335 | end if |
---|
2336 | end do |
---|
2337 | end do |
---|
2338 | ! |
---|
2339 | ! re-initialize hmin array for ensuing calculation. |
---|
2340 | ! |
---|
2341 | do i = 1,il2g |
---|
2342 | hmin(i) = 1.E6_r8 |
---|
2343 | end do |
---|
2344 | do k = msg + 1,pver |
---|
2345 | do i = 1,il2g |
---|
2346 | if (k >= j0(i) .and. k <= jb(i) .and. hmn(i,k) <= hmin(i)) then |
---|
2347 | hmin(i) = hmn(i,k) |
---|
2348 | expdif(i) = hmn(i,mx(i)) - hmin(i) |
---|
2349 | end if |
---|
2350 | end do |
---|
2351 | end do |
---|
2352 | ! |
---|
2353 | ! ********************************************************* |
---|
2354 | ! compute approximate eps(z) using above taylor series |
---|
2355 | ! ********************************************************* |
---|
2356 | ! |
---|
2357 | do k = msg + 2,pver |
---|
2358 | do i = 1,il2g |
---|
2359 | expnum(i) = 0._r8 |
---|
2360 | ftemp(i) = 0._r8 |
---|
2361 | if (k < jt(i) .or. k >= jb(i)) then |
---|
2362 | k1(i,k) = 0._r8 |
---|
2363 | expnum(i) = 0._r8 |
---|
2364 | else |
---|
2365 | expnum(i) = hmn(i,mx(i)) - (hsat(i,k-1)*(zf(i,k)-z(i,k)) + & |
---|
2366 | hsat(i,k)* (z(i,k-1)-zf(i,k)))/(z(i,k-1)-z(i,k)) |
---|
2367 | end if |
---|
2368 | if ((expdif(i) > 100._r8 .and. expnum(i) > 0._r8) .and. & |
---|
2369 | k1(i,k) > expnum(i)*dz(i,k)) then |
---|
2370 | ftemp(i) = expnum(i)/k1(i,k) |
---|
2371 | f(i,k) = ftemp(i) + i2(i,k)/k1(i,k)*ftemp(i)**2 + & |
---|
2372 | (2._r8*i2(i,k)**2-k1(i,k)*i3(i,k))/k1(i,k)**2* & |
---|
2373 | ftemp(i)**3 + (-5._r8*k1(i,k)*i2(i,k)*i3(i,k)+ & |
---|
2374 | 5._r8*i2(i,k)**3+k1(i,k)**2*i4(i,k))/ & |
---|
2375 | k1(i,k)**3*ftemp(i)**4 |
---|
2376 | f(i,k) = max(f(i,k),0._r8) |
---|
2377 | f(i,k) = min(f(i,k),0.0002_r8) |
---|
2378 | end if |
---|
2379 | end do |
---|
2380 | end do |
---|
2381 | do i = 1,il2g |
---|
2382 | if (j0(i) < jb(i)) then |
---|
2383 | if (f(i,j0(i)) < 1.E-6_r8 .and. f(i,j0(i)+1) > f(i,j0(i))) j0(i) = j0(i) + 1 |
---|
2384 | end if |
---|
2385 | end do |
---|
2386 | do k = msg + 2,pver |
---|
2387 | do i = 1,il2g |
---|
2388 | if (k >= jt(i) .and. k <= j0(i)) then |
---|
2389 | f(i,k) = max(f(i,k),f(i,k-1)) |
---|
2390 | end if |
---|
2391 | end do |
---|
2392 | end do |
---|
2393 | do i = 1,il2g |
---|
2394 | eps0(i) = f(i,j0(i)) |
---|
2395 | eps(i,jb(i)) = eps0(i) |
---|
2396 | end do |
---|
2397 | ! |
---|
2398 | ! This is set to match the Rasch and Kristjansson paper |
---|
2399 | ! |
---|
2400 | do k = pver,msg + 1,-1 |
---|
2401 | do i = 1,il2g |
---|
2402 | if (k >= j0(i) .and. k <= jb(i)) then |
---|
2403 | eps(i,k) = f(i,j0(i)) |
---|
2404 | end if |
---|
2405 | end do |
---|
2406 | end do |
---|
2407 | do k = pver,msg + 1,-1 |
---|
2408 | do i = 1,il2g |
---|
2409 | if (k < j0(i) .and. k >= jt(i)) eps(i,k) = f(i,k) |
---|
2410 | end do |
---|
2411 | end do |
---|
2412 | ! |
---|
2413 | ! specify the updraft mass flux mu, entrainment eu, detrainment du |
---|
2414 | ! and moist static energy hu. |
---|
2415 | ! here and below mu, eu,du, md and ed are all normalized by mb |
---|
2416 | ! |
---|
2417 | do i = 1,il2g |
---|
2418 | if (eps0(i) > 0._r8) then |
---|
2419 | mu(i,jb(i)) = 1._r8 |
---|
2420 | eu(i,jb(i)) = mu(i,jb(i))/dz(i,jb(i)) |
---|
2421 | end if |
---|
2422 | end do |
---|
2423 | do k = pver,msg + 1,-1 |
---|
2424 | do i = 1,il2g |
---|
2425 | if (eps0(i) > 0._r8 .and. (k >= jt(i) .and. k < jb(i))) then |
---|
2426 | zuef(i) = zf(i,k) - zf(i,jb(i)) |
---|
2427 | rmue(i) = (1._r8/eps0(i))* (exp(eps(i,k+1)*zuef(i))-1._r8)/zuef(i) |
---|
2428 | mu(i,k) = (1._r8/eps0(i))* (exp(eps(i,k )*zuef(i))-1._r8)/zuef(i) |
---|
2429 | eu(i,k) = (rmue(i)-mu(i,k+1))/dz(i,k) |
---|
2430 | du(i,k) = (rmue(i)-mu(i,k))/dz(i,k) |
---|
2431 | end if |
---|
2432 | end do |
---|
2433 | end do |
---|
2434 | ! |
---|
2435 | khighest = pverp |
---|
2436 | klowest = 1 |
---|
2437 | do i=1,il2g |
---|
2438 | khighest = min(khighest,lel(i)) |
---|
2439 | klowest = max(klowest,jb(i)) |
---|
2440 | end do |
---|
2441 | do k = klowest-1,khighest,-1 |
---|
2442 | !cdir$ ivdep |
---|
2443 | do i = 1,il2g |
---|
2444 | if (k <= jb(i)-1 .and. k >= lel(i) .and. eps0(i) > 0._r8) then |
---|
2445 | if (mu(i,k) < 0.01_r8) then |
---|
2446 | hu(i,k) = hu(i,jb(i)) |
---|
2447 | mu(i,k) = 0._r8 |
---|
2448 | eu(i,k) = 0._r8 |
---|
2449 | du(i,k) = mu(i,k+1)/dz(i,k) |
---|
2450 | else |
---|
2451 | hu(i,k) = mu(i,k+1)/mu(i,k)*hu(i,k+1) + & |
---|
2452 | dz(i,k)/mu(i,k)* (eu(i,k)*hmn(i,k)- du(i,k)*hsat(i,k)) |
---|
2453 | end if |
---|
2454 | end if |
---|
2455 | end do |
---|
2456 | end do |
---|
2457 | ! |
---|
2458 | ! reset cloud top index beginning from two layers above the |
---|
2459 | ! cloud base (i.e. if cloud is only one layer thick, top is not reset |
---|
2460 | ! |
---|
2461 | do i=1,il2g |
---|
2462 | doit(i) = .true. |
---|
2463 | end do |
---|
2464 | do k=klowest-2,khighest-1,-1 |
---|
2465 | do i=1,il2g |
---|
2466 | if (doit(i) .and. k <= jb(i)-2 .and. k >= lel(i)-1) then |
---|
2467 | if (hu(i,k) <= hsthat(i,k) .and. hu(i,k+1) > hsthat(i,k+1) & |
---|
2468 | .and. mu(i,k) >= 0.02_r8) then |
---|
2469 | if (hu(i,k)-hsthat(i,k) < -2000._r8) then |
---|
2470 | jt(i) = k + 1 |
---|
2471 | doit(i) = .false. |
---|
2472 | else |
---|
2473 | jt(i) = k |
---|
2474 | if (eps0(i) <= 0._r8) doit(i) = .false. |
---|
2475 | end if |
---|
2476 | else if (hu(i,k) > hu(i,jb(i)) .or. mu(i,k) < 0.01_r8) then |
---|
2477 | jt(i) = k + 1 |
---|
2478 | doit(i) = .false. |
---|
2479 | end if |
---|
2480 | end if |
---|
2481 | end do |
---|
2482 | end do |
---|
2483 | do k = pver,msg + 1,-1 |
---|
2484 | !cdir$ ivdep |
---|
2485 | do i = 1,il2g |
---|
2486 | if (k >= lel(i) .and. k <= jt(i) .and. eps0(i) > 0._r8) then |
---|
2487 | mu(i,k) = 0._r8 |
---|
2488 | eu(i,k) = 0._r8 |
---|
2489 | du(i,k) = 0._r8 |
---|
2490 | hu(i,k) = hu(i,jb(i)) |
---|
2491 | end if |
---|
2492 | if (k == jt(i) .and. eps0(i) > 0._r8) then |
---|
2493 | du(i,k) = mu(i,k+1)/dz(i,k) |
---|
2494 | eu(i,k) = 0._r8 |
---|
2495 | mu(i,k) = 0._r8 |
---|
2496 | end if |
---|
2497 | end do |
---|
2498 | end do |
---|
2499 | ! |
---|
2500 | ! specify downdraft properties (no downdrafts if jd.ge.jb). |
---|
2501 | ! scale down downward mass flux profile so that net flux |
---|
2502 | ! (up-down) at cloud base in not negative. |
---|
2503 | ! |
---|
2504 | do i = 1,il2g |
---|
2505 | ! |
---|
2506 | ! in normal downdraft strength run alfa=0.2. In test4 alfa=0.1 |
---|
2507 | ! |
---|
2508 | alfa(i) = 0.1_r8 |
---|
2509 | jt(i) = min(jt(i),jb(i)-1) |
---|
2510 | jd(i) = max(j0(i),jt(i)+1) |
---|
2511 | jd(i) = min(jd(i),jb(i)) |
---|
2512 | hd(i,jd(i)) = hmn(i,jd(i)-1) |
---|
2513 | if (jd(i) < jb(i) .and. eps0(i) > 0._r8) then |
---|
2514 | epsm(i) = eps0(i) |
---|
2515 | md(i,jd(i)) = -alfa(i)*epsm(i)/eps0(i) |
---|
2516 | end if |
---|
2517 | end do |
---|
2518 | do k = msg + 1,pver |
---|
2519 | do i = 1,il2g |
---|
2520 | if ((k > jd(i) .and. k <= jb(i)) .and. eps0(i) > 0._r8) then |
---|
2521 | zdef(i) = zf(i,jd(i)) - zf(i,k) |
---|
2522 | md(i,k) = -alfa(i)/ (2._r8*eps0(i))*(exp(2._r8*epsm(i)*zdef(i))-1._r8)/zdef(i) |
---|
2523 | end if |
---|
2524 | end do |
---|
2525 | end do |
---|
2526 | do k = msg + 1,pver |
---|
2527 | do i = 1,il2g |
---|
2528 | if ((k >= jt(i) .and. k <= jb(i)) .and. eps0(i) > 0._r8 .and. jd(i) < jb(i)) then |
---|
2529 | ratmjb(i) = min(abs(mu(i,jb(i))/md(i,jb(i))),1._r8) |
---|
2530 | md(i,k) = md(i,k)*ratmjb(i) |
---|
2531 | end if |
---|
2532 | end do |
---|
2533 | end do |
---|
2534 | |
---|
2535 | small = 1.e-20_r8 |
---|
2536 | do k = msg + 1,pver |
---|
2537 | do i = 1,il2g |
---|
2538 | if ((k >= jt(i) .and. k <= pver) .and. eps0(i) > 0._r8) then |
---|
2539 | ed(i,k-1) = (md(i,k-1)-md(i,k))/dz(i,k-1) |
---|
2540 | mdt = min(md(i,k),-small) |
---|
2541 | hd(i,k) = (md(i,k-1)*hd(i,k-1) - dz(i,k-1)*ed(i,k-1)*hmn(i,k-1))/mdt |
---|
2542 | end if |
---|
2543 | end do |
---|
2544 | end do |
---|
2545 | ! |
---|
2546 | ! calculate updraft and downdraft properties. |
---|
2547 | ! |
---|
2548 | do k = msg + 2,pver |
---|
2549 | do i = 1,il2g |
---|
2550 | if ((k >= jd(i) .and. k <= jb(i)) .and. eps0(i) > 0._r8 .and. jd(i) < jb(i)) then |
---|
2551 | qds(i,k) = qsthat(i,k) + gamhat(i,k)*(hd(i,k)-hsthat(i,k))/ & |
---|
2552 | (rl*(1._r8 + gamhat(i,k))) |
---|
2553 | end if |
---|
2554 | end do |
---|
2555 | end do |
---|
2556 | ! |
---|
2557 | do i = 1,il2g |
---|
2558 | done(i) = .false. |
---|
2559 | end do |
---|
2560 | kount = 0 |
---|
2561 | do k = pver,msg + 2,-1 |
---|
2562 | do i = 1,il2g |
---|
2563 | if (( .not. done(i) .and. k > jt(i) .and. k < jb(i)) .and. eps0(i) > 0._r8) then |
---|
2564 | su(i,k) = mu(i,k+1)/mu(i,k)*su(i,k+1) + & |
---|
2565 | dz(i,k)/mu(i,k)* (eu(i,k)-du(i,k))*s(i,k) |
---|
2566 | qu(i,k) = mu(i,k+1)/mu(i,k)*qu(i,k+1) + dz(i,k)/mu(i,k)* (eu(i,k)*q(i,k)- & |
---|
2567 | du(i,k)*qst(i,k)) |
---|
2568 | tu = su(i,k) - grav/cp*zf(i,k) |
---|
2569 | estu = c1*exp((c2* (tu-tfreez))/ ((tu-tfreez)+c3)) |
---|
2570 | qstu = eps1*estu/ ((p(i,k)+p(i,k-1))/2._r8-estu) |
---|
2571 | if (qu(i,k) >= qstu) then |
---|
2572 | jlcl(i) = k |
---|
2573 | kount = kount + 1 |
---|
2574 | done(i) = .true. |
---|
2575 | end if |
---|
2576 | end if |
---|
2577 | end do |
---|
2578 | if (kount >= il2g) goto 690 |
---|
2579 | end do |
---|
2580 | 690 continue |
---|
2581 | do k = msg + 2,pver |
---|
2582 | do i = 1,il2g |
---|
2583 | if (k == jb(i) .and. eps0(i) > 0._r8) then |
---|
2584 | qu(i,k) = q(i,mx(i)) |
---|
2585 | su(i,k) = (hu(i,k)-rl*qu(i,k))/cp |
---|
2586 | end if |
---|
2587 | if ((k > jt(i) .and. k <= jlcl(i)) .and. eps0(i) > 0._r8) then |
---|
2588 | su(i,k) = shat(i,k) + (hu(i,k)-hsthat(i,k))/(cp* (1._r8+gamhat(i,k))) |
---|
2589 | qu(i,k) = qsthat(i,k) + gamhat(i,k)*(hu(i,k)-hsthat(i,k))/ & |
---|
2590 | (rl* (1._r8+gamhat(i,k))) |
---|
2591 | end if |
---|
2592 | end do |
---|
2593 | end do |
---|
2594 | |
---|
2595 | ! compute condensation in updraft |
---|
2596 | do k = pver,msg + 2,-1 |
---|
2597 | do i = 1,il2g |
---|
2598 | if (k >= jt(i) .and. k < jb(i) .and. eps0(i) > 0._r8) then |
---|
2599 | cu(i,k) = ((mu(i,k)*su(i,k)-mu(i,k+1)*su(i,k+1))/ & |
---|
2600 | dz(i,k)- (eu(i,k)-du(i,k))*s(i,k))/(rl/cp) |
---|
2601 | if (k == jt(i)) cu(i,k) = 0._r8 |
---|
2602 | cu(i,k) = max(0._r8,cu(i,k)) |
---|
2603 | end if |
---|
2604 | end do |
---|
2605 | end do |
---|
2606 | |
---|
2607 | ! compute condensed liquid, rain production rate |
---|
2608 | ! accumulate total precipitation (condensation - detrainment of liquid) |
---|
2609 | ! Note ql1 = ql(k) + rprd(k)*dz(k)/mu(k) |
---|
2610 | ! The differencing is somewhat strange (e.g. du(i,k)*ql(i,k+1)) but is |
---|
2611 | ! consistently applied. |
---|
2612 | ! mu, ql are interface quantities |
---|
2613 | ! cu, du, eu, rprd are midpoint quantites |
---|
2614 | do k = pver,msg + 2,-1 |
---|
2615 | do i = 1,il2g |
---|
2616 | rprd(i,k) = 0._r8 |
---|
2617 | if (k >= jt(i) .and. k < jb(i) .and. eps0(i) > 0._r8 .and. mu(i,k) >= 0.0_r8) then |
---|
2618 | if (mu(i,k) > 0._r8) then |
---|
2619 | ql1 = 1._r8/mu(i,k)* (mu(i,k+1)*ql(i,k+1)- & |
---|
2620 | dz(i,k)*du(i,k)*ql(i,k+1)+dz(i,k)*cu(i,k)) |
---|
2621 | ql(i,k) = ql1/ (1._r8+dz(i,k)*c0mask(i)) |
---|
2622 | else |
---|
2623 | ql(i,k) = 0._r8 |
---|
2624 | end if |
---|
2625 | totpcp(i) = totpcp(i) + dz(i,k)*(cu(i,k)-du(i,k)*ql(i,k+1)) |
---|
2626 | rprd(i,k) = c0mask(i)*mu(i,k)*ql(i,k) |
---|
2627 | end if |
---|
2628 | end do |
---|
2629 | end do |
---|
2630 | ! |
---|
2631 | do i = 1,il2g |
---|
2632 | qd(i,jd(i)) = qds(i,jd(i)) |
---|
2633 | sd(i,jd(i)) = (hd(i,jd(i)) - rl*qd(i,jd(i)))/cp |
---|
2634 | end do |
---|
2635 | ! |
---|
2636 | do k = msg + 2,pver |
---|
2637 | do i = 1,il2g |
---|
2638 | if (k >= jd(i) .and. k < jb(i) .and. eps0(i) > 0._r8) then |
---|
2639 | qd(i,k+1) = qds(i,k+1) |
---|
2640 | evp(i,k) = -ed(i,k)*q(i,k) + (md(i,k)*qd(i,k)-md(i,k+1)*qd(i,k+1))/dz(i,k) |
---|
2641 | evp(i,k) = max(evp(i,k),0._r8) |
---|
2642 | mdt = min(md(i,k+1),-small) |
---|
2643 | sd(i,k+1) = ((rl/cp*evp(i,k)-ed(i,k)*s(i,k))*dz(i,k) + md(i,k)*sd(i,k))/mdt |
---|
2644 | totevp(i) = totevp(i) - dz(i,k)*ed(i,k)*q(i,k) |
---|
2645 | end if |
---|
2646 | end do |
---|
2647 | end do |
---|
2648 | do i = 1,il2g |
---|
2649 | !*guang totevp(i) = totevp(i) + md(i,jd(i))*q(i,jd(i)-1) - |
---|
2650 | totevp(i) = totevp(i) + md(i,jd(i))*qd(i,jd(i)) - md(i,jb(i))*qd(i,jb(i)) |
---|
2651 | end do |
---|
2652 | !!$ if (.true.) then |
---|
2653 | if (.false.) then |
---|
2654 | do i = 1,il2g |
---|
2655 | k = jb(i) |
---|
2656 | if (eps0(i) > 0._r8) then |
---|
2657 | evp(i,k) = -ed(i,k)*q(i,k) + (md(i,k)*qd(i,k))/dz(i,k) |
---|
2658 | evp(i,k) = max(evp(i,k),0._r8) |
---|
2659 | totevp(i) = totevp(i) - dz(i,k)*ed(i,k)*q(i,k) |
---|
2660 | end if |
---|
2661 | end do |
---|
2662 | endif |
---|
2663 | |
---|
2664 | do i = 1,il2g |
---|
2665 | totpcp(i) = max(totpcp(i),0._r8) |
---|
2666 | totevp(i) = max(totevp(i),0._r8) |
---|
2667 | end do |
---|
2668 | ! |
---|
2669 | do k = msg + 2,pver |
---|
2670 | do i = 1,il2g |
---|
2671 | if (totevp(i) > 0._r8 .and. totpcp(i) > 0._r8) then |
---|
2672 | md(i,k) = md (i,k)*min(1._r8, totpcp(i)/(totevp(i)+totpcp(i))) |
---|
2673 | ed(i,k) = ed (i,k)*min(1._r8, totpcp(i)/(totevp(i)+totpcp(i))) |
---|
2674 | evp(i,k) = evp(i,k)*min(1._r8, totpcp(i)/(totevp(i)+totpcp(i))) |
---|
2675 | else |
---|
2676 | md(i,k) = 0._r8 |
---|
2677 | ed(i,k) = 0._r8 |
---|
2678 | evp(i,k) = 0._r8 |
---|
2679 | end if |
---|
2680 | ! cmeg is the cloud water condensed - rain water evaporated |
---|
2681 | ! rprd is the cloud water converted to rain - (rain evaporated) |
---|
2682 | cmeg(i,k) = cu(i,k) - evp(i,k) |
---|
2683 | rprd(i,k) = rprd(i,k)-evp(i,k) |
---|
2684 | end do |
---|
2685 | end do |
---|
2686 | |
---|
2687 | ! compute the net precipitation flux across interfaces |
---|
2688 | pflx(:il2g,1) = 0._r8 |
---|
2689 | do k = 2,pverp |
---|
2690 | do i = 1,il2g |
---|
2691 | pflx(i,k) = pflx(i,k-1) + rprd(i,k-1)*dz(i,k-1) |
---|
2692 | end do |
---|
2693 | end do |
---|
2694 | ! |
---|
2695 | do k = msg + 1,pver |
---|
2696 | do i = 1,il2g |
---|
2697 | mc(i,k) = mu(i,k) + md(i,k) |
---|
2698 | end do |
---|
2699 | end do |
---|
2700 | ! |
---|
2701 | return |
---|
2702 | end subroutine cldprp |
---|
2703 | |
---|
2704 | subroutine closure(lchnk , & |
---|
2705 | q ,t ,p ,z ,s , & |
---|
2706 | tp ,qs ,qu ,su ,mc , & |
---|
2707 | du ,mu ,md ,qd ,sd , & |
---|
2708 | qhat ,shat ,dp ,qstp ,zf , & |
---|
2709 | ql ,dsubcld ,mb ,cape ,tl , & |
---|
2710 | lcl ,lel ,jt ,mx ,il1g , & |
---|
2711 | il2g ,rd ,grav ,cp ,rl , & |
---|
2712 | msg ,capelmt ) |
---|
2713 | !----------------------------------------------------------------------- |
---|
2714 | ! |
---|
2715 | ! Purpose: |
---|
2716 | ! <Say what the routine does> |
---|
2717 | ! |
---|
2718 | ! Method: |
---|
2719 | ! <Describe the algorithm(s) used in the routine.> |
---|
2720 | ! <Also include any applicable external references.> |
---|
2721 | ! |
---|
2722 | ! Author: G. Zhang and collaborators. CCM contact:P. Rasch |
---|
2723 | ! This is contributed code not fully standardized by the CCM core group. |
---|
2724 | ! |
---|
2725 | ! this code is very much rougher than virtually anything else in the CCM |
---|
2726 | ! We expect to release cleaner code in a future release |
---|
2727 | ! |
---|
2728 | ! the documentation has been enhanced to the degree that we are able |
---|
2729 | ! |
---|
2730 | !----------------------------------------------------------------------- |
---|
2731 | #ifndef WRF_PORT |
---|
2732 | use dycore, only: dycore_is, get_resolution |
---|
2733 | #endif |
---|
2734 | |
---|
2735 | implicit none |
---|
2736 | |
---|
2737 | ! |
---|
2738 | !-----------------------------Arguments--------------------------------- |
---|
2739 | ! |
---|
2740 | integer, intent(in) :: lchnk ! chunk identifier |
---|
2741 | |
---|
2742 | real(r8), intent(inout) :: q(pcols,pver) ! spec humidity |
---|
2743 | real(r8), intent(inout) :: t(pcols,pver) ! temperature |
---|
2744 | real(r8), intent(inout) :: p(pcols,pver) ! pressure (mb) |
---|
2745 | real(r8), intent(inout) :: mb(pcols) ! cloud base mass flux |
---|
2746 | real(r8), intent(in) :: z(pcols,pver) ! height (m) |
---|
2747 | real(r8), intent(in) :: s(pcols,pver) ! normalized dry static energy |
---|
2748 | real(r8), intent(in) :: tp(pcols,pver) ! parcel temp |
---|
2749 | real(r8), intent(in) :: qs(pcols,pver) ! sat spec humidity |
---|
2750 | real(r8), intent(in) :: qu(pcols,pver) ! updraft spec. humidity |
---|
2751 | real(r8), intent(in) :: su(pcols,pver) ! normalized dry stat energy of updraft |
---|
2752 | real(r8), intent(in) :: mc(pcols,pver) ! net convective mass flux |
---|
2753 | real(r8), intent(in) :: du(pcols,pver) ! detrainment from updraft |
---|
2754 | real(r8), intent(in) :: mu(pcols,pver) ! mass flux of updraft |
---|
2755 | real(r8), intent(in) :: md(pcols,pver) ! mass flux of downdraft |
---|
2756 | real(r8), intent(in) :: qd(pcols,pver) ! spec. humidity of downdraft |
---|
2757 | real(r8), intent(in) :: sd(pcols,pver) ! dry static energy of downdraft |
---|
2758 | real(r8), intent(in) :: qhat(pcols,pver) ! environment spec humidity at interfaces |
---|
2759 | real(r8), intent(in) :: shat(pcols,pver) ! env. normalized dry static energy at intrfcs |
---|
2760 | real(r8), intent(in) :: dp(pcols,pver) ! pressure thickness of layers |
---|
2761 | real(r8), intent(in) :: qstp(pcols,pver) ! spec humidity of parcel |
---|
2762 | real(r8), intent(in) :: zf(pcols,pver+1) ! height of interface levels |
---|
2763 | real(r8), intent(in) :: ql(pcols,pver) ! liquid water mixing ratio |
---|
2764 | |
---|
2765 | real(r8), intent(in) :: cape(pcols) ! available pot. energy of column |
---|
2766 | real(r8), intent(in) :: tl(pcols) |
---|
2767 | real(r8), intent(in) :: dsubcld(pcols) ! thickness of subcloud layer |
---|
2768 | |
---|
2769 | integer, intent(in) :: lcl(pcols) ! index of lcl |
---|
2770 | integer, intent(in) :: lel(pcols) ! index of launch leve |
---|
2771 | integer, intent(in) :: jt(pcols) ! top of updraft |
---|
2772 | integer, intent(in) :: mx(pcols) ! base of updraft |
---|
2773 | ! |
---|
2774 | !--------------------------Local variables------------------------------ |
---|
2775 | ! |
---|
2776 | real(r8) dtpdt(pcols,pver) |
---|
2777 | real(r8) dqsdtp(pcols,pver) |
---|
2778 | real(r8) dtmdt(pcols,pver) |
---|
2779 | real(r8) dqmdt(pcols,pver) |
---|
2780 | real(r8) dboydt(pcols,pver) |
---|
2781 | real(r8) thetavp(pcols,pver) |
---|
2782 | real(r8) thetavm(pcols,pver) |
---|
2783 | |
---|
2784 | real(r8) dtbdt(pcols),dqbdt(pcols),dtldt(pcols) |
---|
2785 | real(r8) beta |
---|
2786 | real(r8) capelmt |
---|
2787 | real(r8) cp |
---|
2788 | real(r8) dadt(pcols) |
---|
2789 | real(r8) debdt |
---|
2790 | real(r8) dltaa |
---|
2791 | real(r8) eb |
---|
2792 | real(r8) grav |
---|
2793 | |
---|
2794 | integer i |
---|
2795 | integer il1g |
---|
2796 | integer il2g |
---|
2797 | integer k, kmin, kmax |
---|
2798 | integer msg |
---|
2799 | |
---|
2800 | real(r8) rd |
---|
2801 | real(r8) rl |
---|
2802 | ! change of subcloud layer properties due to convection is |
---|
2803 | ! related to cumulus updrafts and downdrafts. |
---|
2804 | ! mc(z)=f(z)*mb, mub=betau*mb, mdb=betad*mb are used |
---|
2805 | ! to define betau, betad and f(z). |
---|
2806 | ! note that this implies all time derivatives are in effect |
---|
2807 | ! time derivatives per unit cloud-base mass flux, i.e. they |
---|
2808 | ! have units of 1/mb instead of 1/sec. |
---|
2809 | ! |
---|
2810 | do i = il1g,il2g |
---|
2811 | mb(i) = 0._r8 |
---|
2812 | eb = p(i,mx(i))*q(i,mx(i))/ (eps1+q(i,mx(i))) |
---|
2813 | dtbdt(i) = (1._r8/dsubcld(i))* (mu(i,mx(i))*(shat(i,mx(i))-su(i,mx(i)))+ & |
---|
2814 | md(i,mx(i))* (shat(i,mx(i))-sd(i,mx(i)))) |
---|
2815 | dqbdt(i) = (1._r8/dsubcld(i))* (mu(i,mx(i))*(qhat(i,mx(i))-qu(i,mx(i)))+ & |
---|
2816 | md(i,mx(i))* (qhat(i,mx(i))-qd(i,mx(i)))) |
---|
2817 | debdt = eps1*p(i,mx(i))/ (eps1+q(i,mx(i)))**2*dqbdt(i) |
---|
2818 | dtldt(i) = -2840._r8* (3.5_r8/t(i,mx(i))*dtbdt(i)-debdt/eb)/ & |
---|
2819 | (3.5_r8*log(t(i,mx(i)))-log(eb)-4.805_r8)**2 |
---|
2820 | end do |
---|
2821 | ! |
---|
2822 | ! dtmdt and dqmdt are cumulus heating and drying. |
---|
2823 | ! |
---|
2824 | do k = msg + 1,pver |
---|
2825 | do i = il1g,il2g |
---|
2826 | dtmdt(i,k) = 0._r8 |
---|
2827 | dqmdt(i,k) = 0._r8 |
---|
2828 | end do |
---|
2829 | end do |
---|
2830 | ! |
---|
2831 | do k = msg + 1,pver - 1 |
---|
2832 | do i = il1g,il2g |
---|
2833 | if (k == jt(i)) then |
---|
2834 | dtmdt(i,k) = (1._r8/dp(i,k))*(mu(i,k+1)* (su(i,k+1)-shat(i,k+1)- & |
---|
2835 | rl/cp*ql(i,k+1))+md(i,k+1)* (sd(i,k+1)-shat(i,k+1))) |
---|
2836 | dqmdt(i,k) = (1._r8/dp(i,k))*(mu(i,k+1)* (qu(i,k+1)- & |
---|
2837 | qhat(i,k+1)+ql(i,k+1))+md(i,k+1)*(qd(i,k+1)-qhat(i,k+1))) |
---|
2838 | end if |
---|
2839 | end do |
---|
2840 | end do |
---|
2841 | ! |
---|
2842 | beta = 0._r8 |
---|
2843 | do k = msg + 1,pver - 1 |
---|
2844 | do i = il1g,il2g |
---|
2845 | if (k > jt(i) .and. k < mx(i)) then |
---|
2846 | dtmdt(i,k) = (mc(i,k)* (shat(i,k)-s(i,k))+mc(i,k+1)* (s(i,k)-shat(i,k+1)))/ & |
---|
2847 | dp(i,k) - rl/cp*du(i,k)*(beta*ql(i,k)+ (1-beta)*ql(i,k+1)) |
---|
2848 | ! dqmdt(i,k)=(mc(i,k)*(qhat(i,k)-q(i,k)) |
---|
2849 | ! 1 +mc(i,k+1)*(q(i,k)-qhat(i,k+1)))/dp(i,k) |
---|
2850 | ! 2 +du(i,k)*(qs(i,k)-q(i,k)) |
---|
2851 | ! 3 +du(i,k)*(beta*ql(i,k)+(1-beta)*ql(i,k+1)) |
---|
2852 | |
---|
2853 | dqmdt(i,k) = (mu(i,k+1)* (qu(i,k+1)-qhat(i,k+1)+cp/rl* (su(i,k+1)-s(i,k)))- & |
---|
2854 | mu(i,k)* (qu(i,k)-qhat(i,k)+cp/rl*(su(i,k)-s(i,k)))+md(i,k+1)* & |
---|
2855 | (qd(i,k+1)-qhat(i,k+1)+cp/rl*(sd(i,k+1)-s(i,k)))-md(i,k)* & |
---|
2856 | (qd(i,k)-qhat(i,k)+cp/rl*(sd(i,k)-s(i,k))))/dp(i,k) + & |
---|
2857 | du(i,k)* (beta*ql(i,k)+(1-beta)*ql(i,k+1)) |
---|
2858 | end if |
---|
2859 | end do |
---|
2860 | end do |
---|
2861 | ! |
---|
2862 | do k = msg + 1,pver |
---|
2863 | do i = il1g,il2g |
---|
2864 | if (k >= lel(i) .and. k <= lcl(i)) then |
---|
2865 | thetavp(i,k) = tp(i,k)* (1000._r8/p(i,k))** (rd/cp)*(1._r8+1.608_r8*qstp(i,k)-q(i,mx(i))) |
---|
2866 | thetavm(i,k) = t(i,k)* (1000._r8/p(i,k))** (rd/cp)*(1._r8+0.608_r8*q(i,k)) |
---|
2867 | dqsdtp(i,k) = qstp(i,k)* (1._r8+qstp(i,k)/eps1)*eps1*rl/(rd*tp(i,k)**2) |
---|
2868 | ! |
---|
2869 | ! dtpdt is the parcel temperature change due to change of |
---|
2870 | ! subcloud layer properties during convection. |
---|
2871 | ! |
---|
2872 | dtpdt(i,k) = tp(i,k)/ (1._r8+rl/cp* (dqsdtp(i,k)-qstp(i,k)/tp(i,k)))* & |
---|
2873 | (dtbdt(i)/t(i,mx(i))+rl/cp* (dqbdt(i)/tl(i)-q(i,mx(i))/ & |
---|
2874 | tl(i)**2*dtldt(i))) |
---|
2875 | ! |
---|
2876 | ! dboydt is the integrand of cape change. |
---|
2877 | ! |
---|
2878 | dboydt(i,k) = ((dtpdt(i,k)/tp(i,k)+1._r8/(1._r8+1.608_r8*qstp(i,k)-q(i,mx(i)))* & |
---|
2879 | (1.608_r8 * dqsdtp(i,k) * dtpdt(i,k) -dqbdt(i))) - (dtmdt(i,k)/t(i,k)+0.608_r8/ & |
---|
2880 | (1._r8+0.608_r8*q(i,k))*dqmdt(i,k)))*grav*thetavp(i,k)/thetavm(i,k) |
---|
2881 | end if |
---|
2882 | end do |
---|
2883 | end do |
---|
2884 | ! |
---|
2885 | do k = msg + 1,pver |
---|
2886 | do i = il1g,il2g |
---|
2887 | if (k > lcl(i) .and. k < mx(i)) then |
---|
2888 | thetavp(i,k) = tp(i,k)* (1000._r8/p(i,k))** (rd/cp)*(1._r8+0.608_r8*q(i,mx(i))) |
---|
2889 | thetavm(i,k) = t(i,k)* (1000._r8/p(i,k))** (rd/cp)*(1._r8+0.608_r8*q(i,k)) |
---|
2890 | ! |
---|
2891 | ! dboydt is the integrand of cape change. |
---|
2892 | ! |
---|
2893 | dboydt(i,k) = (dtbdt(i)/t(i,mx(i))+0.608_r8/ (1._r8+0.608_r8*q(i,mx(i)))*dqbdt(i)- & |
---|
2894 | dtmdt(i,k)/t(i,k)-0.608_r8/ (1._r8+0.608_r8*q(i,k))*dqmdt(i,k))* & |
---|
2895 | grav*thetavp(i,k)/thetavm(i,k) |
---|
2896 | end if |
---|
2897 | end do |
---|
2898 | end do |
---|
2899 | |
---|
2900 | ! |
---|
2901 | ! buoyant energy change is set to 2/3*excess cape per 3 hours |
---|
2902 | ! |
---|
2903 | dadt(il1g:il2g) = 0._r8 |
---|
2904 | kmin = minval(lel(il1g:il2g)) |
---|
2905 | kmax = maxval(mx(il1g:il2g)) - 1 |
---|
2906 | do k = kmin, kmax |
---|
2907 | do i = il1g,il2g |
---|
2908 | if ( k >= lel(i) .and. k <= mx(i) - 1) then |
---|
2909 | dadt(i) = dadt(i) + dboydt(i,k)* (zf(i,k)-zf(i,k+1)) |
---|
2910 | endif |
---|
2911 | end do |
---|
2912 | end do |
---|
2913 | do i = il1g,il2g |
---|
2914 | dltaa = -1._r8* (cape(i)-capelmt) |
---|
2915 | if (dadt(i) /= 0._r8) mb(i) = max(dltaa/tau/dadt(i),0._r8) |
---|
2916 | end do |
---|
2917 | ! |
---|
2918 | return |
---|
2919 | end subroutine closure |
---|
2920 | |
---|
2921 | subroutine q1q2_pjr(lchnk , & |
---|
2922 | dqdt ,dsdt ,q ,qs ,qu , & |
---|
2923 | su ,du ,qhat ,shat ,dp , & |
---|
2924 | mu ,md ,sd ,qd ,ql , & |
---|
2925 | dsubcld ,jt ,mx ,il1g ,il2g , & |
---|
2926 | cp ,rl ,msg , & |
---|
2927 | dl ,evp ,cu ) |
---|
2928 | |
---|
2929 | |
---|
2930 | implicit none |
---|
2931 | |
---|
2932 | !----------------------------------------------------------------------- |
---|
2933 | ! |
---|
2934 | ! Purpose: |
---|
2935 | ! <Say what the routine does> |
---|
2936 | ! |
---|
2937 | ! Method: |
---|
2938 | ! <Describe the algorithm(s) used in the routine.> |
---|
2939 | ! <Also include any applicable external references.> |
---|
2940 | ! |
---|
2941 | ! Author: phil rasch dec 19 1995 |
---|
2942 | ! |
---|
2943 | !----------------------------------------------------------------------- |
---|
2944 | |
---|
2945 | |
---|
2946 | real(r8), intent(in) :: cp |
---|
2947 | |
---|
2948 | integer, intent(in) :: lchnk ! chunk identifier |
---|
2949 | integer, intent(in) :: il1g |
---|
2950 | integer, intent(in) :: il2g |
---|
2951 | integer, intent(in) :: msg |
---|
2952 | |
---|
2953 | real(r8), intent(in) :: q(pcols,pver) |
---|
2954 | real(r8), intent(in) :: qs(pcols,pver) |
---|
2955 | real(r8), intent(in) :: qu(pcols,pver) |
---|
2956 | real(r8), intent(in) :: su(pcols,pver) |
---|
2957 | real(r8), intent(in) :: du(pcols,pver) |
---|
2958 | real(r8), intent(in) :: qhat(pcols,pver) |
---|
2959 | real(r8), intent(in) :: shat(pcols,pver) |
---|
2960 | real(r8), intent(in) :: dp(pcols,pver) |
---|
2961 | real(r8), intent(in) :: mu(pcols,pver) |
---|
2962 | real(r8), intent(in) :: md(pcols,pver) |
---|
2963 | real(r8), intent(in) :: sd(pcols,pver) |
---|
2964 | real(r8), intent(in) :: qd(pcols,pver) |
---|
2965 | real(r8), intent(in) :: ql(pcols,pver) |
---|
2966 | real(r8), intent(in) :: evp(pcols,pver) |
---|
2967 | real(r8), intent(in) :: cu(pcols,pver) |
---|
2968 | real(r8), intent(in) :: dsubcld(pcols) |
---|
2969 | |
---|
2970 | real(r8),intent(out) :: dqdt(pcols,pver),dsdt(pcols,pver) |
---|
2971 | real(r8),intent(out) :: dl(pcols,pver) |
---|
2972 | integer kbm |
---|
2973 | integer ktm |
---|
2974 | integer jt(pcols) |
---|
2975 | integer mx(pcols) |
---|
2976 | ! |
---|
2977 | ! work fields: |
---|
2978 | ! |
---|
2979 | integer i |
---|
2980 | integer k |
---|
2981 | |
---|
2982 | real(r8) emc |
---|
2983 | real(r8) rl |
---|
2984 | !------------------------------------------------------------------- |
---|
2985 | do k = msg + 1,pver |
---|
2986 | do i = il1g,il2g |
---|
2987 | dsdt(i,k) = 0._r8 |
---|
2988 | dqdt(i,k) = 0._r8 |
---|
2989 | dl(i,k) = 0._r8 |
---|
2990 | end do |
---|
2991 | end do |
---|
2992 | ! |
---|
2993 | ! find the highest level top and bottom levels of convection |
---|
2994 | ! |
---|
2995 | ktm = pver |
---|
2996 | kbm = pver |
---|
2997 | do i = il1g, il2g |
---|
2998 | ktm = min(ktm,jt(i)) |
---|
2999 | kbm = min(kbm,mx(i)) |
---|
3000 | end do |
---|
3001 | |
---|
3002 | do k = ktm,pver-1 |
---|
3003 | do i = il1g,il2g |
---|
3004 | emc = -cu (i,k) & ! condensation in updraft |
---|
3005 | +evp(i,k) ! evaporating rain in downdraft |
---|
3006 | |
---|
3007 | dsdt(i,k) = -rl/cp*emc & |
---|
3008 | + (+mu(i,k+1)* (su(i,k+1)-shat(i,k+1)) & |
---|
3009 | -mu(i,k)* (su(i,k)-shat(i,k)) & |
---|
3010 | +md(i,k+1)* (sd(i,k+1)-shat(i,k+1)) & |
---|
3011 | -md(i,k)* (sd(i,k)-shat(i,k)) & |
---|
3012 | )/dp(i,k) |
---|
3013 | |
---|
3014 | dqdt(i,k) = emc + & |
---|
3015 | (+mu(i,k+1)* (qu(i,k+1)-qhat(i,k+1)) & |
---|
3016 | -mu(i,k)* (qu(i,k)-qhat(i,k)) & |
---|
3017 | +md(i,k+1)* (qd(i,k+1)-qhat(i,k+1)) & |
---|
3018 | -md(i,k)* (qd(i,k)-qhat(i,k)) & |
---|
3019 | )/dp(i,k) |
---|
3020 | |
---|
3021 | dl(i,k) = du(i,k)*ql(i,k+1) |
---|
3022 | |
---|
3023 | end do |
---|
3024 | end do |
---|
3025 | |
---|
3026 | ! |
---|
3027 | !DIR$ NOINTERCHANGE! |
---|
3028 | do k = kbm,pver |
---|
3029 | do i = il1g,il2g |
---|
3030 | if (k == mx(i)) then |
---|
3031 | dsdt(i,k) = (1._r8/dsubcld(i))* & |
---|
3032 | (-mu(i,k)* (su(i,k)-shat(i,k)) & |
---|
3033 | -md(i,k)* (sd(i,k)-shat(i,k)) & |
---|
3034 | ) |
---|
3035 | dqdt(i,k) = (1._r8/dsubcld(i))* & |
---|
3036 | (-mu(i,k)*(qu(i,k)-qhat(i,k)) & |
---|
3037 | -md(i,k)*(qd(i,k)-qhat(i,k)) & |
---|
3038 | ) |
---|
3039 | else if (k > mx(i)) then |
---|
3040 | dsdt(i,k) = dsdt(i,k-1) |
---|
3041 | dqdt(i,k) = dqdt(i,k-1) |
---|
3042 | end if |
---|
3043 | end do |
---|
3044 | end do |
---|
3045 | ! |
---|
3046 | return |
---|
3047 | end subroutine q1q2_pjr |
---|
3048 | |
---|
3049 | subroutine buoyan_dilute(lchnk ,ncol , & |
---|
3050 | q ,t ,p ,z ,pf , & |
---|
3051 | tp ,qstp ,tl ,rl ,cape , & |
---|
3052 | pblt ,lcl ,lel ,lon ,mx , & |
---|
3053 | rd ,grav ,cp ,msg , & |
---|
3054 | tpert ) |
---|
3055 | !----------------------------------------------------------------------- |
---|
3056 | ! |
---|
3057 | ! Purpose: |
---|
3058 | ! Calculates CAPE the lifting condensation level and the convective top |
---|
3059 | ! where buoyancy is first -ve. |
---|
3060 | ! |
---|
3061 | ! Method: Calculates the parcel temperature based on a simple constant |
---|
3062 | ! entraining plume model. CAPE is integrated from buoyancy. |
---|
3063 | ! 09/09/04 - Simplest approach using an assumed entrainment rate for |
---|
3064 | ! testing (dmpdp). |
---|
3065 | ! 08/04/05 - Swap to convert dmpdz to dmpdp |
---|
3066 | ! |
---|
3067 | ! SCAM Logical Switches - DILUTE:RBN - Now Disabled |
---|
3068 | ! --------------------- |
---|
3069 | ! switch(1) = .T. - Uses the dilute parcel calculation to obtain tendencies. |
---|
3070 | ! switch(2) = .T. - Includes entropy/q changes due to condensate loss and freezing. |
---|
3071 | ! switch(3) = .T. - Adds the PBL Tpert for the parcel temperature at all levels. |
---|
3072 | ! |
---|
3073 | ! References: |
---|
3074 | ! Raymond and Blythe (1992) JAS |
---|
3075 | ! |
---|
3076 | ! Author: |
---|
3077 | ! Richard Neale - September 2004 |
---|
3078 | ! |
---|
3079 | !----------------------------------------------------------------------- |
---|
3080 | implicit none |
---|
3081 | !----------------------------------------------------------------------- |
---|
3082 | ! |
---|
3083 | ! input arguments |
---|
3084 | ! |
---|
3085 | integer, intent(in) :: lchnk ! chunk identifier |
---|
3086 | integer, intent(in) :: ncol ! number of atmospheric columns |
---|
3087 | |
---|
3088 | real(r8), intent(in) :: q(pcols,pver) ! spec. humidity |
---|
3089 | real(r8), intent(in) :: t(pcols,pver) ! temperature |
---|
3090 | real(r8), intent(in) :: p(pcols,pver) ! pressure |
---|
3091 | real(r8), intent(in) :: z(pcols,pver) ! height |
---|
3092 | real(r8), intent(in) :: pf(pcols,pver+1) ! pressure at interfaces |
---|
3093 | real(r8), intent(in) :: pblt(pcols) ! index of pbl depth |
---|
3094 | real(r8), intent(in) :: tpert(pcols) ! perturbation temperature by pbl processes |
---|
3095 | |
---|
3096 | ! |
---|
3097 | ! output arguments |
---|
3098 | ! |
---|
3099 | real(r8), intent(out) :: tp(pcols,pver) ! parcel temperature |
---|
3100 | real(r8), intent(out) :: qstp(pcols,pver) ! saturation mixing ratio of parcel (only above lcl, just q below). |
---|
3101 | real(r8), intent(out) :: tl(pcols) ! parcel temperature at lcl |
---|
3102 | real(r8), intent(out) :: cape(pcols) ! convective aval. pot. energy. |
---|
3103 | integer lcl(pcols) ! |
---|
3104 | integer lel(pcols) ! |
---|
3105 | integer lon(pcols) ! level of onset of deep convection |
---|
3106 | integer mx(pcols) ! level of max moist static energy |
---|
3107 | ! |
---|
3108 | !--------------------------Local Variables------------------------------ |
---|
3109 | ! |
---|
3110 | real(r8) capeten(pcols,5) ! provisional value of cape |
---|
3111 | real(r8) tv(pcols,pver) ! |
---|
3112 | real(r8) tpv(pcols,pver) ! |
---|
3113 | real(r8) buoy(pcols,pver) |
---|
3114 | |
---|
3115 | real(r8) a1(pcols) |
---|
3116 | real(r8) a2(pcols) |
---|
3117 | real(r8) estp(pcols) |
---|
3118 | real(r8) pl(pcols) |
---|
3119 | real(r8) plexp(pcols) |
---|
3120 | real(r8) hmax(pcols) |
---|
3121 | real(r8) hmn(pcols) |
---|
3122 | real(r8) y(pcols) |
---|
3123 | |
---|
3124 | logical plge600(pcols) |
---|
3125 | integer knt(pcols) |
---|
3126 | integer lelten(pcols,5) |
---|
3127 | |
---|
3128 | real(r8) cp |
---|
3129 | real(r8) e |
---|
3130 | real(r8) grav |
---|
3131 | |
---|
3132 | integer i |
---|
3133 | integer k |
---|
3134 | integer msg |
---|
3135 | integer n |
---|
3136 | |
---|
3137 | real(r8) rd |
---|
3138 | real(r8) rl |
---|
3139 | #ifdef PERGRO |
---|
3140 | real(r8) rhd |
---|
3141 | #endif |
---|
3142 | ! |
---|
3143 | !----------------------------------------------------------------------- |
---|
3144 | ! |
---|
3145 | do n = 1,5 |
---|
3146 | do i = 1,ncol |
---|
3147 | lelten(i,n) = pver |
---|
3148 | capeten(i,n) = 0._r8 |
---|
3149 | end do |
---|
3150 | end do |
---|
3151 | ! |
---|
3152 | do i = 1,ncol |
---|
3153 | lon(i) = pver |
---|
3154 | knt(i) = 0 |
---|
3155 | lel(i) = pver |
---|
3156 | mx(i) = lon(i) |
---|
3157 | cape(i) = 0._r8 |
---|
3158 | hmax(i) = 0._r8 |
---|
3159 | end do |
---|
3160 | |
---|
3161 | tp(:ncol,:) = t(:ncol,:) |
---|
3162 | qstp(:ncol,:) = q(:ncol,:) |
---|
3163 | |
---|
3164 | !!! RBN - Initialize tv and buoy for output. |
---|
3165 | !!! tv=tv : tpv=tpv : qstp=q : buoy=0. |
---|
3166 | tv(:ncol,:) = t(:ncol,:) *(1._r8+1.608_r8*q(:ncol,:))/ (1._r8+q(:ncol,:)) |
---|
3167 | tpv(:ncol,:) = tv(:ncol,:) |
---|
3168 | buoy(:ncol,:) = 0._r8 |
---|
3169 | |
---|
3170 | ! |
---|
3171 | ! set "launching" level(mx) to be at maximum moist static energy. |
---|
3172 | ! search for this level stops at planetary boundary layer top. |
---|
3173 | ! |
---|
3174 | #ifdef PERGRO |
---|
3175 | do k = pver,msg + 1,-1 |
---|
3176 | do i = 1,ncol |
---|
3177 | hmn(i) = cp*t(i,k) + grav*z(i,k) + rl*q(i,k) |
---|
3178 | ! |
---|
3179 | ! Reset max moist static energy level when relative difference exceeds 1.e-4 |
---|
3180 | ! |
---|
3181 | rhd = (hmn(i) - hmax(i))/(hmn(i) + hmax(i)) |
---|
3182 | if (k >= nint(pblt(i)) .and. k <= lon(i) .and. rhd > -1.e-4_r8) then |
---|
3183 | hmax(i) = hmn(i) |
---|
3184 | mx(i) = k |
---|
3185 | end if |
---|
3186 | end do |
---|
3187 | end do |
---|
3188 | #else |
---|
3189 | do k = pver,msg + 1,-1 |
---|
3190 | do i = 1,ncol |
---|
3191 | hmn(i) = cp*t(i,k) + grav*z(i,k) + rl*q(i,k) |
---|
3192 | if (k >= nint(pblt(i)) .and. k <= lon(i) .and. hmn(i) > hmax(i)) then |
---|
3193 | hmax(i) = hmn(i) |
---|
3194 | mx(i) = k |
---|
3195 | end if |
---|
3196 | end do |
---|
3197 | end do |
---|
3198 | #endif |
---|
3199 | |
---|
3200 | ! LCL dilute calculation - initialize to mx(i) |
---|
3201 | ! Determine lcl in parcel_dilute and get pl,tl after parcel_dilute |
---|
3202 | ! Original code actually sets LCL as level above wher condensate forms. |
---|
3203 | ! Therefore in parcel_dilute lcl(i) will be at first level where qsmix < qtmix. |
---|
3204 | |
---|
3205 | do i = 1,ncol ! Initialise LCL variables. |
---|
3206 | lcl(i) = mx(i) |
---|
3207 | tl(i) = t(i,mx(i)) |
---|
3208 | pl(i) = p(i,mx(i)) |
---|
3209 | end do |
---|
3210 | |
---|
3211 | ! |
---|
3212 | ! main buoyancy calculation. |
---|
3213 | ! |
---|
3214 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
---|
3215 | !!! DILUTE PLUME CALCULATION USING ENTRAINING PLUME !!! |
---|
3216 | !!! RBN 9/9/04 !!! |
---|
3217 | |
---|
3218 | call parcel_dilute(lchnk, ncol, msg, mx, p, t, q, tpert, tp, tpv, qstp, pl, tl, lcl) |
---|
3219 | |
---|
3220 | |
---|
3221 | ! If lcl is above the nominal level of non-divergence (600 mbs), |
---|
3222 | ! no deep convection is permitted (ensuing calculations |
---|
3223 | ! skipped and cape retains initialized value of zero). |
---|
3224 | ! |
---|
3225 | do i = 1,ncol |
---|
3226 | plge600(i) = pl(i).ge.600._r8 ! Just change to always allow buoy calculation. |
---|
3227 | end do |
---|
3228 | |
---|
3229 | ! |
---|
3230 | ! Main buoyancy calculation. |
---|
3231 | ! |
---|
3232 | do k = pver,msg + 1,-1 |
---|
3233 | do i=1,ncol |
---|
3234 | if (k <= mx(i) .and. plge600(i)) then ! Define buoy from launch level to cloud top. |
---|
3235 | tv(i,k) = t(i,k)* (1._r8+1.608_r8*q(i,k))/ (1._r8+q(i,k)) |
---|
3236 | buoy(i,k) = tpv(i,k) - tv(i,k) + tiedke_add ! +0.5K or not? |
---|
3237 | else |
---|
3238 | qstp(i,k) = q(i,k) |
---|
3239 | tp(i,k) = t(i,k) |
---|
3240 | tpv(i,k) = tv(i,k) |
---|
3241 | endif |
---|
3242 | end do |
---|
3243 | end do |
---|
3244 | |
---|
3245 | |
---|
3246 | |
---|
3247 | !------------------------------------------------------------------------------- |
---|
3248 | |
---|
3249 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
---|
3250 | |
---|
3251 | |
---|
3252 | |
---|
3253 | ! |
---|
3254 | do k = msg + 2,pver |
---|
3255 | do i = 1,ncol |
---|
3256 | if (k < lcl(i) .and. plge600(i)) then |
---|
3257 | if (buoy(i,k+1) > 0. .and. buoy(i,k) <= 0._r8) then |
---|
3258 | knt(i) = min(5,knt(i) + 1) |
---|
3259 | lelten(i,knt(i)) = k |
---|
3260 | end if |
---|
3261 | end if |
---|
3262 | end do |
---|
3263 | end do |
---|
3264 | ! |
---|
3265 | ! calculate convective available potential energy (cape). |
---|
3266 | ! |
---|
3267 | do n = 1,5 |
---|
3268 | do k = msg + 1,pver |
---|
3269 | do i = 1,ncol |
---|
3270 | if (plge600(i) .and. k <= mx(i) .and. k > lelten(i,n)) then |
---|
3271 | capeten(i,n) = capeten(i,n) + rd*buoy(i,k)*log(pf(i,k+1)/pf(i,k)) |
---|
3272 | end if |
---|
3273 | end do |
---|
3274 | end do |
---|
3275 | end do |
---|
3276 | ! |
---|
3277 | ! find maximum cape from all possible tentative capes from |
---|
3278 | ! one sounding, |
---|
3279 | ! and use it as the final cape, april 26, 1995 |
---|
3280 | ! |
---|
3281 | do n = 1,5 |
---|
3282 | do i = 1,ncol |
---|
3283 | if (capeten(i,n) > cape(i)) then |
---|
3284 | cape(i) = capeten(i,n) |
---|
3285 | lel(i) = lelten(i,n) |
---|
3286 | end if |
---|
3287 | end do |
---|
3288 | end do |
---|
3289 | ! |
---|
3290 | ! put lower bound on cape for diagnostic purposes. |
---|
3291 | ! |
---|
3292 | do i = 1,ncol |
---|
3293 | cape(i) = max(cape(i), 0._r8) |
---|
3294 | end do |
---|
3295 | ! |
---|
3296 | return |
---|
3297 | end subroutine buoyan_dilute |
---|
3298 | |
---|
3299 | subroutine parcel_dilute (lchnk, ncol, msg, klaunch, p, t, q, tpert, tp, tpv, qstp, pl, tl, lcl) |
---|
3300 | |
---|
3301 | ! Routine to determine |
---|
3302 | ! 1. Tp - Parcel temperature |
---|
3303 | ! 2. qstp - Saturated mixing ratio at the parcel temperature. |
---|
3304 | |
---|
3305 | !-------------------- |
---|
3306 | implicit none |
---|
3307 | !-------------------- |
---|
3308 | |
---|
3309 | integer, intent(in) :: lchnk |
---|
3310 | integer, intent(in) :: ncol |
---|
3311 | integer, intent(in) :: msg |
---|
3312 | |
---|
3313 | integer, intent(in), dimension(pcols) :: klaunch(pcols) |
---|
3314 | |
---|
3315 | real(r8), intent(in), dimension(pcols,pver) :: p |
---|
3316 | real(r8), intent(in), dimension(pcols,pver) :: t |
---|
3317 | real(r8), intent(in), dimension(pcols,pver) :: q |
---|
3318 | real(r8), intent(in), dimension(pcols) :: tpert ! PBL temperature perturbation. |
---|
3319 | |
---|
3320 | real(r8), intent(inout), dimension(pcols,pver) :: tp ! Parcel temp. |
---|
3321 | real(r8), intent(inout), dimension(pcols,pver) :: qstp ! Parcel water vapour (sat value above lcl). |
---|
3322 | real(r8), intent(inout), dimension(pcols) :: tl ! Actual temp of LCL. |
---|
3323 | real(r8), intent(inout), dimension(pcols) :: pl ! Actual pressure of LCL. |
---|
3324 | |
---|
3325 | integer, intent(inout), dimension(pcols) :: lcl ! Lifting condesation level (first model level with saturation). |
---|
3326 | |
---|
3327 | real(r8), intent(out), dimension(pcols,pver) :: tpv ! Define tpv within this routine. |
---|
3328 | |
---|
3329 | !-------------------- |
---|
3330 | |
---|
3331 | ! Have to be careful as s is also dry static energy. |
---|
3332 | |
---|
3333 | |
---|
3334 | ! If we are to retain the fact that CAM loops over grid-points in the internal |
---|
3335 | ! loop then we need to dimension sp,atp,mp,xsh2o with ncol. |
---|
3336 | |
---|
3337 | |
---|
3338 | real(r8) tmix(pcols,pver) ! Tempertaure of the entraining parcel. |
---|
3339 | real(r8) qtmix(pcols,pver) ! Total water of the entraining parcel. |
---|
3340 | real(r8) qsmix(pcols,pver) ! Saturated mixing ratio at the tmix. |
---|
3341 | real(r8) smix(pcols,pver) ! Entropy of the entraining parcel. |
---|
3342 | real(r8) xsh2o(pcols,pver) ! Precipitate lost from parcel. |
---|
3343 | real(r8) ds_xsh2o(pcols,pver) ! Entropy change due to loss of condensate. |
---|
3344 | real(r8) ds_freeze(pcols,pver) ! Entropy change sue to freezing of precip. |
---|
3345 | |
---|
3346 | real(r8) mp(pcols) ! Parcel mass flux. |
---|
3347 | real(r8) qtp(pcols) ! Parcel total water. |
---|
3348 | real(r8) sp(pcols) ! Parcel entropy. |
---|
3349 | |
---|
3350 | real(r8) sp0(pcols) ! Parcel launch entropy. |
---|
3351 | real(r8) qtp0(pcols) ! Parcel launch total water. |
---|
3352 | real(r8) mp0(pcols) ! Parcel launch relative mass flux. |
---|
3353 | |
---|
3354 | real(r8) lwmax ! Maximum condesate that can be held in cloud before rainout. |
---|
3355 | real(r8) dmpdp ! Parcel fractional mass entrainment rate (/mb). |
---|
3356 | !real(r8) dmpdpc ! In cloud parcel mass entrainment rate (/mb). |
---|
3357 | real(r8) dmpdz ! Parcel fractional mass entrainment rate (/m) |
---|
3358 | real(r8) dpdz,dzdp ! Hydrstatic relation and inverse of. |
---|
3359 | real(r8) senv ! Environmental entropy at each grid point. |
---|
3360 | real(r8) qtenv ! Environmental total water " " ". |
---|
3361 | real(r8) penv ! Environmental total pressure " " ". |
---|
3362 | real(r8) tenv ! Environmental total temperature " " ". |
---|
3363 | real(r8) new_s ! Hold value for entropy after condensation/freezing adjustments. |
---|
3364 | real(r8) new_q ! Hold value for total water after condensation/freezing adjustments. |
---|
3365 | real(r8) dp ! Layer thickness (center to center) |
---|
3366 | real(r8) tfguess ! First guess for entropy inversion - crucial for efficiency! |
---|
3367 | real(r8) tscool ! Super cooled temperature offset (in degC) (eg -35). |
---|
3368 | |
---|
3369 | real(r8) qxsk, qxskp1 ! LCL excess water (k, k+1) |
---|
3370 | real(r8) dsdp, dqtdp, dqxsdp ! LCL s, qt, p gradients (k, k+1) |
---|
3371 | real(r8) slcl,qtlcl,qslcl ! LCL s, qt, qs values. |
---|
3372 | |
---|
3373 | integer rcall ! Number of ientropy call for errors recording |
---|
3374 | integer nit_lheat ! Number of iterations for condensation/freezing loop. |
---|
3375 | integer i,k,ii ! Loop counters. |
---|
3376 | |
---|
3377 | !====================================================================== |
---|
3378 | ! SUMMARY |
---|
3379 | ! |
---|
3380 | ! 9/9/04 - Assumes parcel is initiated from level of maxh (klaunch) |
---|
3381 | ! and entrains at each level with a specified entrainment rate. |
---|
3382 | ! |
---|
3383 | ! 15/9/04 - Calculates lcl(i) based on k where qsmix is first < qtmix. |
---|
3384 | ! |
---|
3385 | !====================================================================== |
---|
3386 | ! |
---|
3387 | ! Set some values that may be changed frequently. |
---|
3388 | ! |
---|
3389 | |
---|
3390 | nit_lheat = 2 ! iterations for ds,dq changes from condensation freezing. |
---|
3391 | dmpdz=-1.e-3_r8 ! Entrainment rate. (-ve for /m) |
---|
3392 | !dmpdpc = 3.e-2_r8 ! In cloud entrainment rate (/mb). |
---|
3393 | lwmax = 1.e-3_r8 ! Need to put formula in for this. |
---|
3394 | tscool = 0.0_r8 ! Temp at which water loading freezes in the cloud. |
---|
3395 | |
---|
3396 | qtmix=0._r8 |
---|
3397 | smix=0._r8 |
---|
3398 | |
---|
3399 | qtenv = 0._r8 |
---|
3400 | senv = 0._r8 |
---|
3401 | tenv = 0._r8 |
---|
3402 | penv = 0._r8 |
---|
3403 | |
---|
3404 | qtp0 = 0._r8 |
---|
3405 | sp0 = 0._r8 |
---|
3406 | mp0 = 0._r8 |
---|
3407 | |
---|
3408 | qtp = 0._r8 |
---|
3409 | sp = 0._r8 |
---|
3410 | mp = 0._r8 |
---|
3411 | |
---|
3412 | new_q = 0._r8 |
---|
3413 | new_s = 0._r8 |
---|
3414 | |
---|
3415 | ! **** Begin loops **** |
---|
3416 | |
---|
3417 | do k = pver, msg+1, -1 |
---|
3418 | do i=1,ncol |
---|
3419 | |
---|
3420 | ! Initialize parcel values at launch level. |
---|
3421 | |
---|
3422 | if (k == klaunch(i)) then |
---|
3423 | qtp0(i) = q(i,k) ! Parcel launch total water (assuming subsaturated) - OK????. |
---|
3424 | sp0(i) = entropy(t(i,k),p(i,k),qtp0(i)) ! Parcel launch entropy. |
---|
3425 | mp0(i) = 1._r8 ! Parcel launch relative mass (i.e. 1 parcel stays 1 parcel for dmpdp=0, undilute). |
---|
3426 | smix(i,k) = sp0(i) |
---|
3427 | qtmix(i,k) = qtp0(i) |
---|
3428 | tfguess = t(i,k) |
---|
3429 | rcall = 1 |
---|
3430 | call ientropy (rcall,i,lchnk,smix(i,k),p(i,k),qtmix(i,k),tmix(i,k),qsmix(i,k),tfguess) |
---|
3431 | end if |
---|
3432 | |
---|
3433 | ! Entraining levels |
---|
3434 | |
---|
3435 | if (k < klaunch(i)) then |
---|
3436 | |
---|
3437 | ! Set environmental values for this level. |
---|
3438 | |
---|
3439 | dp = (p(i,k)-p(i,k+1)) ! In -ve mb as p decreasing with height - difference between center of layers. |
---|
3440 | qtenv = 0.5_r8*(q(i,k)+q(i,k+1)) ! Total water of environment. |
---|
3441 | tenv = 0.5_r8*(t(i,k)+t(i,k+1)) |
---|
3442 | penv = 0.5_r8*(p(i,k)+p(i,k+1)) |
---|
3443 | |
---|
3444 | senv = entropy(tenv,penv,qtenv) ! Entropy of environment. |
---|
3445 | |
---|
3446 | ! Determine fractional entrainment rate /pa given value /m. |
---|
3447 | |
---|
3448 | dpdz = -(penv*grav)/(rgas*tenv) ! in mb/m since p in mb. |
---|
3449 | dzdp = 1._r8/dpdz ! in m/mb |
---|
3450 | dmpdp = dmpdz*dzdp ! /mb Fractional entrainment |
---|
3451 | |
---|
3452 | ! Sum entrainment to current level |
---|
3453 | ! entrains q,s out of intervening dp layers, in which linear variation is assumed |
---|
3454 | ! so really it entrains the mean of the 2 stored values. |
---|
3455 | |
---|
3456 | sp(i) = sp(i) - dmpdp*dp*senv |
---|
3457 | qtp(i) = qtp(i) - dmpdp*dp*qtenv |
---|
3458 | mp(i) = mp(i) - dmpdp*dp |
---|
3459 | |
---|
3460 | ! Entrain s and qt to next level. |
---|
3461 | |
---|
3462 | smix(i,k) = (sp0(i) + sp(i)) / (mp0(i) + mp(i)) |
---|
3463 | qtmix(i,k) = (qtp0(i) + qtp(i)) / (mp0(i) + mp(i)) |
---|
3464 | |
---|
3465 | ! Invert entropy from s and q to determine T and saturation-capped q of mixture. |
---|
3466 | ! t(i,k) used as a first guess so that it converges faster. |
---|
3467 | |
---|
3468 | tfguess = tmix(i,k+1) |
---|
3469 | rcall = 2 |
---|
3470 | call ientropy(rcall,i,lchnk,smix(i,k),p(i,k),qtmix(i,k),tmix(i,k),qsmix(i,k),tfguess) |
---|
3471 | |
---|
3472 | ! |
---|
3473 | ! Determine if this is lcl of this column if qsmix <= qtmix. |
---|
3474 | ! FIRST LEVEL where this happens on ascending. |
---|
3475 | |
---|
3476 | if (qsmix(i,k) <= qtmix(i,k) .and. qsmix(i,k+1) > qtmix(i,k+1)) then |
---|
3477 | lcl(i) = k |
---|
3478 | qxsk = qtmix(i,k) - qsmix(i,k) |
---|
3479 | qxskp1 = qtmix(i,k+1) - qsmix(i,k+1) |
---|
3480 | dqxsdp = (qxsk - qxskp1)/dp |
---|
3481 | pl(i) = p(i,k+1) - qxskp1/dqxsdp ! pressure level of actual lcl. |
---|
3482 | dsdp = (smix(i,k) - smix(i,k+1))/dp |
---|
3483 | dqtdp = (qtmix(i,k) - qtmix(i,k+1))/dp |
---|
3484 | slcl = smix(i,k+1) + dsdp* (pl(i)-p(i,k+1)) |
---|
3485 | qtlcl = qtmix(i,k+1) + dqtdp*(pl(i)-p(i,k+1)) |
---|
3486 | |
---|
3487 | tfguess = tmix(i,k) |
---|
3488 | rcall = 3 |
---|
3489 | call ientropy (rcall,i,lchnk,slcl,pl(i),qtlcl,tl(i),qslcl,tfguess) |
---|
3490 | |
---|
3491 | ! write(iulog,*)' ' |
---|
3492 | ! write(iulog,*)' p',p(i,k+1),pl(i),p(i,lcl(i)) |
---|
3493 | ! write(iulog,*)' t',tmix(i,k+1),tl(i),tmix(i,lcl(i)) |
---|
3494 | ! write(iulog,*)' s',smix(i,k+1),slcl,smix(i,lcl(i)) |
---|
3495 | ! write(iulog,*)'qt',qtmix(i,k+1),qtlcl,qtmix(i,lcl(i)) |
---|
3496 | ! write(iulog,*)'qs',qsmix(i,k+1),qslcl,qsmix(i,lcl(i)) |
---|
3497 | |
---|
3498 | endif |
---|
3499 | ! |
---|
3500 | end if ! k < klaunch |
---|
3501 | |
---|
3502 | |
---|
3503 | end do ! Levels loop |
---|
3504 | end do ! Columns loop |
---|
3505 | |
---|
3506 | !!!!!!!!!!!!!!!!!!!!!!!!!!END ENTRAINMENT LOOP!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
---|
3507 | |
---|
3508 | !! Could stop now and test with this as it will provide some estimate of buoyancy |
---|
3509 | !! without the effects of freezing/condensation taken into account for tmix. |
---|
3510 | |
---|
3511 | !! So we now have a profile of entropy and total water of the entraining parcel |
---|
3512 | !! Varying with height from the launch level klaunch parcel=environment. To the |
---|
3513 | !! top allowed level for the existence of convection. |
---|
3514 | |
---|
3515 | !! Now we have to adjust these values such that the water held in vaopor is < or |
---|
3516 | !! = to qsmix. Therefore, we assume that the cloud holds a certain amount of |
---|
3517 | !! condensate (lwmax) and the rest is rained out (xsh2o). This, obviously |
---|
3518 | !! provides latent heating to the mixed parcel and so this has to be added back |
---|
3519 | !! to it. But does this also increase qsmix as well? Also freezing processes |
---|
3520 | |
---|
3521 | |
---|
3522 | xsh2o = 0._r8 |
---|
3523 | ds_xsh2o = 0._r8 |
---|
3524 | ds_freeze = 0._r8 |
---|
3525 | |
---|
3526 | !!!!!!!!!!!!!!!!!!!!!!!!!PRECIPITATION/FREEZING LOOP!!!!!!!!!!!!!!!!!!!!!!!!!! |
---|
3527 | !! Iterate solution twice for accuracy |
---|
3528 | |
---|
3529 | |
---|
3530 | |
---|
3531 | do k = pver, msg+1, -1 |
---|
3532 | do i=1,ncol |
---|
3533 | |
---|
3534 | ! Initialize variables at k=klaunch |
---|
3535 | |
---|
3536 | if (k == klaunch(i)) then |
---|
3537 | |
---|
3538 | ! Set parcel values at launch level assume no liquid water. |
---|
3539 | |
---|
3540 | tp(i,k) = tmix(i,k) |
---|
3541 | qstp(i,k) = q(i,k) |
---|
3542 | tpv(i,k) = (tp(i,k) + tpert(i)) * (1._r8+1.608_r8*qstp(i,k)) / (1._r8+qstp(i,k)) |
---|
3543 | |
---|
3544 | end if |
---|
3545 | |
---|
3546 | if (k < klaunch(i)) then |
---|
3547 | |
---|
3548 | ! Initiaite loop if switch(2) = .T. - RBN:DILUTE - TAKEN OUT BUT COULD BE RETURNED LATER. |
---|
3549 | |
---|
3550 | ! Iterate nit_lheat times for s,qt changes. |
---|
3551 | |
---|
3552 | do ii=0,nit_lheat-1 |
---|
3553 | |
---|
3554 | ! Rain (xsh2o) is excess condensate, bar LWMAX (Accumulated loss from qtmix). |
---|
3555 | |
---|
3556 | xsh2o(i,k) = max (0._r8, qtmix(i,k) - qsmix(i,k) - lwmax) |
---|
3557 | |
---|
3558 | ! Contribution to ds from precip loss of condensate (Accumulated change from smix).(-ve) |
---|
3559 | |
---|
3560 | ds_xsh2o(i,k) = ds_xsh2o(i,k+1) - cpliq * log (tmix(i,k)/tfreez) * max(0._r8,(xsh2o(i,k)-xsh2o(i,k+1))) |
---|
3561 | ! |
---|
3562 | ! Entropy of freezing: latice times amount of water involved divided by T. |
---|
3563 | ! |
---|
3564 | |
---|
3565 | if (tmix(i,k) <= tfreez+tscool .and. ds_freeze(i,k+1) == 0._r8) then ! One off freezing of condensate. |
---|
3566 | ds_freeze(i,k) = (latice/tmix(i,k)) * max(0._r8,qtmix(i,k)-qsmix(i,k)-xsh2o(i,k)) ! Gain of LH |
---|
3567 | end if |
---|
3568 | |
---|
3569 | if (tmix(i,k) <= tfreez+tscool .and. ds_freeze(i,k+1) /= 0._r8) then ! Continual freezing of additional condensate. |
---|
3570 | ds_freeze(i,k) = ds_freeze(i,k+1)+(latice/tmix(i,k)) * max(0._r8,(qsmix(i,k+1)-qsmix(i,k))) |
---|
3571 | end if |
---|
3572 | |
---|
3573 | ! Adjust entropy and accordingly to sum of ds (be careful of signs). |
---|
3574 | |
---|
3575 | new_s = smix(i,k) + ds_xsh2o(i,k) + ds_freeze(i,k) |
---|
3576 | |
---|
3577 | ! Adjust liquid water and accordingly to xsh2o. |
---|
3578 | |
---|
3579 | new_q = qtmix(i,k) - xsh2o(i,k) |
---|
3580 | |
---|
3581 | ! Invert entropy to get updated Tmix and qsmix of parcel. |
---|
3582 | |
---|
3583 | tfguess = tmix(i,k) |
---|
3584 | rcall =4 |
---|
3585 | call ientropy (rcall,i,lchnk,new_s, p(i,k), new_q, tmix(i,k), qsmix(i,k), tfguess) |
---|
3586 | |
---|
3587 | end do ! Iteration loop for freezing processes. |
---|
3588 | |
---|
3589 | ! tp - Parcel temp is temp of mixture. |
---|
3590 | ! tpv - Parcel v. temp should be density temp with new_q total water. |
---|
3591 | |
---|
3592 | tp(i,k) = tmix(i,k) |
---|
3593 | |
---|
3594 | ! tpv = tprho in the presence of condensate (i.e. when new_q > qsmix) |
---|
3595 | |
---|
3596 | if (new_q > qsmix(i,k)) then ! Super-saturated so condensate present - reduces buoyancy. |
---|
3597 | qstp(i,k) = qsmix(i,k) |
---|
3598 | else ! Just saturated/sub-saturated - no condensate virtual effects. |
---|
3599 | qstp(i,k) = new_q |
---|
3600 | end if |
---|
3601 | |
---|
3602 | tpv(i,k) = (tp(i,k)+tpert(i))* (1._r8+1.608_r8*qstp(i,k)) / (1._r8+ new_q) |
---|
3603 | |
---|
3604 | end if ! k < klaunch |
---|
3605 | |
---|
3606 | end do ! Loop for columns |
---|
3607 | |
---|
3608 | end do ! Loop for vertical levels. |
---|
3609 | |
---|
3610 | |
---|
3611 | return |
---|
3612 | end subroutine parcel_dilute |
---|
3613 | |
---|
3614 | !----------------------------------------------------------------------------------------- |
---|
3615 | real(r8) function entropy(TK,p,qtot) |
---|
3616 | !----------------------------------------------------------------------------------------- |
---|
3617 | ! |
---|
3618 | ! TK(K),p(mb),qtot(kg/kg) |
---|
3619 | ! from Raymond and Blyth 1992 |
---|
3620 | ! |
---|
3621 | real(r8), intent(in) :: p,qtot,TK |
---|
3622 | real(r8) :: qv,qsat,e,esat,L,eref,pref |
---|
3623 | |
---|
3624 | pref = 1000.0_r8 ! mb |
---|
3625 | eref = 6.106_r8 ! sat p at tfreez (mb) |
---|
3626 | |
---|
3627 | L = rl - (cpliq - cpwv)*(TK-tfreez) ! T IN CENTIGRADE |
---|
3628 | |
---|
3629 | ! Replace call to satmixutils. |
---|
3630 | |
---|
3631 | esat = c1*exp(c2*(TK-tfreez)/(c3+TK-tfreez)) ! esat(T) in mb |
---|
3632 | qsat=eps1*esat/(p-esat) ! Sat. mixing ratio (in kg/kg). |
---|
3633 | |
---|
3634 | qv = min(qtot,qsat) ! Partition qtot into vapor part only. |
---|
3635 | e = qv*p / (eps1 +qv) |
---|
3636 | |
---|
3637 | entropy = (cpres + qtot*cpliq)*log( TK/tfreez) - rgas*log( (p-e)/pref ) + & |
---|
3638 | L*qv/TK - qv*rh2o*log(qv/qsat) |
---|
3639 | ! |
---|
3640 | return |
---|
3641 | end FUNCTION entropy |
---|
3642 | |
---|
3643 | ! |
---|
3644 | !----------------------------------------------------------------------------------------- |
---|
3645 | SUBROUTINE ientropy (rcall,icol,lchnk,s,p,qt,T,qsat,Tfg) |
---|
3646 | !----------------------------------------------------------------------------------------- |
---|
3647 | ! |
---|
3648 | ! p(mb), Tfg/T(K), qt/qv(kg/kg), s(J/kg). |
---|
3649 | ! Inverts entropy, pressure and total water qt |
---|
3650 | ! for T and saturated vapor mixing ratio |
---|
3651 | ! |
---|
3652 | #ifndef WRF_PORT |
---|
3653 | use phys_grid, only: get_rlon_p, get_rlat_p |
---|
3654 | #endif |
---|
3655 | |
---|
3656 | integer, intent(in) :: icol, lchnk, rcall |
---|
3657 | real(r8), intent(in) :: s, p, Tfg, qt |
---|
3658 | real(r8), intent(out) :: qsat, T |
---|
3659 | real(r8) :: qv,Ts,dTs,fs1,fs2,esat |
---|
3660 | real(r8) :: pref,eref,L,e |
---|
3661 | real(r8) :: this_lat,this_lon |
---|
3662 | integer :: LOOPMAX,i |
---|
3663 | |
---|
3664 | LOOPMAX = 100 !* max number of iteration loops |
---|
3665 | |
---|
3666 | ! Values for entropy |
---|
3667 | pref = 1000.0_r8 ! mb ref pressure. |
---|
3668 | eref = 6.106_r8 ! sat p at tfreez (mb) |
---|
3669 | |
---|
3670 | ! Invert the entropy equation -- use Newton's method |
---|
3671 | |
---|
3672 | Ts = Tfg ! Better first guess based on Tprofile from conv. |
---|
3673 | |
---|
3674 | converge: do i=0, LOOPMAX |
---|
3675 | |
---|
3676 | L = rl - (cpliq - cpwv)*(Ts-tfreez) |
---|
3677 | |
---|
3678 | esat = c1*exp(c2*(Ts-tfreez)/(c3+Ts-tfreez)) ! Bolton (eq. 10) |
---|
3679 | qsat = eps1*esat/(p-esat) |
---|
3680 | qv = min(qt,qsat) |
---|
3681 | e = qv*p / (eps1 +qv) ! Bolton (eq. 16) |
---|
3682 | fs1 = (cpres + qt*cpliq)*log( Ts/tfreez ) - rgas*log( (p-e)/pref ) + & |
---|
3683 | L*qv/Ts - qv*rh2o*log(qv/qsat) - s |
---|
3684 | |
---|
3685 | L = rl - (cpliq - cpwv)*(Ts-1._r8-tfreez) |
---|
3686 | |
---|
3687 | esat = c1*exp(c2*(Ts-1._r8-tfreez)/(c3+Ts-1._r8-tfreez)) |
---|
3688 | qsat = eps1*esat/(p-esat) |
---|
3689 | qv = min(qt,qsat) |
---|
3690 | e = qv*p / (eps1 +qv) |
---|
3691 | fs2 = (cpres + qt*cpliq)*log( (Ts-1._r8)/tfreez ) - rgas*log( (p-e)/pref ) + & |
---|
3692 | L*qv/(Ts-1._r8) - qv*rh2o*log(qv/qsat) - s |
---|
3693 | |
---|
3694 | dTs = fs1/(fs2 - fs1) |
---|
3695 | Ts = Ts+dTs |
---|
3696 | if (abs(dTs).lt.0.001_r8) exit converge |
---|
3697 | if (i .eq. LOOPMAX - 1) then |
---|
3698 | #ifndef WRF_PORT |
---|
3699 | this_lat = get_rlat_p(lchnk, icol)*57.296_r8 |
---|
3700 | this_lon = get_rlon_p(lchnk, icol)*57.296_r8 |
---|
3701 | #else |
---|
3702 | !Do not worry about the specific lat/lon in WRF |
---|
3703 | this_lat = 0. |
---|
3704 | this_lon = 0. |
---|
3705 | #endif |
---|
3706 | write(iulog,*) '*** ZM_CONV: IENTROPY: Failed and about to exit, info follows ****' |
---|
3707 | #ifdef WRF_PORT |
---|
3708 | call wrf_message(iulog) |
---|
3709 | #endif |
---|
3710 | write(iulog,100) 'ZM_CONV: IENTROPY. Details: call#,lchnk,icol= ',rcall,lchnk,icol, & |
---|
3711 | ' lat: ',this_lat,' lon: ',this_lon, & |
---|
3712 | ' P(mb)= ', p, ' Tfg(K)= ', Tfg, ' qt(g/kg) = ', 1000._r8*qt, & |
---|
3713 | ' qsat(g/kg) = ', 1000._r8*qsat,', s(J/kg) = ',s |
---|
3714 | #ifdef WRF_PORT |
---|
3715 | call wrf_message(iulog) |
---|
3716 | #endif |
---|
3717 | call endrun('**** ZM_CONV IENTROPY: Tmix did not converge ****') |
---|
3718 | end if |
---|
3719 | enddo converge |
---|
3720 | |
---|
3721 | ! Replace call to satmixutils. |
---|
3722 | |
---|
3723 | esat = c1*exp(c2*(Ts-tfreez)/(c3+Ts-tfreez)) |
---|
3724 | qsat=eps1*esat/(p-esat) |
---|
3725 | |
---|
3726 | qv = min(qt,qsat) ! /* check for saturation */ |
---|
3727 | T = Ts |
---|
3728 | |
---|
3729 | 100 format (A,I1,I4,I4,7(A,F6.2)) |
---|
3730 | |
---|
3731 | return |
---|
3732 | end SUBROUTINE ientropy |
---|
3733 | |
---|
3734 | end module module_cu_camzm |
---|