Skip to content

Commit a3750e4

Browse files
committed
Add subgrid vertical velocity (wsub) schemes; further clean up ndrop_bam
1 parent f4476a7 commit a3750e4

5 files changed

Lines changed: 287 additions & 88 deletions

File tree

src/chemistry/aerosol/bulk_aerosol_state_mod.F90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ subroutine get_ambient_num(self, bin_ndx, num)
224224

225225
nc = self%ncol()
226226

227-
call rad_cnst_get_aer_mmr(self%list_idx_, bin_ndx, self%state, self%pbuf, mmr)
227+
call self%get_ambient_mmr(species_ndx=1, bin_ndx=bin_ndx, mmr=mmr)
228228
call rad_aer_get_props(self%list_idx_, bin_ndx, num_to_mass_aer=ntm, aername=aname)
229229

230230
! Apply bam_sulfate_scale to sulfate/volcanic aerosol
@@ -519,7 +519,7 @@ subroutine get_bulk_num_and_mass(self, bin_ndx, ncol, rho, naer2, maerosol)
519519
real(r8) :: ntm
520520
character(len=32) :: aname
521521

522-
call rad_cnst_get_aer_mmr(self%list_idx_, bin_ndx, self%state, self%pbuf, mmr)
522+
call self%get_ambient_mmr(species_ndx=1, bin_ndx=bin_ndx, mmr=mmr)
523523
call rad_aer_get_props(self%list_idx_, bin_ndx, num_to_mass_aer=ntm, aername=aname)
524524

525525
! b4b operation order: (mmr * rho) first, then * ntm [* 2.0 for sulfate]
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
! Compute raw subgrid-scale vertical velocity from TKE or KVH.
2+
module compute_subgrid_vertical_velocity
3+
4+
use ccpp_kinds, only: kind_phys
5+
6+
implicit none
7+
private
8+
9+
public :: compute_subgrid_vertical_velocity_tke_run
10+
public :: compute_subgrid_vertical_velocity_kvh_run
11+
12+
contains
13+
14+
!> \section arg_table_compute_subgrid_vertical_velocity_tke_run Argument Table
15+
!! \htmlinclude compute_subgrid_vertical_velocity_tke_run.html
16+
subroutine compute_subgrid_vertical_velocity_tke_run( &
17+
ncol, pver, top_lev, &
18+
tke, &
19+
wsub, &
20+
errmsg, errflg)
21+
22+
! Input arguments
23+
integer, intent(in) :: ncol ! number of columns
24+
integer, intent(in) :: pver ! number of vertical levels
25+
integer, intent(in) :: top_lev ! top vertical level for cloud physics
26+
27+
real(kind_phys), intent(in) :: tke(:, :) ! turbulent kinetic energy at interfaces [m2/s2] (ncol, pver+1)
28+
29+
! Output arguments
30+
real(kind_phys), intent(out) :: wsub(:, :) ! subgrid vertical velocity [m/s] (ncol, pver)
31+
32+
character(len=512), intent(out) :: errmsg
33+
integer, intent(out) :: errflg
34+
35+
! Local variables
36+
integer :: i, k
37+
38+
errmsg = ''
39+
errflg = 0
40+
41+
wsub(:, :top_lev-1) = 0._kind_phys
42+
43+
do k = top_lev, pver
44+
do i = 1, ncol
45+
wsub(i,k) = sqrt(0.5_kind_phys * (tke(i,k) + tke(i,k+1)) * (2._kind_phys / 3._kind_phys))
46+
wsub(i,k) = min(wsub(i,k), 10._kind_phys)
47+
end do
48+
end do
49+
50+
end subroutine compute_subgrid_vertical_velocity_tke_run
51+
52+
!> \section arg_table_compute_subgrid_vertical_velocity_kvh_run Argument Table
53+
!! \htmlinclude compute_subgrid_vertical_velocity_kvh_run.html
54+
subroutine compute_subgrid_vertical_velocity_kvh_run( &
55+
ncol, pver, top_lev, &
56+
kvh, &
57+
wsub, &
58+
errmsg, errflg)
59+
60+
! Input arguments
61+
integer, intent(in) :: ncol ! number of columns
62+
integer, intent(in) :: pver ! number of vertical levels
63+
integer, intent(in) :: top_lev ! top vertical level for cloud physics
64+
65+
real(kind_phys), intent(in) :: kvh(:, :) ! eddy diffusivity for heat at interfaces [m2/s] (ncol, pver+1)
66+
67+
! Output arguments
68+
real(kind_phys), intent(out) :: wsub(:, :) ! subgrid vertical velocity [m/s] (ncol, pver)
69+
70+
character(len=512), intent(out) :: errmsg
71+
integer, intent(out) :: errflg
72+
73+
! Local variables
74+
integer :: i, k
75+
76+
errmsg = ''
77+
errflg = 0
78+
79+
wsub(:, :top_lev-1) = 0._kind_phys
80+
81+
! Get sub-grid vertical velocity from diffusion coefficient.
82+
! Following Morrison et al. 2005, JAS.
83+
! Assume mixing length of 30 m.
84+
! Use maximum sub-grid vertical vel of 10 m/s.
85+
do k = top_lev, pver
86+
do i = 1, ncol
87+
wsub(i,k) = (kvh(i,k) + kvh(i,k+1)) / 2._kind_phys / 30._kind_phys
88+
wsub(i,k) = min(wsub(i,k), 10._kind_phys)
89+
end do
90+
end do
91+
92+
end subroutine compute_subgrid_vertical_velocity_kvh_run
93+
94+
end module compute_subgrid_vertical_velocity

