Skip to content

Commit 435d30b

Browse files
Haipeng Linhplin-ucar
authored andcommitted
Add MAM portable science from CAM: schemes/modal_aero + microp_aero ndrop
Verbatim copies (r8 swept to kind_phys) of the portable science split out of CAM's modal aerosol code: calcsize, wateruptake, gasaerexch, rename, newnuc, coag, setsox (+ cldaero/sox_cldaero), wetdep, convproc, activate, drydep (+ dust_sediment), dust + seasalt emissions (+ dust_common/sslt_sections), and ndrop (dropmixnuc). Bit-for-bit validated in CAM regression testing on the CAM-side refactor branch and per-scheme against CAM snapshots in CAM-SIMA. CAM builds these files directly through the atmos_phys external; CCPP wrappers and suite infrastructure follow in later PRs.
1 parent 702918e commit 435d30b

20 files changed

Lines changed: 16848 additions & 0 deletions

schemes/microp_aero/ndrop.F90

Lines changed: 1076 additions & 0 deletions
Large diffs are not rendered by default.

schemes/modal_aero/aero_activate.F90

Lines changed: 429 additions & 0 deletions
Large diffs are not rendered by default.

schemes/modal_aero/aero_convproc.F90

Lines changed: 1698 additions & 0 deletions
Large diffs are not rendered by default.

schemes/modal_aero/aero_drydep_core.F90

Lines changed: 319 additions & 0 deletions
Large diffs are not rendered by default.

