Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

noresm2_5_015_cam6_4_041: Updates from ESCOMP/CAM #175

Merged
merged 50 commits into from
Nov 12, 2024
Merged
Changes from 1 commit
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
7fb147f
ESCOMP tag: cam6_3_159
Katetc Apr 26, 2024
bb5275d
ESCOMP tag: cam6_3_160
cacraigucar Apr 29, 2024
d9347d3
ESCOMP tag: cam6_3_161
cacraigucar May 16, 2024
7388ed9
ESCOMP tag: cam6_3_162
cacraigucar Jun 7, 2024
2c7efda
ESCOMP tag: cam6_4_001
brian-eaton Jun 26, 2024
9248c00
ESCOMP tag: cam6_4_002
brian-eaton Jun 26, 2024
5f2ff2a
ESCOMP tag: cam6_4_003
jtruesdal Jun 28, 2024
d4f9cad
ESCOMP tag: cam6_4_004
fvitt Jun 29, 2024
ff0b850
ESCOMP tag: cam6_4_005
brian-eaton Jul 1, 2024
b71ba86
ESCOMP tag: cam6_4_006
brian-eaton Jul 3, 2024
6296a20
ESCOMP tag: cam6_4_007
mwaxmonsky Jul 8, 2024
32f9fb1
ESCOMP tag: cam6_4_008
cacraigucar Jul 10, 2024
f16af07
ESCOMP tag: cam6_4_009
briandobbins Jul 11, 2024
a1cf7dc
ESCOMP tag: cam6_4_010
cacraigucar Jul 18, 2024
b4d10df
ESCOMP tag: cam6_4_011
cacraigucar Jul 19, 2024
7650946
ESCOMP tag: cam6_4_012
fvitt Jul 20, 2024
4bbda45
ESCOMP tag: cam6_4_013
fvitt Jul 21, 2024
1ef560a
ESCOMP tag: cam6_4_014
fvitt Jul 22, 2024
684a411
ESCOMP tag: cam6_4_015
brian-eaton Jul 23, 2024
b02b6cd
ESCOMP tag: cam6_4_016
brian-eaton Jul 25, 2024
d8909f3
ESCOMP tag: cam6_4_017
brian-eaton Jul 30, 2024
1f66131
ESCOMP tag: cam6_4_018
peverwhee Jul 31, 2024
2b54c49
ESCOMP tag: cam6_4_019
Katetc Aug 12, 2024
f129c14
ESCOMP tag: cam6_4_020
fvitt Aug 14, 2024
8345d33
ESCOMP tag: cam6_4_021
jtruesdal Aug 17, 2024
aca174b
ESCOMP tag: cam6_4_022
cacraigucar Aug 20, 2024
8d57af5
ESCOMP tag: cam6_4_023
jtruesdal Aug 26, 2024
731824f
ESCOMP tag: cam6_4_024
brian-eaton Aug 28, 2024
83f6c5a
ESCOMP tag: cam6_4_025
fvitt Aug 28, 2024
e754ac4
ESCOMP tag: cam6_4_026
cacraigucar Aug 29, 2024
37be340
ESCOMP tag: cam6_4_027
fvitt Sep 3, 2024
376be4e
ESCOMP tag: cam6_4_028
fvitt Sep 4, 2024
2194aca
ESCOMP tag: cam6_4_029
fvitt Sep 6, 2024
aac3a11
ESCOMP tag: cam6_4_030
cacraigucar Sep 6, 2024
8ad60d5
ESCOMP tag: cam6_4_031
nusbaume Sep 9, 2024
09c8452
ESCOMP tag: cam6_4_032
peverwhee Sep 10, 2024
faaeca3
ESCOMP tag: cam6_4_033
gdicker1 Sep 13, 2024
cac02cc
ESCOMP tag: cam6_4_034
jimmielin Sep 19, 2024
beefd55
ESCOMP tag: cam6_4_035
fvitt Sep 23, 2024
d730522
ESCOMP tag: cam6_4_036
gdicker1 Sep 24, 2024
619daf3
ESCOMP tag: cam6_4_037
jimmielin Oct 1, 2024
ff54e3b
ESCOMP tag: cam6_4_038
fvitt Oct 1, 2024
a498b62
ESCOMP tag: cam6_4_039
brian-eaton Oct 10, 2024
aa9e3ea
ESCOMP tag: cam6_4_040
nusbaume Oct 15, 2024
7ae4aab
ESCOMP tag: cam6_4_041
fvitt Oct 16, 2024
423db6d
Updates from ESCOMP/CAM
Nov 7, 2024
892b338
Update externals
Nov 11, 2024
ddfde6f
Merge remote-tracking branch 'NorESM/noresm_develop' into UpdateNores…
Nov 12, 2024
18f2652
Add MPAS as an optional dycore
Nov 12, 2024
9bc40e1
Fix typo in fleximod check entry
Nov 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
ESCOMP tag: cam6_4_025
Merge pull request ESCOMP#1096 from fvitt/aerosol_deposition_fluxes

cam6_4_025: Aerosol deposition fluxes