src/physics/cam/microp_aero.F90

Lines changed: 78 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ module microp_aero
2525
use spmd_utils, only: masterproc
2626
use ppgrid, only: pcols, pver, pverp
2727
use ref_pres, only: top_lev => trop_cloud_top_lev
28-
use physconst, only: rair
28+
use physconst, only: rair, gravit, tmelt, cpair, rh2o, rhoh2o, latvap, &
29+
r_universal, mwh2o
2930
use constituents, only: cnst_get_ind
3031
use physics_types, only: physics_state, physics_ptend, physics_ptend_init, physics_ptend_sum, &
3132
physics_state_copy, physics_update
@@ -48,6 +49,10 @@ module microp_aero
4849
use hetfrz_classnuc_cam, only: hetfrz_classnuc_cam_readnl, hetfrz_classnuc_cam_register, hetfrz_classnuc_cam_init, &
4950
hetfrz_classnuc_cam_calc
5051

52+
use compute_subgrid_vertical_velocity, only: compute_subgrid_vertical_velocity_tke_run, &
53+
compute_subgrid_vertical_velocity_kvh_run
54+
use scale_subgrid_vertical_velocity, only: scale_subgrid_vertical_velocity_run
55+
5156
use cam_history, only: addfld, add_default, outfld
5257
use cam_logfile, only: iulog
5358
use cam_abortutils, only: endrun
@@ -312,7 +317,8 @@ subroutine microp_aero_init(phys_state,pbuf2d)
312317
aero_props_bulk => null()
313318
end do
314319

315-
call ndrop_bam_init(masterproc, iulog)
320+
call ndrop_bam_init(masterproc, iulog, &
321+
mwh2o=mwh2o, r_universal=r_universal, tmelt=tmelt, rhoh2o=rhoh2o)
316322