schemes/modal_aero/cldaero_mod.F90

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
!----------------------------------------------------------------------------------
2+
! low level utility module for cloud aerosols
3+
!
4+
! Created by Francis Vitt
5+
!
6+
! Portable (CCPP-ready): array sizes are runtime arguments and host constants
7+
! are passed in; no CAM infrastructure dependencies.
8+
!----------------------------------------------------------------------------------
9+
module cldaero_mod
10+
11+
use ccpp_kinds, only: kind_phys
12+
13+
implicit none
14+
private
15+
16+
public :: cldaero_uptakerate
17+
public :: cldaero_conc_t
18+
public :: cldaero_allocate
19+
public :: cldaero_deallocate
20+
21+
type cldaero_conc_t
22+
real(kind_phys), pointer :: so4c(:,:)
23+
real(kind_phys), pointer :: nh4c(:,:)
24+
real(kind_phys), pointer :: no3c(:,:)
25+
real(kind_phys), pointer :: xlwc(:,:)
26+
real(kind_phys) :: so4_fact
27+
end type cldaero_conc_t
28+
29+
contains
30+
31+
!----------------------------------------------------------------------------------
32+
!----------------------------------------------------------------------------------
33+
function cldaero_allocate( ncol, pver ) result( cldconc )
34+
integer, intent(in) :: ncol ! number of columns in chunk
35+
integer, intent(in) :: pver ! number of vertical levels
36+
37+
type(cldaero_conc_t), pointer:: cldconc
38+
39+
allocate( cldconc )
40+
allocate( cldconc%so4c(ncol,pver) )
41+
allocate( cldconc%nh4c(ncol,pver) )
42+
allocate( cldconc%no3c(ncol,pver) )
43+
allocate( cldconc%xlwc(ncol,pver) )
44+
45+
cldconc%so4c(:,:) = 0._kind_phys
46+
cldconc%nh4c(:,:) = 0._kind_phys
47+
cldconc%no3c(:,:) = 0._kind_phys
48+
cldconc%xlwc(:,:) = 0._kind_phys
49+
cldconc%so4_fact = 2._kind_phys
50+
51+
end function cldaero_allocate
52+
53+
!----------------------------------------------------------------------------------
54+
!----------------------------------------------------------------------------------
55+
subroutine cldaero_deallocate( cldconc )
56+
type(cldaero_conc_t), pointer :: cldconc
57+
58+
if ( associated(cldconc%so4c) ) then
59+
deallocate(cldconc%so4c)
60+
nullify(cldconc%so4c)
61+
endif
62+
63+
if ( associated(cldconc%nh4c) ) then
64+
deallocate(cldconc%nh4c)
65+
nullify(cldconc%nh4c)
66+
endif
67+
68+
if ( associated(cldconc%no3c) ) then
69+
deallocate(cldconc%no3c)
70+
nullify(cldconc%no3c)
71+
endif
72+
73+
if ( associated(cldconc%xlwc) ) then
74+
deallocate(cldconc%xlwc)
75+
nullify(cldconc%xlwc)
76+
endif
77+
78+
deallocate( cldconc )
79+
nullify( cldconc )
80+
81+
end subroutine cldaero_deallocate
82+
83+
!----------------------------------------------------------------------------------
84+
! utility function for cloud-borne aerosols
85+
!----------------------------------------------------------------------------------
86+
87+
function cldaero_uptakerate( xl, cldnum, cfact, cldfrc, tfld, press, pi ) result( uptkrate )
88+
89+
real(kind_phys), intent(in) :: xl, cldnum, cfact, cldfrc, tfld, press
90+
real(kind_phys), intent(in) :: pi ! host value of pi (passed for bit-for-bit consistency)
91+
92+
real(kind_phys) :: uptkrate
93+
94+
real(kind_phys) :: &
95+
rad_cd, radxnum_cd, num_cd, &
96+
gasdiffus, gasspeed, knudsen, &
97+
fuchs_sutugin, volx34pi_cd
98+
99+
!-----------------------------------------------------------------------
100+
! compute uptake of h2so4 and msa to cloud water
101+
!
102+
! first-order uptake rate is
103+
! 4*pi*(drop radius)*(drop number conc)
104+
! *(gas diffusivity)*(fuchs sutugin correction)
105+
106+
! num_cd = (drop number conc in 1/cm^3)
107+
num_cd = 1.0e-3_kind_phys*cldnum*cfact/cldfrc
108+
num_cd = max( num_cd, 0.0_kind_phys )
109+
110+
! rad_cd = (drop radius in cm), computed from liquid water and drop number,
111+
! then bounded by 0.5 and 50.0 micrometers
112+
! radxnum_cd = (drop radius)*(drop number conc)
113+
! volx34pi_cd = (3/4*pi) * (liquid water volume in cm^3/cm^3)
114+
115+
volx34pi_cd = xl*0.75_kind_phys/pi
116+
117+
! following holds because volx34pi_cd = num_cd*(rad_cd**3)
118+
radxnum_cd = (volx34pi_cd*num_cd*num_cd)**0.3333333_kind_phys
119+
120+
! apply bounds to rad_cd to avoid the occasional unphysical value
121+
if (radxnum_cd .le. volx34pi_cd*4.0e4_kind_phys) then
122+
radxnum_cd = volx34pi_cd*4.0e4_kind_phys
123+
rad_cd = 50.0e-4_kind_phys
124+
else if (radxnum_cd .ge. volx34pi_cd*4.0e8_kind_phys) then
125+
radxnum_cd = volx34pi_cd*4.0e8_kind_phys
126+
rad_cd = 0.5e-4_kind_phys
127+
else
128+
rad_cd = radxnum_cd/num_cd
129+
end if
130+
131+
! gasdiffus = h2so4 gas diffusivity from mosaic code (cm^2/s)
132+
! (pmid must be Pa)
133+
gasdiffus = 0.557_kind_phys * (tfld**1.75_kind_phys) / press
134+
135+
! gasspeed = h2so4 gas mean molecular speed from mosaic code (cm/s)
136+
gasspeed = 1.455e4_kind_phys * sqrt(tfld/98.0_kind_phys)
137+
138+
! knudsen number
139+
knudsen = 3.0_kind_phys*gasdiffus/(gasspeed*rad_cd)
140+
141+
! following assumes accomodation coefficient = 0.65
142+
! (Adams & Seinfeld, 2002, JGR, and references therein)
143+
! fuchs_sutugin = (0.75*accom*(1. + knudsen)) /
144+
! (knudsen*(1.0 + knudsen + 0.283*accom) + 0.75*accom)
145+
fuchs_sutugin = (0.4875_kind_phys*(1._kind_phys + knudsen)) / &
146+
(knudsen*(1.184_kind_phys + knudsen) + 0.4875_kind_phys)
147+
148+
! instantaneous uptake rate
149+
uptkrate = 12.56637_kind_phys*radxnum_cd*gasdiffus*fuchs_sutugin
150+
151+
end function cldaero_uptakerate
152+
153+
end module cldaero_mod

0 commit comments

Comments
 (0)