ESCOMP commit: 2f8ec4d
fvitt authored and Steve Goldhaber committed Nov 8, 2024
commit 83f6c5a9a9ff9564707c5688bfd1712db6cfbd61
116 changes: 114 additions & 2 deletions doc/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,5 +1,117 @@
===============================================================

Tag name: cam6_4_025
Originator(s): fvitt, tilmes
Date: 28 Aug 2024
One-line Summary: Repartition dust deposition fluxes passed to surface models
Github PR URL: https://github.com/ESCOMP/CAM/pull/1096

Purpose of changes (include the issue number and title text for each relevant GitHub issue):

Repartition the modal dust deposition fluxes into 4 bulk bins for passing to the surface
models. The aerosol fluxes code was refactored in a generalized way which can easily be
expanded for other aerosol representations, such as CARMA, and aerosol species types.

Describe any changes made to build system: N/A

Describe any changes made to the namelist: N/A

List any changes to the defaults for the boundary datasets: N/A

Describe any substantial timing or memory changes: N/A

Code reviewed by: cacraigucar

List all files eliminated: N/A

List all files added and what they do:
A src/chemistry/aerosol/aero_deposition_cam.F90
- aerosol model independent module that uses aerosol abstract interface
to prepare deposition fluxes passed to surface models

List all existing files that have been modified, and describe the changes:
M src/chemistry/aerosol/aerosol_properties_mod.F90
M src/chemistry/aerosol/modal_aerosol_properties_mod.F90
- add interface for calculating generalized bulk fluxes

M src/chemistry/modal_aero/aero_model.F90
- replace use of modal_aero_deposition with generalized aero_deposition_cam

If there were any failures reported from running test_driver.sh on any test
platform, and checkin with these failures has been OK'd by the gatekeeper,
then copy the lines from the td.*.status files for the failed tests to the
appropriate machine below. All failed tests must be justified.

derecho/intel/aux_cam:
PEND ERP_Ln9.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq9s
- pre-existing failure due to HEMCO not having reproducible results issues #1018 and #856

FAIL SMS_D_Ln9_P1280x1.ne0ARCTICne30x4_ne0ARCTICne30x4_mt12.FHIST.derecho_intel.cam-outfrq9s
FAIL SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.derecho_intel.cam-outfrq9s
- pre-existing failures -- need fix in CLM external

DIFF ERP_D_Ln9.ne30pg3_ne30pg3_mg17.FLTHIST.derecho_intel.cam-outfrq9s
DIFF ERP_D_Ln9.ne30pg3_ne30pg3_mg17.FLTHIST.derecho_intel.cam-outfrq9s_rrtmgp
DIFF ERP_Ld3.f09_f09_mg17.FWHIST.derecho_intel.cam-reduced_hist1d
DIFF ERP_Ln9.C96_C96_mg17.F2000climo.derecho_intel.cam-outfrq9s_mg3
DIFF ERP_Ln9.f09_f09_mg17.F1850.derecho_intel.cam-outfrq9s
DIFF ERP_Ln9.f09_f09_mg17.F2000climo.derecho_intel.cam-outfrq9s
DIFF ERP_Ln9.f09_f09_mg17.F2010climo.derecho_intel.cam-outfrq9s
DIFF ERP_Ln9.f09_f09_mg17.FHIST_BDRD.derecho_intel.cam-outfrq9s
DIFF ERP_Ln9.f19_f19_mg17.FWsc1850.derecho_intel.cam-outfrq9s
DIFF ERP_Ln9.ne30pg3_ne30pg3_mg17.FCnudged.derecho_intel.cam-outfrq9s
DIFF ERP_Ln9.ne30pg3_ne30pg3_mg17.FW2000climo.derecho_intel.cam-outfrq9s
DIFF ERS_Ld3.f10_f10_mg37.F1850.derecho_intel.cam-outfrq1d_14dec_ghg_cam7
DIFF ERS_Ln9.f09_f09_mg17.FX2000.derecho_intel.cam-outfrq9s
DIFF ERS_Ln9.f19_f19_mg17.FXSD.derecho_intel.cam-outfrq9s
DIFF ERS_Ln9_P288x1.mpasa120_mpasa120.F2000climo.derecho_intel.cam-outfrq9s_mpasa120
DIFF ERS_Ln9_P36x1.mpasa480_mpasa480.F2000climo.derecho_intel.cam-outfrq9s_mpasa480
DIFF SMS_D_Ln9.f09_f09_mg17.FCts2nudged.derecho_intel.cam-outfrq9s_leapday
DIFF SMS_D_Ln9.f09_f09_mg17.FCvbsxHIST.derecho_intel.cam-outfrq9s
DIFF SMS_D_Ln9.f09_f09_mg17.FSD.derecho_intel.cam-outfrq9s
DIFF SMS_D_Ln9.f19_f19_mg17.FWma2000climo.derecho_intel.cam-outfrq9s
DIFF SMS_D_Ln9.f19_f19_mg17.FWma2000climo.derecho_intel.cam-outfrq9s_waccm_ma_mam4
DIFF SMS_D_Ln9.f19_f19_mg17.FXHIST.derecho_intel.cam-outfrq9s_amie
DIFF SMS_D_Ln9.ne16pg3_ne16pg3_mg17.FX2000.derecho_intel.cam-outfrq9s
DIFF SMS_D_Ln9.ne30pg3_ne30pg3_mg17.FCts4MTHIST.derecho_intel.cam-outfrq9s
DIFF SMS_D_Ln9.ne30pg3_ne30pg3_mg17.FMTHIST.derecho_intel.cam-outfrq9s
DIFF SMS_D_Ln9_P1280x1.ne30pg3_ne30pg3_mg17.FCLTHIST.derecho_intel.cam-outfrq9s
DIFF SMS_D_Ln9.T42_T42.FSCAMARM97.derecho_intel.cam-outfrq9s
DIFF SMS_Ld1.f09_f09_mg17.FCHIST_GC.derecho_intel.cam-outfrq1d
DIFF SMS_Ld1.f09_f09_mg17.FW2000climo.derecho_intel.cam-outfrq1d
DIFF SMS_Ld1.ne30pg3_ne30pg3_mg17.FC2010climo.derecho_intel.cam-outfrq1d
DIFF SMS_Lh12.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq3h
DIFF SMS_Lm13.f10_f10_mg37.F2000climo.derecho_intel.cam-outfrq1m
DIFF SMS_Ln9.f09_f09_mg17.F2010climo.derecho_intel.cam-nudging
DIFF SMS_Ln9.f09_f09_mg17.FW1850.derecho_intel.cam-reduced_hist3s
DIFF SMS_Ln9.f19_f19.F2000climo.derecho_intel.cam-silhs
DIFF SMS_Ln9.ne30pg3_ne30pg3_mg17.FW2000climo.derecho_intel.cam-outfrq9s_rrtmgp
- expected baseline failures due to changes in dust deposition fluxes to surface models

