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

Working notes: EAMxx aerosol microphysics AtmosphereProcess #231

Open
jeff-cohere opened this issue Aug 23, 2023 · 2 comments
Open

Working notes: EAMxx aerosol microphysics AtmosphereProcess #231

jeff-cohere opened this issue Aug 23, 2023 · 2 comments
Assignees
Labels
EAMxx integration Integration with SCREAM/EAMxx

Comments

@jeff-cohere
Copy link
Collaborator

jeff-cohere commented Aug 23, 2023

This issue is my scratch space for bringing all of the mam4xx aerosol microphysics parameterizations into their corresponding EAMxx AtmosphereProcess subclass. This code is not part of mam4xx's parameterizations, so I'm taking the liberty of eliminating unneeded code and changing its structure as needed.

I'm working in this branch.

Code Inventory

The code to be transplanted to EAMxx is in mam4_amicphys_1gridcell.cpp, a test suite assembled by @overfelt

Functions (subroutines)

  • modal_aero_amicphys_intr: top-level "driver" subroutine for performing all aerosol microphysics calculations
  • construct_subareas_1gridcell: determines the number of "sub-areas" (subvolumes?) within a given cell (1 for cloudy/clear cells and 2 for partially cloudy cells) and computes sub-area mean mixing ratios
  • subarea_partition_factors: sets the interstitial mixing ratios in the sub-areas of a cell (called by construct_subareas_1gridcell)
  • mam_amicphys_1gridcell: determines whether a cell is cloudy or clear and dispatches microphysics calculations
  • mam_amicphys_1subarea_cloudy: computes cloudy-sky microphysics within a single subarea
  • mam_amicphys_1subarea_clear: computes clear-sky microphysics within a single subarea

Constants

