1 MODULE module_shcu_camuwshcu_driver
2 USE shr_kind_mod, only: r8 => shr_kind_r8
4 ! Roughly based on convect_shallow_tend in convect_shallow.F90 from CAM
5 ! but tailored for the UW shallow cumulus scheme.
7 !-------------------------------------------
8 !Future modifications and important warnings (BSINGH:02/01/2013- Notes from WIG):
9 !===========================================
10 !1. UWShCu is hard-wired for certain moisture variables that could cause trouble
11 ! depending on which MP is used
12 !2. Mixing for rain, snow, and graupel moist vars is commented out.
13 ! For other MP routines that treat this prognostically, we need to implement
14 ! ShCu mixing of these (and other possible) moist species.
15 !3. Fractional occurrence of shallow convection is currently not calculated.
16 !-------------------------------------------
23 PRIVATE !Default to private
24 PUBLIC :: & !Public entities
29 !------------------------------------------------------------------------
30 SUBROUTINE camuwshcu_driver( &
31 ids,ide, jds,jde, kds,kde &
32 ,ims,ime, jms,jme, kms,kme &
33 ,its,ite, jts,jte, kts,kte &
35 ,p, p8w, pi_phy, z, z_at_w, dz8w &
36 ,t_phy, u_phy, v_phy &
37 ,moist, qv, qc, qi, qnc, qni &
41 ,pblh_in, tke_pbl, cldfra, cldfra_old &
42 ,cldfra_old_mp,cldfra_conv, is_CAMMGMP_used &
44 ,cush_inout, pratesh, snowsh, icwmrsh &
45 ,cmfmc, cmfmc2_inout, rprdsh_inout, cbmf_inout &
46 ,cmfsl, cmflq, dlf, dlf2, evapcsh_inout &
47 ,rliq, rliq2_inout, cubot, cutop &
48 ,rushten, rvshten, rthshten &
49 ,rqvshten, rqcshten, rqrshten &
50 ,rqishten, rqsshten, rqgshten &
51 ,rqcnshten,rqinshten &
52 ,ht, shfrc3d,itimestep &
54 ! This routine is based on convect_shallow_tend in CAM. It handles the
55 ! mapping of variables from the WRF to the CAM framework for the UW
56 ! shallow convective parameterization.
58 ! Author: William.Gustafson@pnl.gov, Jan. 2010
59 !------------------------------------------------------------------------
60 USE module_state_description, only: param_first_scalar, &
61 p_qc, p_qr, p_qi, p_qs, p_qg, p_qnc, p_qni
62 USE module_cam_support, only: pcols, pver, pcnst =>pcnst_runtime
64 USE module_cam_support, only: cam_mam_aerosols
66 USE constituents, only: cnst_get_ind
67 USE physconst, only: latice,cpair, gravit, latvap
68 USE uwshcu, only: compute_uwshcu_inv
69 USE wv_saturation, only: fqsatd
71 use module_state_description, only: num_chem, param_first_scalar,CBMZ_CAM_MAM3_NOAQ, &
72 CBMZ_CAM_MAM3_AQ,CBMZ_CAM_MAM7_NOAQ,CBMZ_CAM_MAM7_AQ
73 use module_data_cam_mam_asect, only: lptr_chem_to_q, factconv_chem_to_q
74 use module_mp_cammgmp_driver, only: physics_update, physics_ptend_init
77 ! Subroutine arguments...
78 LOGICAL, INTENT(IN) :: is_CAMMGMP_used
79 INTEGER, INTENT(IN ) :: ids,ide, jds,jde, kds,kde, &
80 ims,ime, jms,jme, kms,kme, &
81 its,ite, jts,jte, kts,kte, &
84 INTEGER, INTENT(IN ) :: chem_opt
87 REAL, DIMENSION( ims:ime, kms:kme, jms:jme, num_moist ), INTENT(IN) :: &
88 moist !moist tracer array
90 REAL, DIMENSION( ims:ime, kms:kme, jms:jme, num_chem ), INTENT(INOUT) :: &
91 chem !moist tracer array
94 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), INTENT(IN) :: &
95 cldfra, & !cloud fraction
96 cldfra_old, & !previous time step cloud fraction
99 dz8w, & !height between layer interface (m)
100 p, & !pressure at mid-level (Pa)
101 p8w, & !pressure at level interface (Pa)
102 pi_phy, & !exner function, (p0/p)^(R/cpair) (none)
103 qv, & !water vapor mixing ratio (kg/kg-dry air)
104 t_phy, & !temperature (K)
105 tke_pbl, & !turbulent kinetic energy from PBL (m2/s2)
106 u_phy, & !zonal wind component on T points (m/s)
107 v_phy, & !meridional wind component on T points (m/s)
108 z, & !height above sea level at mid-level (m)
109 z_at_w !height above sea level at interface (m)
111 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), INTENT(IN), OPTIONAL :: &
112 qc, & !cloud droplet mixing ratio (kg/kg-dry air)
113 qi, & !cloud ice crystal mixing ratio (kg/kg-dry air)
114 qnc, & !cloud water number concentration (#/kg)
115 qni !cloud ice number concentration (#/kg)
117 REAL, DIMENSION( ims:ime, jms:jme ), INTENT(IN) :: &
118 pblh_in, & !height of PBL (m)
119 ht !Terrain height (m)
121 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), INTENT(INOUT) :: &
122 cldfrash, & !shallow convective cloud fraction
123 cmfmc, & !deep+shalow cloud fraction (already contains deep part from ZM)
124 cmfmc2_inout, & !shallow cloud fraction
125 cmflq, & !convective flux of total water in energy unit (~units)
126 cmfsl, & !convective flux of liquid water static energy (~units)
127 dlf, & !dq/dt due to export of cloud water (input=deep from ZM, output=deep+shallow)
128 evapcsh_inout, & !output array for evaporation of shallow convection precipitation (kg/kg/s)
129 icwmrsh, & !shallow cumulus in-cloud water mixing ratio (kg/m2)
130 rprdsh_inout, & !dq/dt due to deep(~?) & shallow convective rainout (~units?)
131 rushten, & !UNcoupled zonal wind tend from shallow Cu scheme (m/s2)
132 rvshten, & !UNcoupled meridional wind tend from shallow Cu scheme (m/s2)
133 rthshten, & !UNcoupled potential temperature tendendcy from shallow cu scheme (K/s)
134 rqvshten, & !UNcoupled water vapor mixing ratio tend from shallow Cu scheme (kg/kg/s)
135 rqcshten, & !UNcoupled clod droplet mixing ratio tend from shallow Cu scheme (kg/kg/s)
136 rqrshten, & !UNcoupled raindrop mixing ratio tend from shallow Cu scheme (kg/kg/s)
137 rqishten, & !UNcoupled ice crystal mixing ratio tend from shallow Cu scheme (kg/kg/s)
138 rqsshten, & !UNcoupled snow mixing ratio tend from shallow Cu scheme (kg/kg/s)
139 rqgshten, & !UNcoupled graupel mixing ratio tend from shallow Cu scheme (kg/kg/s)
144 REAL, DIMENSION( ims:ime, jms:jme ), INTENT(INOUT) :: &
145 cbmf_inout, & !cloud base mass flux (kg/m2/s)
146 cubot, & !level number of base of convection
147 cutop, & !level number of top of convection
148 cush_inout, & !convective scale height (~units?)
149 pratesh, & !time-step shallow cumulus precip rate at surface (mm/s)
150 rliq, & !vertically-integrated reserved cloud condensate (m/s)
151 rliq2_inout, & !vertically-integrated reserved cloud condensate for shallow (m/s)
152 snowsh !accumulated convective snow rate at surface for shallow Cu (m/s) ~are these the units we should use for WRF?
154 REAL, INTENT(IN) :: &
157 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), INTENT(OUT) :: &
158 dlf2 ! Required by CAMMGMP Microphysics
159 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), INTENT(OUT) :: &
160 shfrc3d !Shallow cloud fraction
163 !Variables dimensioned for input to CAM routines
164 REAL(r8), DIMENSION(pcols, kte, pcnst) :: &
165 moist8, & !tracer array for CAM routines
166 tnd_tracer !tracer tendency
168 REAL(r8), DIMENSION(pcols, kte+1) :: &
169 pint8, & !pressure at layer interface (Pa)
170 zi8, & !height above the ground at interfaces (m)
171 tke8, & !turbulent kinetic energy at level interfaces (m2/s2)
172 slflx, & !convective liquid water static energy flux (~units?)
173 qtflx, & !convective total water flux (~units?)
174 flxprec, & ! Shallow convective-scale flux of precip (rain+snow) at interfaces [ kg/m2/s ]
175 flxsnow, & ! Shallow convective-scale flux of snow at interfaces [ kg/m2/s ]
176 cmfmc2 !cloud fraction
181 REAL(r8), DIMENSION(pcols, kte) :: &
182 cld8, & !cloud fraction
183 cldold8, & !previous time step cloud fraction ~should this be just the convective part?
184 cmfdqs, & !convective snow production (~units?)
185 evapcsh, & !evaporation of shallow convection precipitation >= 0. (kg/kg/s)
186 iccmr_uw, & !in-cloud cumulus LWC+IWC (kg/m2)
187 icwmr_uw, & !in-cloud cumulus LWC (kg/m2)
188 icimr_uw, & !in-cloud cumulus IWC (kg/m2)
189 pdel8, & !pressure difference between layer interfaces (Pa)
190 pdeldry8, & !pressure difference between layer interfaces for dry atm (Pa)
191 pmid8, & !pressure at layer middle (Pa)
192 qc2, & !dq/dt due to export of cloud water
193 qh8, & !specific humidity (kg/kg-moist air)
194 qc8, & !cloud liquid water (~units?)
195 qi8, & !cloud ice (~units?)
196 qhtnd, & !specific humidity tendency (kg/kg/s)
197 qctnd, & !cloud water mixing ratio tendency
198 qitnd, & !cloud ice mixing ratio tendency
199 rprdsh, & !dq/dt due to deep(~?) & shallow convective rainout (~units?)
200 s8, & !dry static energy (J/kg)
201 shfrc, & !shallow cloud fraction
202 stnd, & !heating rate (dry static energy tendency, W/kg)
203 t8, & !temperature (K)
204 u8, & !environment zonal wind (m/s)
205 utnd, & !zonal wind tendency (m/s2)
206 v8, & !environment meridional wind (m/s)
207 vtnd, & !meridional wind tendency (m/s2)
208 zm8 !height between interfaces (m)
210 REAL(r8), DIMENSION(pcols, kte) :: &
217 REAL(r8), DIMENSION(pcols) :: &
218 cbmf, & !cloud base mass flux (kg/m2/s)
219 cnb2, & !bottom level of convective activity
220 cnt2, & !top level of convective activity
221 cush, & !convective scale height (~units?)
222 pblh, & !pblh height (m)
223 precc, & !convective precip (rain+snow) at surface for shallow Cu (m/s)
224 rliq2, & !vertically-integrated reserved cloud condensate for shallow (m/s)
225 snow !convective snow rate at surface (m/s)
228 REAL(r8) :: ztodt,dum1
229 INTEGER :: i, j, k, kflip, m, mp1
230 INTEGER :: cnb, cnt !index of cloud base and top in CAM world (indices decrease with height)
231 INTEGER :: lchnk !chunk identifier, used to map 2-D to 1-D arrays in WRF
232 INTEGER :: ncnst !number of tracers
233 INTEGER :: ncol !number of atmospheric columns in chunk
234 CHARACTER(LEN=1000) :: msg
236 character*24 :: ptend_name !ptend%name in CAM5 - used in parameterization
237 logical :: ptend_ls !ptend%ls in CAM5 - used for calling physics_update subroutine
238 logical :: ptend_lq(pcnst) !ptend%lq in CAM5
241 real(r8) :: state_s(pcols,kte)
242 real(r8) :: ptend_s(pcols,kte) !Dummy arguments for physics_update call
244 #if ( WRF_CHEM == 1 )
245 !BSINGH:02/01/2013: Sanity check for Non-MAM simulations
246 if(.NOT.cam_mam_aerosols .AND. chem_opt .NE. 0) then
247 write(msg,*)'CAMUWSHACU DRIVER - camuwshcu_driver is valid for only MAM aerosols ', &
248 '(chem_opts:',CBMZ_CAM_MAM3_NOAQ,CBMZ_CAM_MAM3_AQ,CBMZ_CAM_MAM7_NOAQ,CBMZ_CAM_MAM7_AQ ,')'
249 call wrf_error_fatal( msg )
257 ncol = 1 !chunk size in WRF is 1 since we loop over all columns in a tile
258 ncnst = pcnst !Balwinder.Singh@pnnl.gov
261 ! Map variables to inputs for zm_convr and call it...
262 ! Loop over the points in the tile and treat them each as a CAM chunk.
264 ij_loops : do j = jts,jte
266 lchnk = (j-jts)*(ite-its+1) + (i-its+1) !1-D index location from the 2-D tile
268 !Flip variables on the layer interfaces
272 pint8(1,kflip) = p8w(i,k,j)
273 zi8(1,kflip) = z_at_w(i,k,j) - ht(i,j) ! height above the ground at interfaces
276 !Flip variables on the layer middles
279 if(is_CAMMGMP_used) then
280 cld8(1,kflip) = cldfra_old_mp(i,k,j)
281 cldold8(1,kflip) = cldfra_conv(i,k,j)
283 cld8(1,kflip) = cldfra(i,k,j)
284 cldold8(1,kflip) = cldfra_old(i,k,j)
286 if (itimestep .eq. 1) then
287 cld8(1,kflip) = 0._r8
288 cldold8(1,kflip) = 0._r8
290 cld8(1,kflip) = min(max((cld8(1,kflip) + cldold8(1,kflip)),0._r8),1._r8)
292 pdel8(1,kflip) = p8w(i,k,j) - p8w(i,k+1,j)
293 pmid8(1,kflip) = p(i,k,j)
294 qh8(1,kflip) = max( qv(i,k,j)/(1. + qv(i,k,j)), 1e-30 ) !values of 0 cause a crash in entropy
295 if( present(qc) ) then
296 qc8(1,kflip) = qc(i,k,j)/(1. + qv(i,k,j)) !Convert to moist mix ratio
300 if( present(qi) ) then
301 qi8(1,kflip) = qi(i,k,j)/(1. + qv(i,k,j)) !Used in convtran, ditto for conversion
305 pdeldry8(1,kflip)= pdel8(1,kflip)*(1._r8 - qh8(1,kflip))
306 t8(1,kflip) = t_phy(i,k,j)
307 s8(1,kflip) = cpair*t8(1,kflip) + gravit*(z(i,k,j)-ht(i,j))
308 u8(1,kflip) = u_phy(i,k,j)
309 v8(1,kflip) = v_phy(i,k,j)
310 zm8(1,kflip) = z(i,k,j)-ht(i,j)
313 !BSINGH - TKE at the interfaces
317 tke8(1,kflip) = tke_pbl(i,k,j) !Turbulent kinetic energy
320 !Flip the tracer array -
321 !shift tracer dimension down one to remove "blank" index and
322 !convert to wet instead of dry mixing ratios.
326 moist8(1,kflip,1:ncnst) = 0.
328 moist8(1,kflip,1) = max(0.0,qv(i,k,j)/(1. + qv(i,k,j)))
330 call cnst_get_ind( 'CLDLIQ', m )
331 moist8(1,kflip,m) = max(0.0,qc(i,k,j)/(1. + qv(i,k,j)))
333 call cnst_get_ind( 'CLDICE', m )
334 moist8(1,kflip,m) = max(0.0,qi(i,k,j)/(1. + qv(i,k,j)))
336 call cnst_get_ind( 'NUMLIQ', m )
337 moist8(1,kflip,m) = max(0.0,qnc(i,k,j)/(1. + qv(i,k,j)))
339 call cnst_get_ind( 'NUMICE', m )
340 moist8(1,kflip,m) = max(0.0,qni(i,k,j)/(1. + qv(i,k,j)))
342 #if ( WRF_CHEM == 1 )
343 !Following Do-Loop is obtained from chem/module_cam_mam_aerchem_driver.F
344 do l = param_first_scalar, num_chem
345 l2 = lptr_chem_to_q(l)
346 if ((l2 >= 1) .and. (l2 <= pcnst)) then
347 moist8(1,kflip,l2) = max(0.0,chem(i,k,j,l)*factconv_chem_to_q(l))
354 !Some remapping to get arrays to pass into the routine
355 pblh(1) = pblh_in(i,j)
356 cush(1) = cush_inout(i,j)
358 ! Main guts of the routine...
359 ! This is a bit inefficient because we are flippling the arrays and they
360 ! will then get flipped back again by compute_uwshcu_inv. We are doing
361 ! this to preserve the CAM code as much as possible for maintenance.
363 call compute_uwshcu_inv( &
364 pcols, pver, ncol, ncnst, ztodt, &
365 pint8, zi8, pmid8, zm8, pdel8, &
366 u8, v8, qh8, qc8, qi8, &
368 tke8, cld8, cldold8, pblh, cush, &
369 cmfmc2, slflx, qtflx, &
371 qhtnd, qctnd, qitnd, &
372 stnd, utnd, vtnd, tnd_tracer, &
373 rprdsh, cmfdqs, precc, snow, &
374 evapcsh, shfrc, iccmr_UW, icwmr_UW, &
375 icimr_UW, cbmf, qc2, rliq2, &
376 cnt2, cnb2, fqsatd, lchnk, pdeldry8 )
378 ! Map output into WRF-dimensioned arrays...
380 cush_inout(i,j) = cush(1)
384 qc2(1,kflip)=max(0._r8,min(1.e-6_r8,qc2(1,kflip)))
385 if( t8(1,kflip) > 268.15_r8 ) then
387 elseif( t8(1,kflip) < 238.15_r8 ) then
390 dum1 = ( 268.15_r8 - t8(1,kflip) ) / 30._r8
392 qcten_det(1,kflip) = qc2(1,kflip) * ( 1._r8 - dum1 )
393 qiten_det(1,kflip) = qc2(1,kflip) * dum1
394 qcnten_det(1,kflip) = 3._r8 * (qc2(1,kflip) * ( 1._r8 - dum1 ) ) / (4._r8*3.14159_r8*(10.e-6_r8**3)*997._r8)
395 qinten_det(1,kflip) = 3._r8 * (qc2(1,kflip) * dum1 ) / (4._r8*3.14159_r8*(50.e-6_r8**3)*500._r8)
396 qsten_det(1,kflip) = qc2(1,kflip) * dum1 * latice ! liquid to ice heating
400 dlf2(i,k,j) = qc2(1,kflip)
401 shfrc3d(i,k,j) = shfrc(1,kflip) ! Required by CAM's wet scavenging - Balwinder.Singh@pnnl.gov
403 !Add shallow reserved cloud condensate to deep reserved cloud condensate
404 ! dlf (kg/kg/s, qc in CAM), rliq done below
405 dlf(i,k,j) = dlf(i,k,j) + qc2(1,kflip)
407 evapcsh_inout(i,k,j)= evapcsh(1,kflip)
408 icwmrsh(i,k,j) = icwmr_uw(1,kflip)
410 rprdsh(1,kflip) = rprdsh(1,kflip) + cmfdqs(1,kflip)
411 rprdsh_inout(i,k,j) = rprdsh(1,kflip)
412 !Not doing rprdtot for now since not yet used by other CAM routines in WRF
414 !Tendencies of winds, potential temperature, and moisture
415 !fields treated specifically by UW scheme
416 rushten(i,k,j) = utnd(1,kflip)
417 rvshten(i,k,j) = vtnd(1,kflip)
418 rthshten(i,k,j) = (stnd(1,kflip)+qsten_det(1,kflip))/cpair/pi_phy(i,k,j)
419 rqvshten(i,k,j) = qhtnd(1,kflip)*(1. + qv(i,k,j))**2
420 if( p_qc >= param_first_scalar ) &
421 rqcshten(i,k,j) = (qctnd(1,kflip)+qcten_det(1,kflip))*(1. + qv(i,k,j))
422 if( p_qi >= param_first_scalar ) &
423 rqishten(i,k,j) = (qitnd(1,kflip)+qiten_det(1,kflip))*(1. + qv(i,k,j))
425 if( p_qnc >= param_first_scalar ) then
426 call cnst_get_ind( 'NUMLIQ', m )
427 rqcnshten(i,k,j) = (tnd_tracer(1,kflip,m)+qcnten_det(1,kflip))*(1. + qv(i,k,j))
429 if( p_qni >= param_first_scalar ) then
430 call cnst_get_ind( 'NUMICE', m )
431 rqinshten(i,k,j) = (tnd_tracer(1,kflip,m)+qinten_det(1,kflip))*(1. + qv(i,k,j))
433 end do !k-loop to kte
436 #if ( WRF_CHEM == 1 )
437 !BSINGH - update moist8 by physics update call
438 !Update chem array and state constituents
439 !populate state_s, ptend_s, ptend_ls with dummy values (zeros) for physics update call
440 state_s(:,:) = 0.0_r8
441 ptend_s(:,:) = 0.0_r8
444 ptend_lq(1:5) = .FALSE.
445 ptend_name = 'convect_shallow'
448 call physics_update(lchnk,ztodt,moist8,tnd_tracer,state_s,ptend_s,ptend_name,ptend_lq,ptend_ls,pcnst)
451 do l = param_first_scalar, num_chem
452 l2 = lptr_chem_to_q(l)
453 if ((l2 >= 1) .and. (l2 <= pcnst)) then
454 chem(i,k,j,l) = moist8(1,kflip,l2)/factconv_chem_to_q(l)
457 end do !k-loop to kte
464 !Convective fluxes of 'sl' and 'qt' in energy unit
465 cmfsl(i,k,j) = slflx(1,kflip)
466 cmflq(i,k,j) = qtflx(1,kflip)*latvap
467 !BSINGH - Storing CMFMC and CMFMC2 at the interfaces
468 cmfmc2_inout(i,k,j) = cmfmc2(1,kflip)
469 cmfmc(i,k,j) = cmfmc(i,k,j) + cmfmc2(1,kflip)
470 end do !k-loop to kte+1
472 !Calculate fractional occurance of shallow convection
473 !~Not doing this since it would require adding time averaging ability across output times
475 !Rain rate for shallow convection
476 pratesh(i,j) = precc(1)*1e3/dt !~this will need changing for adaptive time steps and cudt
478 !Get indices of convection top and bottom based on deep+shallow
479 !Note: cnt2 and cnb2 have indices decreasing with height, but
480 ! cutop and cubot have indicies increasing with height
481 kflip = kte - cutop(i,j) + 1
483 if( cnt2(1) < kflip ) cnt = cnt2(1)
484 cutop(i,j) = kte - cnt + 1
486 kflip = kte - cubot(i,j) + 1
488 if( cnb2(1) > kflip ) cnb = cnb2(1)
489 cubot(i,j) = kte - cnb + 1
491 !Add shallow reserved cloud condensate to deep reserved cloud condensate
492 !dlf done above, rliq (m/s)
493 rliq2_inout(i,j) = rliq2(1)
494 rliq(i,j) = rliq(i,j) + rliq2(1)
498 END SUBROUTINE camuwshcu_driver
500 END MODULE module_shcu_camuwshcu_driver