derecho/nvhpc/aux_cam:
DIFF ERS_Ln9_G4-a100-openacc.ne30pg3_ne30pg3_mg17.F2000dev.derecho_nvhpc.cam-outfrq9s_mg3_default
- expected baseline failure due to changes in dust deposition fluxes to surface models

izumi/nag/aux_cam:
FAIL DAE.f45_f45_mg37.FHS94.izumi_nag.cam-dae
- pre-existing failure - issue #670

izumi/gnu/aux_cam: All PASS

Summarize any changes to answers:
larger than roundoff but same climate

URL for AMWG diagnostics output used to validate new climate:

https://acomstaff.acom.ucar.edu/tilmes/amwg/cam7/f.e23_beta02.FLTHIST_ne30.surf_flux_1995_2004_vs_f.e23_beta02.FLTHIST_ne30.001_1995_2004/website/index.html

The land diagnostics are here:

https://webext.cgd.ucar.edu/FLTHIST/f.e23_beta02.FLTHIST_ne30.surf_flux/lnd/f.e23_beta02.FLTHIST_ne30.surf_flux_1995_2004-f.e23_beta02.FLTHIST_ne30.001_1995_2004/setsIndex.html

===============================================================
===============================================================

Tag name: cam6_4_024
Originator(s): eaton
Date: 27 Aug 2024
@@ -48,9 +160,9 @@ List all existing files that have been modified, and describe the changes:

bld/build-namelist
. if simple model or aquaplanet remove the settings of
stream_ndep_data_filename and stream_ndep_mesh_filename
stream_ndep_data_filename and stream_ndep_mesh_filename
. modify logic so the add_default call for drydep_srf_file is not made for
simple models or aquaplanet
simple models or aquaplanet

bld/namelist_files/namelist_definition.xml
. remove the variables in the ndep_stream_nml group. Not used.
336 changes: 336 additions & 0 deletions src/chemistry/aerosol/aero_deposition_cam.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,336 @@
module aero_deposition_cam
!------------------------------------------------------------------------------
! Purpose:
!
! Partition the contributions from aerosols of wet and dry
! deposition at the surface into the fields passed to the coupler.
!------------------------------------------------------------------------------

use shr_kind_mod, only: r8 => shr_kind_r8
use shr_kind_mod, only: cl => shr_kind_cl
use constituents, only: cnst_get_ind, pcnst
use camsrfexch, only: cam_out_t
use cam_abortutils,only: endrun
use aerosol_properties_mod, only: aero_name_len
use aerosol_properties_mod, only: aerosol_properties

implicit none

private

! Public interfaces

public :: aero_deposition_cam_init
public :: aero_deposition_cam_setwet
public :: aero_deposition_cam_setdry

! Private module data

integer :: bcphi_ndx( pcnst ) = -1
integer :: bcphi_cnt = 0
integer :: bcpho_ndx( pcnst ) = -1
integer :: bcpho_cnt = 0
integer :: ocphi_ndx( pcnst ) = -1
integer :: ocphi_cnt = 0
integer :: ocpho_ndx( pcnst ) = -1
integer :: ocpho_cnt = 0

class(aerosol_properties), pointer :: aero_props=>null()
integer :: nele_tot=0 ! total number of aerosol elements

! bulk dust bins (meters)

integer, parameter :: n_bulk_dst_bins = 4