Many of these seem related to history data that we may dispose of, since legacy MAM's I/O model ("write anything out whenever you want") won't work with GPUs. Also, there are some weird-looking "conversion factors" that might not actually be used.

  • int nqtendaa (5): number of contributions tracked for different parameterizations, used to write history data
  • int nqtendbb (4): number of tendencies recorded for box-model diagnostic output for different parameterizations
  • int nqqcwtendaa (1): a variant of nqtendaa (not sure of its original purpose)
  • int nqqcwtendbb (1): a variant of nqtendbb (not sure of its original purpose)
  • int iqtend_cond (0): the index of conduction contributions in e.g. qX_delaa
  • int iqtend_rnam (1): the index of rename contributions in e.g. qX_delaa
  • int iqtend_nnuc (2): the index of nucleation contributions in e.g. qX_delaa
  • int iqtend_coag (3): the index of coagulation contributions in e.g. qX_delaa
  • int iqtend_cond_only (4): the index of conduction contributions when only conduction is considered (?)
  • int iqqcwtend_rnam (0): a variant of iqtend_rnam related to nqqcwtendaa
  • int maxsubarea (2): the maximum number of "subareas" in a cell (clear cells have 1 "clear subarea", cloudy cells have 1 "cloudy" subarea, partially cloudy cells have 1 "clear" and 1 "cloudy" subarea)
  • Real fcvt_gas[AeroConfig::num_gas_ids()] ({1, 1, 1}): conversion factors for converting gas mixing ratios from (kg/kg) to (mol/mol) (?)
  • Real fcvt_aer[AeroConfig::num_aerosol_ids()] ({1, 1, 1, 1, 1, 1, 1}); conversion factors for converting aerosol mixing ratios from (kg/kg) to (mol/mol) (?)
  • Real fcvt_num (1.0): leave number mix-ratios unchanged (#/kmol-air)
  • Real fcvt_wtr (1.0): factor for converting aerosol water mix-ratios from (kg/kg) to (mol/mol)
  • int gaexch_h2so4_uptake_optaa (2): controls treatment of h2so4 condensation in mam_gasaerexch_1subarea (1 = sequential calc. of gas-chem prod then condensation loss; 2 = simultaneous calc. of gas-chem prod and condensation loss)

Indexing Shenanigans

I'm not sure any of this stuff will survive the integration process. :-)

static constexpr int lmapcc_val_nul = 0;
static constexpr int lmapcc_val_gas = 1;
static constexpr int lmapcc_val_aer = 2;
static constexpr int lmapcc_val_num = 3;
static constexpr int gas_pcnst = 30;
const int lmapcc_all[gas_pcnst] = {
lmapcc_val_nul, lmapcc_val_gas, lmapcc_val_nul, lmapcc_val_nul,
lmapcc_val_gas, lmapcc_val_aer, lmapcc_val_aer, lmapcc_val_aer,
lmapcc_val_aer, lmapcc_val_aer, lmapcc_val_aer, lmapcc_val_aer,
lmapcc_val_num, lmapcc_val_aer, lmapcc_val_aer, lmapcc_val_aer,
lmapcc_val_aer, lmapcc_val_num, lmapcc_val_aer, lmapcc_val_aer,
lmapcc_val_aer, lmapcc_val_aer, lmapcc_val_aer, lmapcc_val_aer,
lmapcc_val_aer, lmapcc_val_num, lmapcc_val_aer, lmapcc_val_aer,
lmapcc_val_aer, lmapcc_val_num};

// Where lmapcc_val_num are defined in lmapcc_all
const int numptr_amode[AeroConfig::num_modes()] = {12, 17, 25, 29};
// Where lmapcc_val_gas are defined in lmapcc_all
const int lmap_gas[AeroConfig::num_modes()] = {4, 1};

Notes

  • nstep and ncol are passed to many subroutines but aren't used
  • deltat is used to compute gas production and nucleation rates

Aerosol Microphysics Configuration

These parameters can be set to allow specific test/diagnostic setups for analyzing the effects of aerosol microphysics in EAMxx simulations.

  • Switches for activating and deactivating individual parameterizations
    • condensation (gas-aerosol exchange)
    • renaming
    • nucleation
    • coagulation
@jeff-cohere jeff-cohere added the EAMxx integration Integration with SCREAM/EAMxx label Aug 23, 2023
@jeff-cohere jeff-cohere self-assigned this Aug 23, 2023
@mjs271
Copy link
Contributor

mjs271 commented Sep 12, 2023

Here's the notes about indexing etc., that I mentioned.

Mike Trying to Figure Out Indexing Scheme

  • From Brian (paraphrased):

For given imode in the big, concatenated arrays, qoi(mam_idx(imode,0)) is number concentration (modal qoi), mam_idx(imode,lspec>0) is mass concentration of species lspec. The module basically defines new indices mm = mam_idx(imode,0) to simplify the local referencing to these elements, ensuring a contiguous 1-D array.

  • So... the max amount of modes that's currently possible in E3SM is 9
  • In the case of 9 modes, we have the following numbers of species/mode:
    • 9 + 7 + 5 + 3 + 3 + 3 + 3 + 3 + 3 = 39 entries
  • There's also the number mixing ratios for each mode, for both cloudborne and interstitial aerosols $\implies$ 18 entries
  • This adds up to 57... which is odd

  • These are the density and hygroscopicity values found in the following validation inputs:
ccncalc_ts_1400.yaml
dropmixnuc_ts_1407.yaml
dropmixnuc_ts_1417.yaml
stand_dropmixnuc_ts_1407.yaml
specdens_amode: [0.1770000000E+004,0.1797693135E+309,0.1797693135E+309,
0.1000000000E+004,0.1000000000E+004,0.1700000000E+004,0.1900000000E+004,
0.2600000000E+004,0.1601000000E+004,0.0000000000E+000,0.0000000000E+000,
0.0000000000E+000,0.0000000000E+000,0.0000000000E+000]
spechygro: [0.5070000000E+000,0.1797693135E+309,0.1797693135E+309,
0.1000000083E-009,0.1400000000E+000,0.1000000013E-009,0.1160000000E+001,
0.6800000000E-001,0.1000000015E+000,0.0000000000E+000,0.0000000000E+000,
0.0000000000E+000,0.0000000000E+000,0.0000000000E+000]
/// mam4 aerosol densities [kg/m3]
static constexpr Real mam4_density_soa = 1000.0;
static constexpr Real mam4_density_so4 = 1770.0;
static constexpr Real mam4_density_pom = 1000.0;
static constexpr Real mam4_density_bc = 1700.0;
static constexpr Real mam4_density_nacl = 1900.0;
static constexpr Real mam4_density_dst = 2600.0;
static constexpr Real mam4_density_mom = 1601.0;

/// mam4 aerosol hygroscopicities
static constexpr Real mam4_hyg_soa = 0.1;
static constexpr Real mam4_hyg_so4 = 0.507;
static constexpr Real mam4_hyg_pom = 1e-10;
static constexpr Real mam4_hyg_bc = 1e-10;
static constexpr Real mam4_hyg_nacl = 1.16;
static constexpr Real mam4_hyg_dst = 0.14;
static constexpr Real mam4_hyg_mom = 0.1;
  • specdens_amode appears to have the entries:

    [so4, garbage, garbage, soa/pom, soa/pom, bc, nacl, dust, mom, <zeros>]
  • And for spechygro:

    [so4, junk, junk, pom/bc, dust, pom/bc, nacl, mom/soa?, mom/soa?, <zeros>]
    • note that the mom/soa value is different from that given in aero_modes.hpp
  • These also come from the above-referenced yaml files, so I'm leaving them here for reference

lspectype_amode: [1, 4, 5, 6, 8, 7, 9, 0, 0, 0, 0, 0, 0, 0, 1, 5, 7, 9, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 7, 1, 6, 4, 5, 9, 0, 0, 0, 0, 0, 0, 0, 
4, 6, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
lmassptrcw_amode: [16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 24, 
25, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, 32, 33, 34, 35, 
0, 0, 0, 0, 0, 0, 0, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
numptrcw_amode: [23, 28, 36, 40]
lmassptr_amode: [16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 24, 
25, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, 32, 33, 34, 35, 
0, 0, 0, 0, 0, 0, 0, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
numptr_amode: [23, 28, 36, 40]

Other Useful Information (Ordering, etc.)

MODAL_AERO_4MODE_MOM .and. RAIN_EVAP_TO_COARSE_AERO
#elif ( defined MODAL_AERO_4MODE_MOM )
    real(r8), parameter :: specmw_amode(ntot_aspectype)   = (/ 
        115.0_r8, 115.0_r8,  62.0_r8, 12.0_r8,   12.0_r8,   12.0_r8,  
        58.5_r8, 135.0_r8, 250092.0_r8 /)
#elif

[...]

#elif ( defined MODAL_AERO_4MODE_MOM )
#if (defined RAIN_EVAP_TO_COARSE_AERO)
    integer, parameter :: nspec_amode(ntot_amode) = (/ 7, 4, 7, 3 /)
#else
    integer, parameter :: nspec_amode(ntot_amode) = (/ 7, 4, 3, 3 /)
#endif
#elif

[...]

#elif ( defined MODAL_AERO_4MODE_MOM )
  integer, parameter ::  ntot_aspectype = 9
  character(len=*),parameter ::  specname_amode(ntot_aspectype) = (/
     'sulfate', 'ammonium', 'nitrate', 'p-organic', 's-organic', 
     'black-c', 'seasalt', 'dust', 'm-organic' /)
#else

[...]

#elif ( defined MODAL_AERO_4MODE_MOM )
    real(r8), parameter :: specmw_amode(ntot_aspectype)   = (/ 
        115.0_r8, 115.0_r8,  62.0_r8, 12.0_r8,   12.0_r8,   12.0_r8,  
        58.5_r8, 135.0_r8, 250092.0_r8 /)
#elif

[...]

#elif ( (defined MODAL_AERO_4MODE) || (defined MODAL_AERO_4MODE_MOM) )
    character(len=*), parameter :: modename_amode(ntot_amode) = (/   
        'accum', 'aitken', 'coarse', 'primary_carbon  '/)
#elif

[...]

#elif ( (defined MODAL_AERO_4MODE) || (defined MODAL_AERO_4MODE_MOM) )
    integer, parameter :: mprognum_amode(ntot_amode)   = (/ 1, 1, 1, 1/)
    integer, parameter :: mdiagnum_amode(ntot_amode)   = (/ 0, 0, 0, 0/)
    integer, parameter :: mprogsfc_amode(ntot_amode)   = (/ 0, 0, 0, 0/)
    integer, parameter :: mcalcwater_amode(ntot_amode) = (/ 0, 0, 0, 0/)
#elif
#elif ( defined MODAL_AERO_4MODE_MOM )
    xname_massptr(:nspec_amode(1),1)   = (/ 'so4_a1', 'pom_a1', 
       'soa_a1', 'bc_a1', 'dst_a1', 'ncl_a1', 'mom_a1 ' /)
    xname_massptrcw(:nspec_amode(1),1) = (/ 'so4_c1', 'pom_c1', 
       'soa_c1', 'bc_c1', 'dst_c1', 'ncl_c1', 'mom_c1' /)
    xname_spectype(:nspec_amode(1),1)  = (/ 'sulfate', 'p-organic',
        's-organic', 'black-c', 'dust', 'seasalt', 'm-organic' /)
    #elif ( defined MODAL_AERO_3MODE || defined MODAL_AERO_4MODE )
    xname_massptr(:nspec_amode(1),1)   = (/ 'so4_a1', 'pom_a1',
        'soa_a1', 'bc_a1', 'dst_a1', 'ncl_a1' /)
    xname_massptrcw(:nspec_amode(1),1) = (/ 'so4_c1', 'pom_c1',
        'soa_c1', 'bc_c1', 'dst_c1', 'ncl_c1' /)
    xname_spectype(:nspec_amode(1),1)  = (/ 'sulfate', 'p-organic',
        's-organic', 'black-c', 'dust', 'seasalt' /)
#endif

[...]

#elif ( defined MODAL_AERO_4MODE_MOM )
       xname_massptr(:nspec_amode(2),2)   = (/ 'so4_a2', 'soa_a2',
           'ncl_a2', 'mom_a2' /)
       xname_massptrcw(:nspec_amode(2),2) = (/ 'so4_c2', 'soa_c2',
           'ncl_c2', 'mom_c2' /)
       xname_spectype(:nspec_amode(2),2)  = (/ 'sulfate', 's-organic',
           'seasalt', 'm-organic' /)
#elif

[...]

#elif ( defined MODAL_AERO_4MODE_MOM )
       ! mode 3 (coarse dust & seasalt) species
#if (defined RAIN_EVAP_TO_COARSE_AERO)
    xname_massptr(:nspec_amode(3),3)   =    (/ 'dst_a3',
      'ncl_a3', 'so4_a3', 'bc_a3', 'pom_a3', 'soa_a3', 'mom_a3' /)
    xname_massptrcw(:nspec_amode(3),3) =    (/ 'dst_c3',
      'ncl_c3', 'so4_c3', 'bc_c3', 'pom_c3', 'soa_c3', 'mom_c3' /)
    xname_spectype(:nspec_amode(3),3)  = (/ 'dust', 'seasalt',
      'sulfate', 'black-c', 'p-organic', 's-organic', 'm-organic' /)
#else
    xname_massptr(:nspec_amode(3),3)   = (/ 'dst_a3', 'ncl_a3', 
        'so4_a3' /)
    xname_massptrcw(:nspec_amode(3),3) = (/ 'dst_c3', 'ncl_c3', 
        'so4_c3' /)
    xname_spectype(:nspec_amode(3),3)  = (/ 'dust', 'seasalt', 
        'sulfate' /)
#endif
#endif

[...]

#if ( defined MODAL_AERO_4MODE_MOM )
       ! mode 4 (primary carbon) species
    xname_massptr(:nspec_amode(4),4)   = (/ 'pom_a4', 'bc_a4',
       'mom_a4' /)
    xname_massptrcw(:nspec_amode(4),4) = (/ 'pom_c4', 'bc_c4',
       'mom_c4' /)
    xname_spectype(:nspec_amode(4),4)  = (/ 'p-organic', 'black-c',
        'm-organic' /)
#elif

@jeff-cohere
Copy link
Collaborator Author

jeff-cohere commented Sep 19, 2023

I'm making some progress here. Some diagnostic quantities apparently are needed in order to compute aerosol microphysics, so perhaps we need to do this during initialization. The required diagnostic (modal) quantities are

  • dgncur_a and dgncur_awet: wet and dry geometric particle diameters [m] (mean or nominal? Total or interstitial?)
  • wetdens: the wet density of aerosols [kg/m3]
  • qaerwat: the aerosol water mass mixing ratio [kg/kg]

All but qaerwat currently exist in the Diagnostics type. Once I figure out how to compute qaerwat, I'll probably put up a little PR to add an aerosol_water_mass_mixing_ratio field to Diagnostics.

Copying @pressel because he's got the most fingerprints on Diagnostics, if I'm not mistaken.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
EAMxx integration Integration with SCREAM/EAMxx
Projects
None yet
Development

No branches or pull requests

2 participants