317323
! Set module-level props object for BAM (used by nucleate_ice_cam)
318324
aero_props_obj => aero_props_bulk
@@ -524,7 +530,6 @@ subroutine microp_aero_run ( &
524530
real(r8) :: cldliqf(pcols,pver) ! fractional of total cloud that is liquid
525531
real(r8) :: qcld ! total cloud water
526532
real(r8) :: nctend_mixnuc(pcols,pver)
527-
real(r8) :: dum ! temporary dummy variable
528533
real(r8) :: dmc, ssmc, so4mc ! variables for modal scheme.
529534

530535
! BAM diagnostic output from ndrop_bam_run
@@ -558,7 +563,6 @@ subroutine microp_aero_run ( &
558563
ncol = state1%ncol
559564

560565
itim_old = pbuf_old_tim_idx()
561-
call pbuf_get_field(pbuf, ast_idx, ast, start=(/1,1,itim_old/), kount=(/pcols,pver,1/))
562566

563567
call pbuf_get_field(pbuf, npccn_idx, npccn)
564568

@@ -634,7 +638,6 @@ subroutine microp_aero_run ( &
634638
!cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
635639
! More refined computation of sub-grid vertical velocity
636640
! Set to be zero at the surface by initialization.
637-
638641
select case (trim(eddy_scheme))
639642
case ('diag_TKE')
640643
call pbuf_get_field(pbuf, tke_idx, tke)
@@ -643,42 +646,50 @@ subroutine microp_aero_run ( &
643646
call pbuf_get_field(pbuf, wp2_idx, wp2, start=(/1,1,itim_old/),kount=(/pcols,pverp,1/))
644647
allocate(tke(pcols,pverp))
645648
tke(:ncol,:) = (3._r8/2._r8)*wp2(:ncol,:)
646-
647649
case default
648650
call pbuf_get_field(pbuf, kvh_idx, kvh)
649651
end select
650652

651-
! Set minimum values above top_lev.
652-
wsub(:ncol,:top_lev-1) = wsub_min
653-
wsubi(:ncol,:top_lev-1) = wsubi_min
654-
655-
do k = top_lev, pver
656-
do i = 1, ncol
657-
658-
select case (trim(eddy_scheme))
659-
case ('diag_TKE', 'CLUBB_SGS')
660-
wsub(i,k) = sqrt(0.5_r8*(tke(i,k) + tke(i,k+1))*(2._r8/3._r8))
661-
wsub(i,k) = min(wsub(i,k),10._r8)
662-
case default
663-
! get sub-grid vertical velocity from diff coef.
664-
! following morrison et al. 2005, JAS
665-
! assume mixing length of 30 m
666-
dum = (kvh(i,k) + kvh(i,k+1))/2._r8/30._r8
667-
! use maximum sub-grid vertical vel of 10 m/s
668-
dum = min(dum, 10._r8)
669-
! set wsub to value at current vertical level
670-
wsub(i,k) = dum
671-
end select
672-
673-
wsubi(i,k) = max(wsubi_min, wsub(i,k)) * wsubi_scale
674-
if (.not. use_preexisting_ice) then
675-
wsubi(i,k) = min(wsubi(i,k), 0.2_r8)
676-
endif
677-
678-
wsub(i,k) = max(wsub_min, wsub(i,k)) * wsub_scale
653+
! Compute raw wsub from TKE or KVH via CCPP-ized routines
654+
wsub(:,:) = 0._r8
655+
select case (trim(eddy_scheme))
656+
case ('diag_TKE', 'CLUBB_SGS')
657+
call compute_subgrid_vertical_velocity_tke_run( &
658+
ncol = ncol, &
659+
pver = pver, &
660+
top_lev = top_lev, &
661+
tke = tke(:ncol,:pverp), &
662+
wsub = wsub(:ncol,:pver), &
663+
errmsg = errmsg, &
664+
errflg = errflg)
665+
if(errflg /= 0) call endrun('compute_subgrid_vertical_velocity_tke_run: ' // errmsg)
666+
case default
667+
call compute_subgrid_vertical_velocity_kvh_run( &
668+
ncol = ncol, &
669+
pver = pver, &
670+
top_lev = top_lev, &
671+
kvh = kvh(:ncol,:pverp), &
672+
wsub = wsub(:ncol,:pver), &
673+
errmsg = errmsg, &
674+
errflg = errflg)
675+
if(errflg /= 0) call endrun('compute_subgrid_vertical_velocity_kvh_run: ' // errmsg)
676+
end select
679677

680-
end do
681-
end do
678+
! Apply min/max/scale and derive wsubi (for ice nucleation)
679+
call scale_subgrid_vertical_velocity_run( &
680+
ncol = ncol, &
681+
pver = pver, &
682+
top_lev = top_lev, &
683+
wsub_min = wsub_min, &
684+
wsubi_min = wsubi_min, &
685+
wsub_scale = wsub_scale, &
686+
wsubi_scale = wsubi_scale, &
687+
use_preexisting_ice = use_preexisting_ice, &
688+
wsub = wsub(:ncol,:pver), &
689+
wsubi = wsubi(:ncol,:pver), &
690+
errmsg = errmsg, &
691+
errflg = errflg)
692+
if(errflg /= 0) call endrun('scale_subgrid_vertical_velocity_run: ' // errmsg)
682693

683694
call outfld('WSUB', wsub, pcols, lchnk)
684695
call outfld('WSUBI', wsubi, pcols, lchnk)
@@ -697,18 +708,8 @@ subroutine microp_aero_run ( &
697708
call physics_ptend_sum(ptend_loc, ptend_all, ncol)
698709
call physics_update(state1, ptend_loc, deltatin)
699710

700-
!cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
701-
! get liquid cloud fraction, check for minimum
702-
703-
do k = top_lev, pver
704-
do i = 1, ncol
705-
lcldm(i,k) = max(ast(i,k), mincld)
706-
end do
707-
end do
708-
709711
!cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
710712
! Droplet Activation
711-
712713
if (clim_modal_aero .or. clim_carma_aero) then
713714

714715
! for modal or carma aerosol
@@ -737,6 +738,8 @@ subroutine microp_aero_run ( &
737738

738739
! If not using preexsiting ice, then only use cloudbourne aerosol for the
739740
! liquid clouds. This is the same behavior as CAM5.
741+
!
742+
! ptend_loc is initialized inside dropmixnuc
740743
if (use_preexisting_ice) then
741744
call dropmixnuc( aero_props_obj, aero_state1_obj, &
742745
state1, ptend_loc, deltatin, pbuf, wsub, wsub_min_asf, &
@@ -757,6 +760,11 @@ subroutine microp_aero_run ( &
757760
! for bulk aerosol: activation, contact freezing, CCN diagnostics
758761
! do not run for aquaplanet compsets which also gets in this path.
759762
if (associated(aero_state1_obj)) then
763+
! get liquid cloud fraction. scaling is done within the ndrop_bam scheme.
764+
call pbuf_get_field(pbuf, ast_idx, ast, start=(/1,1,itim_old/), kount=(/pcols,pver,1/))
765+
766+
! ndrop_bam has no tendencies; this is initialized in order
767+
! for ptend_loc accummulation to happen the same as dropmixnuc above.
760768
call physics_ptend_init(ptend_loc, state1%psetcols, 'none')
761769

762770
allocate(ccn_bam(pcols, pver, psat))
@@ -774,12 +782,19 @@ subroutine microp_aero_run ( &
774782
ncol = ncol, &
775783
pver = pver, &
776784
top_lev = top_lev, &
785+
gravit = gravit, &
786+
rair = rair, &
787+
tmelt = tmelt, &
788+
cpair = cpair, &
789+
rh2o = rh2o, &
790+
rhoh2o = rhoh2o, &
791+
latvap = latvap, &
777792
rho = rho(:ncol,:), &
778793
tair = state1%t(:ncol,:), &
779794
wsub = wsub(:ncol,:), &
780795
qcld = state1%q(:ncol,:,cldliq_idx), &
781796
qsmall_in = qsmall, &
782-
lcldm = lcldm(:ncol,:), &
797+
ast = ast(:ncol,:), &
783798
numliq = state1%q(:ncol,:,numliq_idx), &
784799
deltatin = deltatin, &
785800
npccn = npccn(:ncol,:), &
@@ -802,18 +817,17 @@ subroutine microp_aero_run ( &
802817
!cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
803818
! Contact freezing (-40<T<-3 C) (Young, 1974) with hooks into simulated dust
804819
! estimate rndst and nacon for 4 dust bins here to pass to MG microphysics
805-
806-
do k = top_lev, pver
807-
do i = 1, ncol
808-
809-
if (state1%t(i,k) < 269.15_r8) then
810-
811-
if (clim_modal_aero) then
812-
813-
! For modal aerosols:
814-
! use size '3' for dust coarse mode...
815-
! scale by dust fraction in coarse mode
816-
820+
!
821+
! For bulk aerosol contact freezing is handled inside ndrop_bam_run
822+
! (nacon is output from ndrop_bam_run)
823+
! Below for modal aerosol only:
824+
if(clim_modal_aero) then
825+
! For modal aerosols:
826+
! use size '3' for dust coarse mode...
827+
! scale by dust fraction in coarse mode
828+
do k = top_lev, pver
829+
do i = 1, ncol
830+
if (state1%t(i,k) < 269.15_r8) then
817831
dmc = coarse_dust(i,k)
818832
ssmc = coarse_nacl(i,k)
819833

@@ -832,26 +846,20 @@ subroutine microp_aero_run ( &
832846
nacon(i,k,3) = 0._r8
833847
end if
834848

835-
!also redefine parameters based on size...
836-
849+
! also redefine parameters based on size...
837850
rndst(i,k,3) = 0.5_r8*dgnumwet(i,k,mode_coarse_dst_idx)
838851
if (rndst(i,k,3) <= 0._r8) then
839852
rndst(i,k,3) = rn_dst3
840853
end if
841-
842854
end if
843-
844-
! For bulk aerosol contact freezing is handled inside ndrop_bam_run
845-
! nacon is output from ndrop_bam_run
846-
847-
end if
855+
end do
848856
end do
849-
end do
857+
end if
850858

851859
!cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
852860
! BAM diagnostic output (CCN concentration and aerosol number)
853-
854-
if ((.not. clim_modal_aero) .and. (.not.clim_carma_aero) .and. allocated(ccn_bam) .and. allocated(naer2_bam)) then
861+
if ((.not. clim_modal_aero) .and. (.not.clim_carma_aero) .and. & ! not modal / carma
862+
allocated(ccn_bam) .and. allocated(naer2_bam)) then ! and bulk aerosols are active (not aquap)
855863
do l = 1, psat
856864
call outfld(ccn_name(l), ccn_bam(1,1,l), pcols, lchnk)
857865
end do

0 commit comments

Comments
 (0)