! CAM4 bulk dust bin sizes (https://doi.org/10.1002/2013MS000279)
real(r8), parameter :: bulk_dst_edges(n_bulk_dst_bins+1) = &
(/0.1e-6_r8, 1.0e-6_r8, 2.5e-6_r8, 5.0e-6_r8, 10.e-6_r8/)

contains

!============================================================================
subroutine aero_deposition_cam_init(aero_props_in)

class(aerosol_properties),target, intent(in) :: aero_props_in

integer :: pcnt, scnt
character(len=*), parameter :: subrname = 'aero_deposition_cam_init'

! construct the aerosol properties object
aero_props => aero_props_in

! set the cam constituent indices and determine the counts
! for the specified aerosol types

! black carbons
call get_indices( type='black-c', hydrophilic=.true., indices=bcphi_ndx, count=bcphi_cnt )
call get_indices( type='black-c', hydrophilic=.false., indices=bcpho_ndx, count=bcpho_cnt )

! primary and secondary organics
call get_indices( type='p-organic',hydrophilic=.true., indices=ocphi_ndx, count=pcnt )
call get_indices( type='s-organic',hydrophilic=.true., indices=ocphi_ndx(pcnt+1:), count=scnt )
ocphi_cnt = pcnt+scnt

call get_indices( type='p-organic',hydrophilic=.false., indices=ocpho_ndx, count=pcnt )
call get_indices( type='s-organic',hydrophilic=.false., indices=ocpho_ndx(pcnt+1:), count=scnt )
ocpho_cnt = pcnt+scnt

! total number of aerosol elements
nele_tot = aero_props%ncnst_tot()

contains

!==========================================================================
! returns CAM constituent indices of the aerosol tracers (and count)
!==========================================================================
subroutine get_indices( type, hydrophilic, indices, count)

character(len=*), intent(in) :: type
logical, intent(in ) :: hydrophilic
integer, intent(out) :: indices(:)
integer, intent(out) :: count

integer :: ibin,ispc, ndx, nspec
character(len=aero_name_len) :: spec_type, spec_name

count = 0
indices(:) = -1

! loop through aerosol bins / modes
do ibin = 1, aero_props%nbins()

! check if the bin/mode is hydrophilic
if ( aero_props%hydrophilic(ibin) .eqv. hydrophilic ) then
do ispc = 1, aero_props%nspecies(ibin)

call aero_props%get(ibin,ispc, spectype=spec_type, specname=spec_name)

if (spec_type==type) then

! get CAM constituent index
call cnst_get_ind(spec_name, ndx, abort=.false.)
if (ndx>0) then
count = count+1
indices(count) = ndx
endif

endif

enddo
endif

enddo

end subroutine get_indices

end subroutine aero_deposition_cam_init

!============================================================================
! Set surface wet deposition fluxes passed to coupler.
!============================================================================
subroutine aero_deposition_cam_setwet(aerdepwetis, aerdepwetcw, cam_out)

! Arguments:
real(r8), intent(in) :: aerdepwetis(:,:) ! aerosol wet deposition (interstitial)
real(r8), intent(in) :: aerdepwetcw(:,:) ! aerosol wet deposition (cloud water)
type(cam_out_t), intent(inout) :: cam_out ! cam export state

! Local variables:
integer :: i, ispec, ibin, mm, ndx
integer :: ncol ! number of columns

real(r8) :: dep_fluxes(nele_tot)
real(r8) :: dst_fluxes(n_bulk_dst_bins)
character(len=aero_name_len) :: specname, name_c
integer :: errstat
character(len=cl) :: errstr

ncol = cam_out%ncol

cam_out%bcphiwet(:) = 0._r8
cam_out%ocphiwet(:) = 0._r8
cam_out%dstwet1(:) = 0._r8
cam_out%dstwet2(:) = 0._r8
cam_out%dstwet3(:) = 0._r8
cam_out%dstwet4(:) = 0._r8

! derive cam_out variables from deposition fluxes
! note: wet deposition fluxes are negative into surface,
! dry deposition fluxes are positive into surface.
! srf models want positive definite fluxes.
do i = 1, ncol

! hydrophilic black carbon fluxes
do ispec=1,bcphi_cnt
cam_out%bcphiwet(i) = cam_out%bcphiwet(i) &
- (aerdepwetis(i,bcphi_ndx(ispec))+aerdepwetcw(i,bcphi_ndx(ispec)))
enddo

! hydrophobic black carbon fluxes
do ispec=1,bcpho_cnt
cam_out%bcphiwet(i) = cam_out%bcphiwet(i) &
- (aerdepwetis(i,bcpho_ndx(ispec))+aerdepwetcw(i,bcpho_ndx(ispec)))
enddo

! hydrophilic organic carbon fluxes
do ispec=1,ocphi_cnt
cam_out%ocphiwet(i) = cam_out%ocphiwet(i) &
- (aerdepwetis(i,ocphi_ndx(ispec))+aerdepwetcw(i,ocphi_ndx(ispec)))
enddo

! hydrophobic organic carbon fluxes
do ispec=1,ocpho_cnt
cam_out%ocphiwet(i) = cam_out%ocphiwet(i) &
- (aerdepwetis(i,ocpho_ndx(ispec))+aerdepwetcw(i,ocpho_ndx(ispec)))
enddo

! dust fluxes

dep_fluxes = 0._r8
dst_fluxes = 0._r8

do ibin = 1,aero_props%nbins()
do ispec = 0,aero_props%nmasses(ibin)
if (ispec==0) then
call aero_props%num_names(ibin, specname, name_c)
else
call aero_props%get(ibin,ispec, specname=specname)
end if
call cnst_get_ind(specname, ndx, abort=.false.)
if (ndx>0) then
mm = aero_props%indexer(ibin,ispec)
dep_fluxes(mm) = - (aerdepwetis(i,ndx)+aerdepwetcw(i,ndx))
end if
end do
end do

! rebin dust fluxes to bulk dust bins
call aero_props%rebin_bulk_fluxes('dust', dep_fluxes, bulk_dst_edges, dst_fluxes, errstat, errstr)
if (errstat/=0) then
call endrun('aero_deposition_cam_setwet: '//trim(errstr))
end if

cam_out%dstwet1(i) = cam_out%dstwet1(i) + dst_fluxes(1)
cam_out%dstwet2(i) = cam_out%dstwet2(i) + dst_fluxes(2)
cam_out%dstwet3(i) = cam_out%dstwet3(i) + dst_fluxes(3)
cam_out%dstwet4(i) = cam_out%dstwet4(i) + dst_fluxes(4)

! in rare cases, integrated deposition tendency is upward
if (cam_out%bcphiwet(i) < 0._r8) cam_out%bcphiwet(i) = 0._r8
if (cam_out%ocphiwet(i) < 0._r8) cam_out%ocphiwet(i) = 0._r8
if (cam_out%dstwet1(i) < 0._r8) cam_out%dstwet1(i) = 0._r8
if (cam_out%dstwet2(i) < 0._r8) cam_out%dstwet2(i) = 0._r8
if (cam_out%dstwet3(i) < 0._r8) cam_out%dstwet3(i) = 0._r8
if (cam_out%dstwet4(i) < 0._r8) cam_out%dstwet4(i) = 0._r8

enddo

end subroutine aero_deposition_cam_setwet

!============================================================================
! Set surface dry deposition fluxes passed to coupler.
!============================================================================
subroutine aero_deposition_cam_setdry(aerdepdryis, aerdepdrycw, cam_out)

! Arguments:
real(r8), intent(in) :: aerdepdryis(:,:) ! aerosol dry deposition (interstitial)
real(r8), intent(in) :: aerdepdrycw(:,:) ! aerosol dry deposition (cloud water)
type(cam_out_t), intent(inout) :: cam_out ! cam export state

! Local variables:
integer :: i, ispec, ibin, mm, ndx
integer :: ncol ! number of columns

real(r8) :: dep_fluxes(nele_tot)
real(r8) :: dst_fluxes(n_bulk_dst_bins)
character(len=aero_name_len) :: specname, name_c
integer :: errstat
character(len=cl) :: errstr

ncol = cam_out%ncol

cam_out%bcphidry(:) = 0._r8
cam_out%ocphidry(:) = 0._r8
cam_out%bcphodry(:) = 0._r8
cam_out%ocphodry(:) = 0._r8
cam_out%dstdry1(:) = 0._r8
cam_out%dstdry2(:) = 0._r8
cam_out%dstdry3(:) = 0._r8
cam_out%dstdry4(:) = 0._r8

! derive cam_out variables from deposition fluxes
! note: wet deposition fluxes are negative into surface,
! dry deposition fluxes are positive into surface.
! srf models want positive definite fluxes.
do i = 1, ncol

! hydrophilic black carbon fluxes
do ispec=1,bcphi_cnt
cam_out%bcphidry(i) = cam_out%bcphidry(i) &
+ (aerdepdryis(i,bcphi_ndx(ispec))+aerdepdrycw(i,bcphi_ndx(ispec)))
enddo

! hydrophobic black carbon fluxes
do ispec=1,bcpho_cnt
cam_out%bcphodry(i) = cam_out%bcphodry(i) &
+ (aerdepdryis(i,bcpho_ndx(ispec))+aerdepdrycw(i,bcpho_ndx(ispec)))
enddo

! hydrophilic organic carbon fluxes
do ispec=1,ocphi_cnt
cam_out%ocphidry(i) = cam_out%ocphidry(i) &
+ (aerdepdryis(i,ocphi_ndx(ispec))+aerdepdrycw(i,ocphi_ndx(ispec)))
enddo

! hydrophobic organic carbon fluxes
do ispec=1,ocpho_cnt
cam_out%ocphodry(i) = cam_out%ocphodry(i) &
+ (aerdepdryis(i,ocpho_ndx(ispec))+aerdepdrycw(i,ocpho_ndx(ispec)))
enddo

! dust fluxes

dep_fluxes = 0._r8
dst_fluxes = 0._r8

do ibin = 1,aero_props%nbins()
do ispec = 0,aero_props%nspecies(ibin)
if (ispec==0) then
call aero_props%num_names(ibin, specname, name_c)
else
call aero_props%get(ibin,ispec, specname=specname)
end if
call cnst_get_ind(specname, ndx, abort=.false.)
if (ndx>0) then
mm = aero_props%indexer(ibin,ispec)
dep_fluxes(mm) = aerdepdryis(i,ndx)+aerdepdrycw(i,ndx)
end if
end do
end do

! rebin dust fluxes to bulk dust bins
call aero_props%rebin_bulk_fluxes('dust', dep_fluxes, bulk_dst_edges, dst_fluxes, errstat, errstr)
if (errstat/=0) then
call endrun('aero_deposition_cam_setdry: '//trim(errstr))
end if

cam_out%dstdry1(i) = cam_out%dstdry1(i) + dst_fluxes(1)
cam_out%dstdry2(i) = cam_out%dstdry2(i) + dst_fluxes(2)
cam_out%dstdry3(i) = cam_out%dstdry3(i) + dst_fluxes(3)
cam_out%dstdry4(i) = cam_out%dstdry4(i) + dst_fluxes(4)

! in rare cases, integrated deposition tendency is upward
if (cam_out%bcphidry(i) < 0._r8) cam_out%bcphidry(i) = 0._r8
if (cam_out%ocphidry(i) < 0._r8) cam_out%ocphidry(i) = 0._r8
if (cam_out%bcphodry(i) < 0._r8) cam_out%bcphodry(i) = 0._r8
if (cam_out%ocphodry(i) < 0._r8) cam_out%ocphodry(i) = 0._r8
if (cam_out%dstdry1(i) < 0._r8) cam_out%dstdry1(i) = 0._r8
if (cam_out%dstdry2(i) < 0._r8) cam_out%dstdry2(i) = 0._r8
if (cam_out%dstdry3(i) < 0._r8) cam_out%dstdry3(i) = 0._r8
if (cam_out%dstdry4(i) < 0._r8) cam_out%dstdry4(i) = 0._r8

enddo

end subroutine aero_deposition_cam_setdry

end module aero_deposition_cam
32 changes: 31 additions & 1 deletion src/chemistry/aerosol/aerosol_properties_mod.F90
Original file line number Diff line number Diff line change
@@ -70,6 +70,8 @@ module aerosol_properties_mod
procedure(aero_min_mass_mean_rad), deferred :: min_mass_mean_rad
procedure(aero_optics_params), deferred :: optics_params
procedure(aero_bin_name), deferred :: bin_name
procedure(aero_rebin_bulk_fluxes), deferred :: rebin_bulk_fluxes
procedure(aero_hydrophilic), deferred :: hydrophilic

procedure :: final=>aero_props_final
end type aerosol_properties
@@ -91,12 +93,13 @@ end function aero_number_transported
! density
! hygroscopicity
! species type
! species name
! short wave species refractive indices
! long wave species refractive indices
! species morphology
!------------------------------------------------------------------------
subroutine aero_props_get(self, bin_ndx, species_ndx, list_ndx, density, hygro, &
spectype, specmorph, refindex_sw, refindex_lw)
spectype, specname, specmorph, refindex_sw, refindex_lw)
import :: aerosol_properties, r8
class(aerosol_properties), intent(in) :: self
integer, intent(in) :: bin_ndx ! bin index
@@ -105,6 +108,7 @@ subroutine aero_props_get(self, bin_ndx, species_ndx, list_ndx, density, hygro,
real(r8), optional, intent(out) :: density ! density (kg/m3)
real(r8), optional, intent(out) :: hygro ! hygroscopicity
character(len=*), optional, intent(out) :: spectype ! species type
character(len=*), optional, intent(out) :: specname ! species name
character(len=*), optional, intent(out) :: specmorph ! species morphology
complex(r8), pointer, optional, intent(out) :: refindex_sw(:) ! short wave species refractive indices
complex(r8), pointer, optional, intent(out) :: refindex_lw(:) ! long wave species refractive indices
@@ -378,6 +382,32 @@ function aero_bin_name(self, list_ndx, bin_ndx) result(name)

end function aero_bin_name

!------------------------------------------------------------------------------
! returns bulk deposition fluxes of the specified species type
! rebinned to specified diameter limits
!------------------------------------------------------------------------------
subroutine aero_rebin_bulk_fluxes(self, bulk_type, dep_fluxes, diam_edges, bulk_fluxes, &
error_code, error_string)
import :: aerosol_properties, r8
class(aerosol_properties), intent(in) :: self
character(len=*),intent(in) :: bulk_type ! aerosol type to rebin
real(r8), intent(in) :: dep_fluxes(:) ! kg/m2
real(r8), intent(in) :: diam_edges(:) ! meters
real(r8), intent(out) :: bulk_fluxes(:) ! kg/m2
integer, intent(out) :: error_code ! error code (0 if no error)
character(len=*), intent(out) :: error_string ! error string

end subroutine aero_rebin_bulk_fluxes

!------------------------------------------------------------------------------
! Returns TRUE if bin is hydrophilic, otherwise FALSE
!------------------------------------------------------------------------------
logical function aero_hydrophilic(self, bin_ndx)
import :: aerosol_properties
class(aerosol_properties), intent(in) :: self
integer, intent(in) :: bin_ndx ! bin number
end function aero_hydrophilic

end interface

contains
122 changes: 121 additions & 1 deletion src/chemistry/aerosol/modal_aerosol_properties_mod.F90
Original file line number Diff line number Diff line change
@@ -36,6 +36,8 @@ module modal_aerosol_properties_mod
procedure :: soluble
procedure :: min_mass_mean_rad
procedure :: bin_name
procedure :: rebin_bulk_fluxes
procedure :: hydrophilic

final :: destructor
end type modal_aerosol_properties
@@ -44,6 +46,8 @@ module modal_aerosol_properties_mod
procedure :: constructor
end interface modal_aerosol_properties

logical, parameter :: debug = .false.

contains

!------------------------------------------------------------------------------
@@ -182,12 +186,13 @@ end function number_transported
! density
! hygroscopicity
! species type
! species name
! short wave species refractive indices
! long wave species refractive indices
! species morphology
!------------------------------------------------------------------------
subroutine get(self, bin_ndx, species_ndx, list_ndx, density, hygro, &
spectype, specmorph, refindex_sw, refindex_lw)
spectype, specname, specmorph, refindex_sw, refindex_lw)

class(modal_aerosol_properties), intent(in) :: self
integer, intent(in) :: bin_ndx ! bin index
@@ -196,6 +201,7 @@ subroutine get(self, bin_ndx, species_ndx, list_ndx, density, hygro, &
real(r8), optional, intent(out) :: density ! density (kg/m3)
real(r8), optional, intent(out) :: hygro ! hygroscopicity
character(len=*), optional, intent(out) :: spectype ! species type
character(len=*), optional, intent(out) :: specname ! species name
character(len=*), optional, intent(out) :: specmorph ! species morphology
complex(r8), pointer, optional, intent(out) :: refindex_sw(:) ! short wave species refractive indices
complex(r8), pointer, optional, intent(out) :: refindex_lw(:) ! long wave species refractive indices
@@ -212,6 +218,10 @@ subroutine get(self, bin_ndx, species_ndx, list_ndx, density, hygro, &
density_aer=density, hygro_aer=hygro, spectype=spectype, &
refindex_aer_sw=refindex_sw, refindex_aer_lw=refindex_lw)

if (present(specname)) then
call rad_cnst_get_info(ilist, bin_ndx, species_ndx, spec_name=specname)
end if

if (present(specmorph)) then
specmorph = 'UNKNOWN'
end if
@@ -665,4 +675,114 @@ function bin_name(self, list_ndx, bin_ndx) result(name)

end function bin_name

!------------------------------------------------------------------------------
! returns bulk deposition fluxes of the specified species type
! rebinned to specified diameter limits
!------------------------------------------------------------------------------
subroutine rebin_bulk_fluxes(self, bulk_type, dep_fluxes, diam_edges, bulk_fluxes, &
error_code, error_string)
use infnan, only: nan, assignment(=)

class(modal_aerosol_properties), intent(in) :: self
character(len=*),intent(in) :: bulk_type ! aerosol type to rebin
real(r8), intent(in) :: dep_fluxes(:) ! kg/m2
real(r8), intent(in) :: diam_edges(:) ! meters
real(r8), intent(out) :: bulk_fluxes(:) ! kg/m2
integer, intent(out) :: error_code ! error code (0 if no error)
character(len=*), intent(out) :: error_string ! error string

real(r8) :: dns_dst ! kg/m3
real(r8) :: sigma_g, vmd, tmp, massfrac_bin(size(bulk_fluxes))
real(r8) :: Ntype, Mtype, Mtotal, Ntot
integer :: k,l,m,mm, nbulk
logical :: has_type, type_not_found

character(len=aero_name_len) :: spectype
character(len=aero_name_len) :: modetype

real(r8), parameter :: sqrtwo = sqrt(2._r8)
real(r8), parameter :: onethrd = 1._r8/3._r8

error_code = 0
error_string = ' '

type_not_found = .true.

nbulk = size(bulk_fluxes)

bulk_fluxes(:) = 0.0_r8

do m = 1,self%nbins()
Mtype = 0._r8
Mtotal = 0._r8
mm = self%indexer(m,0)
Ntot = dep_fluxes(mm) ! #/m2

has_type = .false.

do l = 1,self%nspecies(m)
mm = self%indexer(m,l)
call self%get(m,l, spectype=spectype, density=dns_dst) ! kg/m3
if (spectype==bulk_type) then
Mtype = dep_fluxes(mm) ! kg/m2
has_type = .true.
type_not_found = .false.
end if
Mtotal = Mtotal + dep_fluxes(mm) ! kg/m2
end do
mode_has_type: if (has_type) then
call rad_cnst_get_info(0, m, mode_type=modetype)
if (Ntot>1.e-40_r8 .and. Mtype>1.e-40_r8 .and. Mtotal>1.e-40_r8) then

call rad_cnst_get_mode_props(0, m, sigmag=sigma_g)
tmp = sqrtwo*log(sigma_g)

! type number concentration
Ntype = Ntot * Mtype/Mtotal ! #/m2

! volume median diameter (meters)
vmd = (6._r8*Mtype/(pi*Ntype*dns_dst))**onethrd * exp(1.5_r8*(log(sigma_g))**2)

massfrac_bin = 0._r8

do k = 1,nbulk
massfrac_bin(k) = 0.5_r8*( erf((log(diam_edges(k+1)/vmd))/tmp) &
- erf((log(diam_edges(k )/vmd))/tmp) )
bulk_fluxes(k) = bulk_fluxes(k) + massfrac_bin(k) * Mtype
end do

if (debug) then
if (abs(1._r8-sum(massfrac_bin)) > 1.e-6_r8) then
write(*,*) 'rebin_bulk_fluxes WARNING mode-num, massfrac_bin, sum(massfrac_bin) = ', &
m, massfrac_bin, sum(massfrac_bin)
end if
end if

end if
end if mode_has_type
end do

if (type_not_found) then
bulk_fluxes(:) = nan
error_code = 1
write(error_string,*) 'aerosol_properties::rebin_bulk_fluxes ERROR : ',trim(bulk_type),' not found'
end if

end subroutine rebin_bulk_fluxes

!------------------------------------------------------------------------------
! Returns TRUE if bin is hydrophilic, otherwise FALSE
!------------------------------------------------------------------------------
logical function hydrophilic(self, bin_ndx)
class(modal_aerosol_properties), intent(in) :: self
integer, intent(in) :: bin_ndx ! bin number

character(len=aero_name_len) :: modetype

call rad_cnst_get_info(0, bin_ndx, mode_type=modetype)

hydrophilic = (trim(modetype) == 'accum')

end function hydrophilic

end module modal_aerosol_properties_mod
18 changes: 11 additions & 7 deletions src/chemistry/modal_aero/aero_model.F90
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ module aero_model

use modal_aero_wateruptake, only: modal_strat_sulfate
use mo_setsox, only: setsox, has_sox
use modal_aerosol_properties_mod, only: modal_aerosol_properties

implicit none
private
@@ -107,6 +108,8 @@ module aero_model

logical :: convproc_do_aer

class(modal_aerosol_properties), pointer :: aero_props=>null()

contains

!=============================================================================
@@ -194,7 +197,7 @@ subroutine aero_model_init( pbuf2d )

use modal_aero_calcsize, only: modal_aero_calcsize_init
use modal_aero_coag, only: modal_aero_coag_init
use modal_aero_deposition, only: modal_aero_deposition_init
use aero_deposition_cam, only: aero_deposition_cam_init
use modal_aero_gasaerexch, only: modal_aero_gasaerexch_init
use modal_aero_newnuc, only: modal_aero_newnuc_init
use modal_aero_rename, only: modal_aero_rename_init
@@ -253,10 +256,11 @@ subroutine aero_model_init( pbuf2d )
call modal_aero_coag_init
call modal_aero_newnuc_init

! call modal_aero_deposition_init only if the user has not specified
! call aero_deposition_cam_init only if the user has not specified
! prescribed aerosol deposition fluxes
if (.not.aerodep_flx_prescribed()) then
call modal_aero_deposition_init
aero_props => modal_aerosol_properties()
call aero_deposition_cam_init(aero_props)
endif

if (convproc_do_aer) then
@@ -694,7 +698,7 @@ subroutine aero_model_drydep ( state, pbuf, obklen, ustar, cam_in, dt, cam_out,
use modal_aero_data, only: numptrcw_amode
use modal_aero_data, only: lmassptr_amode
use modal_aero_data, only: lmassptrcw_amode
use modal_aero_deposition, only: set_srf_drydep
use aero_deposition_cam,only: aero_deposition_cam_setdry

! args
type(physics_state), intent(in) :: state ! Physics state variables
@@ -972,7 +976,7 @@ subroutine aero_model_drydep ( state, pbuf, obklen, ustar, cam_in, dt, cam_out,
! if the user has specified prescribed aerosol dep fluxes then
! do not set cam_out dep fluxes according to the prognostic aerosols
if (.not.aerodep_flx_prescribed()) then
call set_srf_drydep(aerdepdryis, aerdepdrycw, cam_out)
call aero_deposition_cam_setdry(aerdepdryis, aerdepdrycw, cam_out)
endif

endsubroutine aero_model_drydep
@@ -981,10 +985,10 @@ subroutine aero_model_drydep ( state, pbuf, obklen, ustar, cam_in, dt, cam_out,
!=============================================================================
subroutine aero_model_wetdep( state, dt, dlf, cam_out, ptend, pbuf)

use modal_aero_deposition, only: set_srf_wetdep
use wetdep, only: wetdepa_v2, wetdep_inputs_set, wetdep_inputs_t
use modal_aero_data
use modal_aero_convproc, only: deepconv_wetdep_history, ma_convproc_intr, convproc_do_evaprain_atonce
use aero_deposition_cam, only: aero_deposition_cam_setwet

! args

@@ -1635,7 +1639,7 @@ subroutine aero_model_wetdep( state, dt, dlf, cam_out, ptend, pbuf)
! if the user has specified prescribed aerosol dep fluxes then
! do not set cam_out dep fluxes according to the prognostic aerosols
if (.not. aerodep_flx_prescribed()) then
call set_srf_wetdep(aerdepwetis, aerdepwetcw, cam_out)
call aero_deposition_cam_setwet(aerdepwetis, aerdepwetcw, cam_out)
endif

endsubroutine aero_model_wetdep