From 892ca144d5ac0bbb50594dc92017c2e70dbd2390 Mon Sep 17 00:00:00 2001 From: Steve Goldhaber Date: Fri, 1 Sep 2023 13:29:46 +0200 Subject: [PATCH 01/24] Restore pp_trop_mam_oslo from cam_cesm2_1_rel_05-Nor_v1.0.5 Copy pp_trop_mam_oslo mechanism and pp source from cam_cesm2_1_rel_05-Nor_v1.0.5 Add trop_mam_oslo chemistry option Specify trop_mam_oslo for NF compsets Set correct paths in configure Some cleanup in configure Bring in OSLO_AERO as a CAM external. NB: Fortran is identical to that created with the new chemistry preprocessor --- .gitignore | 1 + Externals_CAM.cfg | 7 + bld/config_files/definition.xml | 6 +- bld/configure | 24 +- cime_config/config_component.xml | 3 +- src/chemistry/pp_trop_mam_oslo/chem_mech.doc | 162 ++++++++ src/chemistry/pp_trop_mam_oslo/chem_mech.in | 109 +++++ src/chemistry/pp_trop_mam_oslo/chem_mods.F90 | 50 +++ src/chemistry/pp_trop_mam_oslo/m_rxt_id.F90 | 16 + src/chemistry/pp_trop_mam_oslo/m_spc_id.F90 | 33 ++ src/chemistry/pp_trop_mam_oslo/mo_adjrxt.F90 | 34 ++ src/chemistry/pp_trop_mam_oslo/mo_exp_sol.F90 | 79 ++++ src/chemistry/pp_trop_mam_oslo/mo_imp_sol.F90 | 392 ++++++++++++++++++ src/chemistry/pp_trop_mam_oslo/mo_indprd.F90 | 56 +++ .../pp_trop_mam_oslo/mo_lin_matrix.F90 | 74 ++++ .../pp_trop_mam_oslo/mo_lu_factor.F90 | 57 +++ .../pp_trop_mam_oslo/mo_lu_solve.F90 | 90 ++++ .../pp_trop_mam_oslo/mo_nln_matrix.F90 | 103 +++++ src/chemistry/pp_trop_mam_oslo/mo_phtadj.F90 | 24 ++ .../pp_trop_mam_oslo/mo_prod_loss.F90 | 97 +++++ .../pp_trop_mam_oslo/mo_rxt_rates_conv.F90 | 25 ++ src/chemistry/pp_trop_mam_oslo/mo_setrxt.F90 | 90 ++++ src/chemistry/pp_trop_mam_oslo/mo_sim_dat.F90 | 132 ++++++ 23 files changed, 1651 insertions(+), 13 deletions(-) create mode 100644 src/chemistry/pp_trop_mam_oslo/chem_mech.doc create mode 100644 src/chemistry/pp_trop_mam_oslo/chem_mech.in create mode 100644 src/chemistry/pp_trop_mam_oslo/chem_mods.F90 create mode 100644 src/chemistry/pp_trop_mam_oslo/m_rxt_id.F90 create mode 100644 src/chemistry/pp_trop_mam_oslo/m_spc_id.F90 create mode 100644 src/chemistry/pp_trop_mam_oslo/mo_adjrxt.F90 create mode 100644 src/chemistry/pp_trop_mam_oslo/mo_exp_sol.F90 create mode 100644 src/chemistry/pp_trop_mam_oslo/mo_imp_sol.F90 create mode 100644 src/chemistry/pp_trop_mam_oslo/mo_indprd.F90 create mode 100644 src/chemistry/pp_trop_mam_oslo/mo_lin_matrix.F90 create mode 100644 src/chemistry/pp_trop_mam_oslo/mo_lu_factor.F90 create mode 100644 src/chemistry/pp_trop_mam_oslo/mo_lu_solve.F90 create mode 100644 src/chemistry/pp_trop_mam_oslo/mo_nln_matrix.F90 create mode 100644 src/chemistry/pp_trop_mam_oslo/mo_phtadj.F90 create mode 100644 src/chemistry/pp_trop_mam_oslo/mo_prod_loss.F90 create mode 100644 src/chemistry/pp_trop_mam_oslo/mo_rxt_rates_conv.F90 create mode 100644 src/chemistry/pp_trop_mam_oslo/mo_setrxt.F90 create mode 100644 src/chemistry/pp_trop_mam_oslo/mo_sim_dat.F90 diff --git a/.gitignore b/.gitignore index 6beb06fc54..de7655b8d1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ chem_proc cime components manage_externals.log +src/chemistry/oslo_aero src/physics/ali_arms/ src/physics/camnor_phys src/physics/carma/base diff --git a/Externals_CAM.cfg b/Externals_CAM.cfg index 4a43ae2d5d..83a9db2bcf 100644 --- a/Externals_CAM.cfg +++ b/Externals_CAM.cfg @@ -68,6 +68,13 @@ repo_url = https://github.com/NorESMhub/CAM-Nor-physics local_path = src/physics/camnor_phys required = True +[oslo_aero] +protocol = git +branch = noresm_develop +repo_url = https://github.com/NorESMhub/OSLO_AERO +local_path = src/chemistry/oslo_aero +required = True + [hemco] protocol = git tag = hemco-cesm1_2_0_hemco3_6_2_cesm diff --git a/bld/config_files/definition.xml b/bld/config_files/definition.xml index 251669792a..93733061c0 100644 --- a/bld/config_files/definition.xml +++ b/bld/config_files/definition.xml @@ -106,8 +106,8 @@ meteor_smoke (Meteor Smoke), mixed_sulfate (Meteor Smoke and Sulfate), pmc (Pola sulfate (Sulfate Aerosols), tholin (early earth haze), test_detrain (Detrainment), test_growth (Particle Growth), test_passive (Passive Dust), test_radiative (Radiatively Active Dust), test_swelling (Sea Salt), test_tracers (Asian Monsoon), test_tracers2 (Guam). - - Chemistry package: none,ghg_mam4,terminator,trop_mam3,trop_mam4,trop_mam7,trop_mozart,trop_strat_mam4_ts2,trop_strat_mam4_vbs,trop_strat_mam4_vbsext,trop_strat_mam5_ts2,trop_strat_mam5_vbs,trop_strat_mam5_vbsext,waccm_ma,waccm_mad,waccm_ma_sulfur,waccm_sc,waccm_sc_mam4,waccm_mad_mam4,waccm_ma_mam4,waccm_tsmlt_mam4,waccm_tsmlt_mam4_vbsext,waccm_mad_mam5,waccm_ma_mam5,waccm_tsmlt_mam5,waccm_tsmlt_mam5_vbsext + + Chemistry package: none,ghg_mam4,terminator,trop_mam3,trop_mam4,trop_mam7,trop_mam_oslo,trop_mozart,trop_strat_mam4_ts2,trop_strat_mam4_vbs,trop_strat_mam4_vbsext,trop_strat_mam5_ts2,trop_strat_mam5_vbs,trop_strat_mam5_vbsext,waccm_ma,waccm_mad,waccm_ma_sulfur,waccm_sc,waccm_sc_mam4,waccm_mad_mam4,waccm_ma_mam4,waccm_tsmlt_mam4,waccm_tsmlt_mam4_vbsext,waccm_mad_mam5,waccm_ma_mam5,waccm_tsmlt_mam5,waccm_tsmlt_mam5_vbsext Prognostic mozart species packages: list of any subset of the following: DST,SSLT,SO4,GHG,OC,BC,CARBON16 @@ -224,7 +224,7 @@ User specified C compiler options to append to Makefile defaults. User specified Fortran compiler overrides Makefile default. - + Type of Fortran compiler. Used when -fc specifies a generic wrapper script such as mpif90 or ftn. diff --git a/bld/configure b/bld/configure index dce056db30..ab49ec2fd9 100755 --- a/bld/configure +++ b/bld/configure @@ -64,12 +64,15 @@ OPTIONS test_tracers, test_tracers2]. Default: none. -chem Build CAM with specified prognostic chemistry package - [ none | ghg_mam4 | terminator | trop_mam3 | trop_mam4 | trop_mam7 | trop_mozart | trop_strat_mam4_ts2 | + [ none | ghg_mam4 | terminator | trop_mam3 | trop_mam4 | trop_mam7 trop_mam_oslo | trop_mozart | trop_strat_mam4_ts2 | trop_strat_mam4_vbs | trop_strat_mam4_vbsext | trop_strat_mam5_ts2 | trop_strat_mam5_vbs | trop_strat_mam5_vbsext | waccm_ma | waccm_mad | waccm_ma_sulfur | waccm_sc | waccm_sc_mam4 | waccm_mad_mam4 | waccm_ma_mam4 | waccm_tsmlt_mam4 | waccm_tsmlt_mam4_vbsext | waccm_mad_mam5 | waccm_ma_mam5 | waccm_tsmlt_mam5 | waccm_tsmlt_mam5_vbsext ]. - Default: trop_mam4 for cam6 and trop_mam3 for cam5. + Default: trop_mam_oslo when -camnor is specified + Default: trop_mam5 for cam7 + Default: trop_mam4 for cam6 + Default: trop_mam3 for cam5. -[no]clubb_sgs Switch on [off] CLUBB_SGS. Default: on for cam6, otherwise off. -clubb_opts Comma separated list of CLUBB options to turn on/off. By default they are all off. Current option is: clubb_do_adv (Advect CLUBB moments) @@ -154,13 +157,13 @@ OPTIONS -cosp_libdir Directory containing COSP library. -esmf_libdir Directory containing ESMF library and esmf.mk file. -fc User specified Fortran compiler. Overrides Makefile default. - -fc_type Type of Fortran compiler [pgi | intel | gnu | pathscale - | ibm | nag]. This argument is used in conjunction + -fc_type Type of Fortran compiler [intel | gnu]. + This argument is used in conjunction with the -fc argument when the name of the fortran - compiler refers to a wrapper script (e.g., mpif90 - or ftn). In this case the user needs to specify + compiler refers to a wrapper script (e.g., mpif90). + In this case the user needs to specify the type of Fortran compiler that is being invoked - by the wrapper script. Default: pgi + by the wrapper script. Default: gnu -fflags A string of user specified Fortran compiler flags. Appended to Makefile defaults. See -fopt to override optimization flags. -fopt A string of user specified Fortran compiler optimization flags. @@ -589,6 +592,9 @@ my $chem_pkg = 'trop_mam4'; if ($simple_phys or $phys_pkg =~ m/^cam[34]$/ or $phys_pkg eq 'spcam_sam1mom') { $chem_pkg = 'none'; } +elsif ($camnor) { + $chem_pkg = 'trop_mam_oslo'; +} elsif ($phys_pkg eq 'cam5' or $phys_pkg eq 'spcam_m2005') { $chem_pkg = 'trop_mam3'; } @@ -2130,7 +2136,9 @@ sub write_filepath if ($chem_src_dir) { print $fh "$chem_src_dir\n"; } - if ($chem =~ /_mam/) { + if ($chem =~/_oslo/) { + print $fh "$camsrcdir/cam/src/chemistry/oslo_aero\n"; + } elsif ($chem =~ /_mam/) { print $fh "$camsrcdir/src/chemistry/modal_aero\n"; } else { print $fh "$camsrcdir/src/chemistry/bulk_aero\n"; diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml index 6326bd3c8a..02ca4efc54 100644 --- a/cime_config/config_component.xml +++ b/cime_config/config_component.xml @@ -145,8 +145,7 @@ -phys cam_dev -chem ghg_mam4 -chem trop_strat_mam5_vbs - -camnor - + -camnor -chem trop_mam_oslo -chem trop_mam7 -chem trop_strat_mam5_vbsext -chem trop_strat_mam5_ts2 diff --git a/src/chemistry/pp_trop_mam_oslo/chem_mech.doc b/src/chemistry/pp_trop_mam_oslo/chem_mech.doc new file mode 100644 index 0000000000..328b93a925 --- /dev/null +++ b/src/chemistry/pp_trop_mam_oslo/chem_mech.doc @@ -0,0 +1,162 @@ + + + |--------------------------------------------------------------------------------------------------| + | | + | | + | This is a mam-oslo simulation with : | + | (1) comments to add | + | (2) comments to add | + | | + | | + |--------------------------------------------------------------------------------------------------| + + + Solution species + ( 1) SO2 + ( 2) H2SO4 + ( 3) DMS (CH3SCH3) + ( 4) H2O2 + ( 5) SO4_NA (H2SO4) + ( 6) SO4_A1 (H2SO4) + ( 7) SO4_A2 (NH4HSO4) + ( 8) SO4_AC (H2SO4) + ( 9) SO4_PR (H2SO4) + ( 10) BC_N (C) + ( 11) BC_AX (C) + ( 12) BC_NI (C) + ( 13) BC_A (C) + ( 14) BC_AI (C) + ( 15) BC_AC (C) + ( 16) OM_NI (C) + ( 17) OM_AI (C) + ( 18) OM_AC (C) + ( 19) DST_A2 (AlSiO5) + ( 20) DST_A3 (AlSiO5) + ( 21) SS_A1 (NaCl) + ( 22) SS_A2 (NaCl) + ( 23) SS_A3 (NaCl) + ( 24) SOA_NA (C10H16O2) + ( 25) SOA_A1 (C10H16O2) + ( 26) SOA_LV (C10H16O2) + ( 27) SOA_SV (C10H16O2) + ( 28) monoterp (C10H16) + ( 29) isoprene (C5H8) + ( 30) H2O + + + Invariant species + ( 1) M + ( 2) N2 + ( 3) O2 + ( 4) O3 + ( 5) OH + ( 6) NO3 + ( 7) HO2 + + + Column integrals + ( 1) O3 - 0.000E+00 + ( 2) O2 - 0.000E+00 + +Class List +========== + + Implicit + -------- + ( 1) DMS + ( 2) SO2 + ( 3) H2O2 + ( 4) SO4_NA + ( 5) SO4_A1 + ( 6) SO4_A2 + ( 7) SO4_AC + ( 8) SO4_PR + ( 9) BC_N + ( 10) BC_AX + ( 11) BC_NI + ( 12) BC_A + ( 13) BC_AI + ( 14) BC_AC + ( 15) OM_NI + ( 16) OM_AI + ( 17) OM_AC + ( 18) DST_A2 + ( 19) DST_A3 + ( 20) SS_A1 + ( 21) SS_A2 + ( 22) SS_A3 + ( 23) H2SO4 + ( 24) SOA_NA + ( 25) SOA_A1 + ( 26) SOA_LV + ( 27) SOA_SV + ( 28) monoterp + ( 29) isoprene + ( 30) H2O + + Photolysis + jh2o2 ( 1) H2O2 + hv -> (No products) rate = ** User defined ** ( 1) + + Reactions + usr_HO2_HO2 ( 1) HO2 + HO2 -> H2O2 rate = ** User defined ** ( 2) + ( 2) H2O2 + OH -> H2O + HO2 rate = 2.90E-12*exp( -160./t) ( 3) + ( 3) DMS + OH -> SO2 rate = 9.60E-12*exp( -234./t) ( 4) + ( 4) DMS + NO3 -> SO2 + {HNO3} rate = 1.90E-13*exp( 520./t) ( 5) + ( 5) SO2 + OH + M -> H2SO4 + M troe : ko=3.00E-31*(300/t)**3.30 ( 6) + ki=1.50E-12 + f=0.60 + usr_DMS_OH ( 6) DMS + OH -> .75*SO2 + .5*HO2 + 0.029*SOA_LV + 0.114*SOA_SV rate = ** User defined ** ( 7) + ( 7) monoterp + O3 -> .15*SOA_LV rate = 8.05E-16*exp( -640./t) ( 8) + ( 8) monoterp + OH -> .15*SOA_SV rate = 1.20E-11*exp( 440./t) ( 9) + ( 9) monoterp + NO3 -> .15*SOA_SV rate = 1.20E-12*exp( 490./t) ( 10) + ( 10) isoprene + O3 -> .05*SOA_SV rate = 1.03E-14*exp( -1995./t) ( 11) + ( 11) isoprene + OH -> .05*SOA_SV rate = 2.70E-11*exp( 390./t) ( 12) + ( 12) isoprene + NO3 -> .05*SOA_SV rate = 3.15E-12*exp( -450./t) ( 13) + +Heterogeneous loss species + +Extraneous prod/loss species + ( 1) SO2 (dataset) + ( 2) BC_NI (dataset) + ( 3) BC_AX (dataset) + ( 4) BC_N (dataset) + ( 5) OM_NI (dataset) + ( 6) SO4_PR (dataset) + ( 7) H2O (dataset) + + + Equation Report + + d(SO2)/dt = r3*OH*DMS + r4*NO3*DMS + .75*r6*OH*DMS + - r5*OH*M*SO2 + d(H2SO4)/dt = r5*OH*M*SO2 + d(DMS)/dt = - r3*OH*DMS - r4*NO3*DMS - r6*OH*DMS + d(H2O2)/dt = r1 + - j1*H2O2 - r2*OH*H2O2 + d(SO4_NA)/dt = 0 + d(SO4_A1)/dt = 0 + d(SO4_A2)/dt = 0 + d(SO4_AC)/dt = 0 + d(SO4_PR)/dt = 0 + d(BC_N)/dt = 0 + d(BC_AX)/dt = 0 + d(BC_NI)/dt = 0 + d(BC_A)/dt = 0 + d(BC_AI)/dt = 0 + d(BC_AC)/dt = 0 + d(OM_NI)/dt = 0 + d(OM_AI)/dt = 0 + d(OM_AC)/dt = 0 + d(DST_A2)/dt = 0 + d(DST_A3)/dt = 0 + d(SS_A1)/dt = 0 + d(SS_A2)/dt = 0 + d(SS_A3)/dt = 0 + d(SOA_NA)/dt = 0 + d(SOA_A1)/dt = 0 + d(SOA_LV)/dt = .029*r6*OH*DMS + .15*r7*O3*monoterp + d(SOA_SV)/dt = .114*r6*OH*DMS + .15*r8*OH*monoterp + .15*r9*NO3*monoterp + .05*r10*O3*isoprene + + .05*r11*OH*isoprene + .05*r12*NO3*isoprene + d(monoterp)/dt = - r7*O3*monoterp - r8*OH*monoterp - r9*NO3*monoterp + d(isoprene)/dt = - r10*O3*isoprene - r11*OH*isoprene - r12*NO3*isoprene + d(H2O)/dt = r2*OH*H2O2 diff --git a/src/chemistry/pp_trop_mam_oslo/chem_mech.in b/src/chemistry/pp_trop_mam_oslo/chem_mech.in new file mode 100644 index 0000000000..5897d33683 --- /dev/null +++ b/src/chemistry/pp_trop_mam_oslo/chem_mech.in @@ -0,0 +1,109 @@ +BEGSIM + SPECIES + + Solution + SO2, H2SO4 + DMS -> CH3SCH3, H2O2 + SO4_NA->H2SO4, SO4_A1->H2SO4, SO4_A2->NH4HSO4 + SO4_AC->H2SO4, SO4_PR->H2SO4, BC_N->C + BC_AX->C, BC_NI->C, BC_A->C, BC_AI->C + BC_AC->C, OM_NI->C, OM_AI->C, OM_AC->C + DST_A2->AlSiO5, DST_A3->AlSiO5 + SS_A1->NaCl, SS_A2->NaCl, SS_A3->NaCl +* Approximate soa species with those of monoterpene oxidation products +* based on Paasonen et al. (2010); Taipale et al. (2008). + SOA_NA->C10H16O2, SOA_A1->C10H16O2 + SOA_LV ->C10H16O2, SOA_SV->C10H16O2 + monoterp -> C10H16, isoprene -> C5H8 + H2O + End Solution + + Fixed + M, N2, O2, O3, OH, NO3, HO2 + End Fixed + + Col-int + O3 = 0. + O2 = 0. + End Col-int + + End SPECIES + + Solution Classes + Explicit + End Explicit + Implicit + DMS, SO2, H2O2 + SO4_NA, SO4_A1, SO4_A2 + SO4_AC, SO4_PR, BC_N + BC_AX, BC_NI, BC_A, BC_AI + BC_AC, OM_NI, OM_AI, OM_AC + DST_A2, DST_A3 + SS_A1, SS_A2, SS_A3 , H2SO4 + SOA_NA, SOA_A1 + SOA_LV,SOA_SV, monoterp, isoprene + H2O + End Implicit + End Solution Classes + + CHEMISTRY + Photolysis + [jh2o2] H2O2 + hv -> + End Photolysis + + Reactions + [usr_HO2_HO2] HO2 + HO2 -> H2O2 + H2O2 + OH -> H2O + HO2 ; 2.9e-12, -160 + DMS + OH -> SO2 ; 9.6e-12, -234. + DMS + NO3 -> SO2 + HNO3 ; 1.9e-13, 520. + SO2 + OH + M -> H2SO4 + M ; 3.0e-31, 3.3, 1.5e-12, 0.0, 0.6 +* SOA has MW=168, and MSA=96, so to get correct MSA mass ==> factor of 96/168 = 0.57 +* Then account for 0.25 which is 0.25 MSA molec per DMS molec (the other 0.75 goes to SO2) +* Then 0.2 assumed yield for SOA_LV and 0.8 assumed yield for SOA_SV gives the coefficients below +* reaction rate from Chin et al 1996, JGR, vol 101, no D13 +* + [usr_DMS_OH] DMS + OH -> .75 * SO2 + .5 * HO2 + 0.029*SOA_LV + 0.114*SOA_SV +* +*cka: added organic vapor oxidation with constants from IUPAC below +* Assume a yield of 15% for SOA LV production from these reactions +* Assume a yield of 15 % for monoterpene and 5% for isoprene SOA SV production reactions +* SOA_LV: very low volatility, can nucleate or grow small particles (oxidation products from O3+monoterp) +* SOA_SV: rest of SOA formed + monoterp + O3 -> .15*SOA_LV ; 8.05e-16, -640. + monoterp + OH -> .15*SOA_SV ; 1.2e-11, 440. + monoterp + NO3 -> .15*SOA_SV ; 1.2e-12, 490. + isoprene + O3 -> .05*SOA_SV ; 1.03e-14, -1995. + isoprene + OH -> .05*SOA_SV ; 2.7e-11, 390. + isoprene + NO3 -> .05*SOA_SV ; 3.15e-12, -450. + End Reactions + + Heterogeneous + H2O2, SO2 + End Heterogeneous + + Ext Forcing + SO2 <- dataset + BC_NI <-dataset + BC_AX <-dataset + BC_N <-dataset + OM_NI <-dataset + SO4_PR <-dataset + H2O <- dataset + End Ext Forcing + + END CHEMISTRY + + SIMULATION PARAMETERS + + Version Options + model = cam + machine = intel + architecture = hybrid + vec_ftns = on + multitask = on + namemod = on + modules = on + End Version Options + + END SIMULATION PARAMETERS +ENDSIM diff --git a/src/chemistry/pp_trop_mam_oslo/chem_mods.F90 b/src/chemistry/pp_trop_mam_oslo/chem_mods.F90 new file mode 100644 index 0000000000..bcd985192b --- /dev/null +++ b/src/chemistry/pp_trop_mam_oslo/chem_mods.F90 @@ -0,0 +1,50 @@ + module chem_mods +!-------------------------------------------------------------- +! ... Basic chemistry parameters and arrays +!-------------------------------------------------------------- + use shr_kind_mod, only : r8 => shr_kind_r8 + implicit none + save + integer, parameter :: phtcnt = 1, & ! number of photolysis reactions + rxntot = 13, & ! number of total reactions + gascnt = 12, & ! number of gas phase reactions + nabscol = 2, & ! number of absorbing column densities + gas_pcnst = 30, & ! number of "gas phase" species + nfs = 7, & ! number of "fixed" species + relcnt = 0, & ! number of relationship species + grpcnt = 0, & ! number of group members + nzcnt = 38, & ! number of non-zero matrix entries + extcnt = 7, & ! number of species with external forcing + clscnt1 = 0, & ! number of species in explicit class + clscnt2 = 0, & ! number of species in hov class + clscnt3 = 0, & ! number of species in ebi class + clscnt4 = 30, & ! number of species in implicit class + clscnt5 = 0, & ! number of species in rodas class + indexm = 1, & ! index of total atm density in invariant array + indexh2o = 0, & ! index of water vapor density + clsze = 1, & ! loop length for implicit chemistry + rxt_tag_cnt = 3, & + enthalpy_cnt = 0, & + nslvd = 0 + integer :: clscnt(5) = 0 + integer :: cls_rxt_cnt(4,5) = 0 + integer :: clsmap(gas_pcnst,5) = 0 + integer :: permute(gas_pcnst,5) = 0 + integer :: diag_map(clscnt4) = 0 + real(r8) :: adv_mass(gas_pcnst) = 0._r8 + real(r8) :: crb_mass(gas_pcnst) = 0._r8 + real(r8) :: fix_mass(max(1,nfs)) + real(r8), allocatable :: cph_enthalpy(:) + integer, allocatable :: cph_rid(:) + integer, allocatable :: num_rnts(:) + integer, allocatable :: rxt_tag_map(:) + real(r8), allocatable :: pht_alias_mult(:,:) + character(len=32), allocatable :: rxt_tag_lst(:) + character(len=16), allocatable :: pht_alias_lst(:,:) + character(len=16) :: inv_lst(max(1,nfs)) + character(len=16) :: extfrc_lst(max(1,extcnt)) + logical :: frc_from_dataset(max(1,extcnt)) + logical :: is_vector + logical :: is_scalar + character(len=16) :: slvd_lst(max(1,nslvd)) + end module chem_mods diff --git a/src/chemistry/pp_trop_mam_oslo/m_rxt_id.F90 b/src/chemistry/pp_trop_mam_oslo/m_rxt_id.F90 new file mode 100644 index 0000000000..278910603d --- /dev/null +++ b/src/chemistry/pp_trop_mam_oslo/m_rxt_id.F90 @@ -0,0 +1,16 @@ + module m_rxt_id + implicit none + integer, parameter :: rid_jh2o2 = 1 + integer, parameter :: rid_usr_HO2_HO2 = 2 + integer, parameter :: rid_usr_DMS_OH = 7 + integer, parameter :: rid_r0003 = 3 + integer, parameter :: rid_r0004 = 4 + integer, parameter :: rid_r0005 = 5 + integer, parameter :: rid_r0006 = 6 + integer, parameter :: rid_r0008 = 8 + integer, parameter :: rid_r0009 = 9 + integer, parameter :: rid_r0010 = 10 + integer, parameter :: rid_r0011 = 11 + integer, parameter :: rid_r0012 = 12 + integer, parameter :: rid_r0013 = 13 + end module m_rxt_id diff --git a/src/chemistry/pp_trop_mam_oslo/m_spc_id.F90 b/src/chemistry/pp_trop_mam_oslo/m_spc_id.F90 new file mode 100644 index 0000000000..f288d118fa --- /dev/null +++ b/src/chemistry/pp_trop_mam_oslo/m_spc_id.F90 @@ -0,0 +1,33 @@ + module m_spc_id + implicit none + integer, parameter :: id_SO2 = 1 + integer, parameter :: id_H2SO4 = 2 + integer, parameter :: id_DMS = 3 + integer, parameter :: id_H2O2 = 4 + integer, parameter :: id_SO4_NA = 5 + integer, parameter :: id_SO4_A1 = 6 + integer, parameter :: id_SO4_A2 = 7 + integer, parameter :: id_SO4_AC = 8 + integer, parameter :: id_SO4_PR = 9 + integer, parameter :: id_BC_N = 10 + integer, parameter :: id_BC_AX = 11 + integer, parameter :: id_BC_NI = 12 + integer, parameter :: id_BC_A = 13 + integer, parameter :: id_BC_AI = 14 + integer, parameter :: id_BC_AC = 15 + integer, parameter :: id_OM_NI = 16 + integer, parameter :: id_OM_AI = 17 + integer, parameter :: id_OM_AC = 18 + integer, parameter :: id_DST_A2 = 19 + integer, parameter :: id_DST_A3 = 20 + integer, parameter :: id_SS_A1 = 21 + integer, parameter :: id_SS_A2 = 22 + integer, parameter :: id_SS_A3 = 23 + integer, parameter :: id_SOA_NA = 24 + integer, parameter :: id_SOA_A1 = 25 + integer, parameter :: id_SOA_LV = 26 + integer, parameter :: id_SOA_SV = 27 + integer, parameter :: id_monoterp = 28 + integer, parameter :: id_isoprene = 29 + integer, parameter :: id_H2O = 30 + end module m_spc_id diff --git a/src/chemistry/pp_trop_mam_oslo/mo_adjrxt.F90 b/src/chemistry/pp_trop_mam_oslo/mo_adjrxt.F90 new file mode 100644 index 0000000000..fe6931f11d --- /dev/null +++ b/src/chemistry/pp_trop_mam_oslo/mo_adjrxt.F90 @@ -0,0 +1,34 @@ + module mo_adjrxt + private + public :: adjrxt + contains + subroutine adjrxt( rate, inv, m, ncol, nlev ) + use shr_kind_mod, only : r8 => shr_kind_r8 + use chem_mods, only : nfs, rxntot + implicit none +!-------------------------------------------------------------------- +! ... dummy arguments +!-------------------------------------------------------------------- + integer, intent(in) :: ncol, nlev + real(r8), intent(in) :: inv(ncol,nlev,nfs) + real(r8), intent(in) :: m(ncol,nlev) + real(r8), intent(inout) :: rate(ncol,nlev,rxntot) +!-------------------------------------------------------------------- +! ... local variables +!-------------------------------------------------------------------- + real(r8) :: im(ncol,nlev) + im(:,:) = 1._r8 / m(:,:) + rate(:,:, 3) = rate(:,:, 3) * inv(:,:, 5) + rate(:,:, 4) = rate(:,:, 4) * inv(:,:, 5) + rate(:,:, 5) = rate(:,:, 5) * inv(:,:, 6) + rate(:,:, 7) = rate(:,:, 7) * inv(:,:, 5) + rate(:,:, 8) = rate(:,:, 8) * inv(:,:, 4) + rate(:,:, 9) = rate(:,:, 9) * inv(:,:, 5) + rate(:,:, 10) = rate(:,:, 10) * inv(:,:, 6) + rate(:,:, 11) = rate(:,:, 11) * inv(:,:, 4) + rate(:,:, 12) = rate(:,:, 12) * inv(:,:, 5) + rate(:,:, 13) = rate(:,:, 13) * inv(:,:, 6) + rate(:,:, 2) = rate(:,:, 2) * inv(:,:, 7) * inv(:,:, 7) * im(:,:) + rate(:,:, 6) = rate(:,:, 6) * inv(:,:, 5) * inv(:,:, 1) + end subroutine adjrxt + end module mo_adjrxt diff --git a/src/chemistry/pp_trop_mam_oslo/mo_exp_sol.F90 b/src/chemistry/pp_trop_mam_oslo/mo_exp_sol.F90 new file mode 100644 index 0000000000..cfde22391a --- /dev/null +++ b/src/chemistry/pp_trop_mam_oslo/mo_exp_sol.F90 @@ -0,0 +1,79 @@ +module mo_exp_sol + private + public :: exp_sol + public :: exp_sol_inti +contains + subroutine exp_sol_inti + use mo_tracname, only : solsym + use chem_mods, only : clscnt1, clsmap + use ppgrid, only : pver + use cam_history, only : addfld + implicit none + integer :: i,j + do i = 1,clscnt1 + j = clsmap(i,1) + call addfld( trim(solsym(j))//'_CHMP', (/ 'lev' /), 'I', '/cm3/s', 'chemical production rate' ) + call addfld( trim(solsym(j))//'_CHML', (/ 'lev' /), 'I', '/cm3/s', 'chemical loss rate' ) + enddo + end subroutine exp_sol_inti + subroutine exp_sol( base_sol, reaction_rates, het_rates, extfrc, delt, xhnm, ncol, lchnk, ltrop ) + !----------------------------------------------------------------------- + ! ... Exp_sol advances the volumetric mixing ratio + ! forward one time step via the fully explicit + ! Euler scheme + !----------------------------------------------------------------------- + use chem_mods, only : clscnt1, extcnt, gas_pcnst, clsmap, rxntot + use ppgrid, only : pcols, pver + use mo_prod_loss, only : exp_prod_loss + use mo_indprd, only : indprd + use shr_kind_mod, only : r8 => shr_kind_r8 + use cam_history, only : outfld + use mo_tracname, only : solsym + implicit none + !----------------------------------------------------------------------- + ! ... Dummy arguments + !----------------------------------------------------------------------- + integer, intent(in) :: ncol ! columns in chunck + integer, intent(in) :: lchnk ! chunk id + real(r8), intent(in) :: delt ! time step (s) + real(r8), intent(in) :: het_rates(ncol,pver,max(1,gas_pcnst)) ! het rates (1/cm^3/s) + real(r8), intent(in) :: reaction_rates(ncol,pver,rxntot) ! rxt rates (1/cm^3/s) + real(r8), intent(in) :: extfrc(ncol,pver,extcnt) ! "external insitu forcing" (1/cm^3/s) + real(r8), intent(in) :: xhnm(ncol,pver) + integer, intent(in) :: ltrop(pcols) ! chemistry troposphere boundary (index) + real(r8), intent(inout) :: base_sol(ncol,pver,gas_pcnst) ! working mixing ratios (vmr) + !----------------------------------------------------------------------- + ! ... Local variables + !----------------------------------------------------------------------- + integer :: i, k, l, m + real(r8), dimension(ncol,pver,clscnt1) :: & + prod, & + loss, & + ind_prd + real(r8), dimension(ncol,pver) :: wrk + !----------------------------------------------------------------------- + ! ... Put "independent" production in the forcing + !----------------------------------------------------------------------- + call indprd( 1, ind_prd, clscnt1, base_sol, extfrc, & + reaction_rates, ncol ) + !----------------------------------------------------------------------- + ! ... Form F(y) + !----------------------------------------------------------------------- + call exp_prod_loss( prod, loss, base_sol, reaction_rates, het_rates ) + !----------------------------------------------------------------------- + ! ... Solve for the mixing ratio at t(n+1) + !----------------------------------------------------------------------- + do m = 1,clscnt1 + l = clsmap(m,1) + do i = 1,ncol + do k = ltrop(i)+1,pver + base_sol(i,k,l) = base_sol(i,k,l) + delt * (prod(i,k,m) + ind_prd(i,k,m) - loss(i,k,m)) + end do + end do + wrk(:,:) = (prod(:,:,m) + ind_prd(:,:,m))*xhnm + call outfld( trim(solsym(l))//'_CHMP', wrk(:,:), ncol, lchnk ) + wrk(:,:) = (loss(:,:,m))*xhnm + call outfld( trim(solsym(l))//'_CHML', wrk(:,:), ncol, lchnk ) + end do + end subroutine exp_sol +end module mo_exp_sol diff --git a/src/chemistry/pp_trop_mam_oslo/mo_imp_sol.F90 b/src/chemistry/pp_trop_mam_oslo/mo_imp_sol.F90 new file mode 100644 index 0000000000..d885728ba4 --- /dev/null +++ b/src/chemistry/pp_trop_mam_oslo/mo_imp_sol.F90 @@ -0,0 +1,392 @@ +module mo_imp_sol + use shr_kind_mod, only : r8 => shr_kind_r8 + use chem_mods, only : clscnt4, gas_pcnst, clsmap + use cam_logfile, only : iulog + implicit none + private + public :: imp_slv_inti, imp_sol + save + real(r8), parameter :: rel_err = 1.e-3_r8 + real(r8), parameter :: high_rel_err = 1.e-4_r8 + !----------------------------------------------------------------------- + ! Newton-Raphson iteration limits + !----------------------------------------------------------------------- + integer, parameter :: itermax = 11 + integer, parameter :: cut_limit = 5 + real(r8), parameter :: small = 1.e-40_r8 + real(r8) :: epsilon(clscnt4) + logical :: factor(itermax) +contains + subroutine imp_slv_inti + !----------------------------------------------------------------------- + ! ... Initialize the implict solver + !----------------------------------------------------------------------- + use mo_chem_utls, only : get_spc_ndx + implicit none + !----------------------------------------------------------------------- + ! ... Local variables + !----------------------------------------------------------------------- + integer :: m, ox_ndx, o3a_ndx + real(r8) :: eps(gas_pcnst) + factor(:) = .true. + eps(:) = rel_err + ox_ndx = get_spc_ndx( 'OX' ) + if( ox_ndx < 1 ) then + ox_ndx = get_spc_ndx( 'O3' ) + end if + if( ox_ndx > 0 ) then + eps(ox_ndx) = high_rel_err + end if + m = get_spc_ndx( 'NO' ) + if( m > 0 ) then + eps(m) = high_rel_err + end if + m = get_spc_ndx( 'NO2' ) + if( m > 0 ) then + eps(m) = high_rel_err + end if + m = get_spc_ndx( 'NO3' ) + if( m > 0 ) then + eps(m) = high_rel_err + end if + m = get_spc_ndx( 'HNO3' ) + if( m > 0 ) then + eps(m) = high_rel_err + end if + m = get_spc_ndx( 'HO2NO2' ) + if( m > 0 ) then + eps(m) = high_rel_err + end if + m = get_spc_ndx( 'N2O5' ) + if( m > 0 ) then + eps(m) = high_rel_err + end if + m = get_spc_ndx( 'OH' ) + if( m > 0 ) then + eps(m) = high_rel_err + end if + m = get_spc_ndx( 'HO2' ) + if( m > 0 ) then + eps(m) = high_rel_err + end if + o3a_ndx = get_spc_ndx( 'O3A' ) + if( o3a_ndx > 0 ) then + eps(m) = high_rel_err + end if + m = get_spc_ndx( 'XNO' ) + if( m > 0 ) then + eps(m) = high_rel_err + end if + m = get_spc_ndx( 'XNO2' ) + if( m > 0 ) then + eps(m) = high_rel_err + end if + m = get_spc_ndx( 'XNO3' ) + if( m > 0 ) then + eps(m) = high_rel_err + end if + m = get_spc_ndx( 'XHNO3' ) + if( m > 0 ) then + eps(m) = high_rel_err + end if + m = get_spc_ndx( 'XHO2NO2' ) + if( m > 0 ) then + eps(m) = high_rel_err + end if + m = get_spc_ndx( 'XNO2NO3' ) + if( m > 0 ) then + eps(m) = high_rel_err + end if + m = get_spc_ndx( 'NO2XNO3' ) + if( m > 0 ) then + eps(m) = high_rel_err + end if + do m = 1,clscnt4 + epsilon(m) = eps(clsmap(m,4)) + end do + end subroutine imp_slv_inti + subroutine imp_sol( base_sol, reaction_rates, het_rates, extfrc, delt, & + ncol,nlev, lchnk, prod_out, loss_out ) + !----------------------------------------------------------------------- + ! ... imp_sol advances the volumetric mixing ratio + ! forward one time step via the fully implicit euler scheme. + ! this source is meant for small l1 cache machines such as + ! the intel pentium and itanium cpus + !----------------------------------------------------------------------- + use chem_mods, only : rxntot, extcnt, nzcnt, permute, cls_rxt_cnt + use mo_tracname, only : solsym + use mo_lin_matrix, only : linmat + use mo_nln_matrix, only : nlnmat + use mo_lu_factor, only : lu_fac + use mo_lu_solve, only : lu_slv + use mo_prod_loss, only : imp_prod_loss + use mo_indprd, only : indprd + use time_manager, only : get_nstep + use perf_mod, only : t_startf, t_stopf + implicit none + !----------------------------------------------------------------------- + ! ... dummy args + !----------------------------------------------------------------------- + integer, intent(in) :: ncol ! columns in chunck + integer, intent(in) :: nlev + integer, intent(in) :: lchnk ! chunk id + real(r8), intent(in) :: delt ! time step (s) + real(r8), intent(in) :: reaction_rates(ncol,nlev,max(1,rxntot)) ! rxt rates (1/cm^3/s) + real(r8), intent(in) :: extfrc(ncol,nlev,max(1,extcnt)) ! external in-situ forcing (1/cm^3/s) + real(r8), intent(in) :: het_rates(ncol,nlev,max(1,gas_pcnst)) ! washout rates (1/s) + real(r8), intent(inout) :: base_sol(ncol,nlev,gas_pcnst) ! species mixing ratios (vmr) + real(r8), intent(out) :: prod_out(ncol,nlev,max(1,clscnt4)) + real(r8), intent(out) :: loss_out(ncol,nlev,max(1,clscnt4)) + !----------------------------------------------------------------------- + ! ... local variables + !----------------------------------------------------------------------- + integer :: nr_iter, & + lev, & + i, & + j, & + k, l, & + m + integer :: fail_cnt, cut_cnt, stp_con_cnt + integer :: nstep + real(r8) :: interval_done, dt, dti + real(r8) :: max_delta(max(1,clscnt4)) + real(r8) :: sys_jac(max(1,nzcnt)) + real(r8) :: lin_jac(max(1,nzcnt)) + real(r8), dimension(max(1,clscnt4)) :: & + solution, & + forcing, & + iter_invariant, & + prod, & + loss + real(r8) :: lrxt(max(1,rxntot)) + real(r8) :: lsol(max(1,gas_pcnst)) + real(r8) :: lhet(max(1,gas_pcnst)) + real(r8), dimension(ncol,nlev,max(1,clscnt4)) :: & + ind_prd + logical :: convergence + logical :: frc_mask, iter_conv + logical :: converged(max(1,clscnt4)) + solution(:) = 0._r8 + !----------------------------------------------------------------------- + ! ... class independent forcing + !----------------------------------------------------------------------- + if( cls_rxt_cnt(1,4) > 0 .or. extcnt > 0 ) then + call indprd( 4, ind_prd, clscnt4, base_sol, extfrc, & + reaction_rates, ncol ) + else + do m = 1,max(1,clscnt4) + ind_prd(:,:,m) = 0._r8 + end do + end if + level_loop : do lev = 1,nlev + column_loop : do i = 1,ncol + !----------------------------------------------------------------------- + ! ... transfer from base to local work arrays + !----------------------------------------------------------------------- + do m = 1,rxntot + lrxt(m) = reaction_rates(i,lev,m) + end do + if( gas_pcnst > 0 ) then + do m = 1,gas_pcnst + lhet(m) = het_rates(i,lev,m) + end do + end if + !----------------------------------------------------------------------- + ! ... time step loop + !----------------------------------------------------------------------- + dt = delt + cut_cnt = 0 + fail_cnt = 0 + stp_con_cnt = 0 + interval_done = 0._r8 + time_step_loop : do + dti = 1._r8 / dt + !----------------------------------------------------------------------- + ! ... transfer from base to local work arrays + !----------------------------------------------------------------------- + do m = 1,gas_pcnst + lsol(m) = base_sol(i,lev,m) + end do + !----------------------------------------------------------------------- + ! ... transfer from base to class array + !----------------------------------------------------------------------- + do k = 1,clscnt4 + j = clsmap(k,4) + m = permute(k,4) + solution(m) = lsol(j) + end do + !----------------------------------------------------------------------- + ! ... set the iteration invariant part of the function f(y) + !----------------------------------------------------------------------- + if( cls_rxt_cnt(1,4) > 0 .or. extcnt > 0 ) then + do m = 1,clscnt4 + iter_invariant(m) = dti * solution(m) + ind_prd(i,lev,m) + end do + else + do m = 1,clscnt4 + iter_invariant(m) = dti * solution(m) + end do + end if + !----------------------------------------------------------------------- + ! ... the linear component + !----------------------------------------------------------------------- + if( cls_rxt_cnt(2,4) > 0 ) then + call t_startf( 'lin_mat' ) + call linmat( lin_jac, lsol, lrxt, lhet ) + call t_stopf( 'lin_mat' ) + end if + !======================================================================= + ! the newton-raphson iteration for f(y) = 0 + !======================================================================= + iter_loop : do nr_iter = 1,itermax + !----------------------------------------------------------------------- + ! ... the non-linear component + !----------------------------------------------------------------------- + if( factor(nr_iter) ) then + call t_startf( 'nln_mat' ) + call nlnmat( sys_jac, lsol, lrxt, lin_jac, dti ) + call t_stopf( 'nln_mat' ) + !----------------------------------------------------------------------- + ! ... factor the "system" matrix + !----------------------------------------------------------------------- + call t_startf( 'lu_fac' ) + call lu_fac( sys_jac ) + call t_stopf( 'lu_fac' ) + end if + !----------------------------------------------------------------------- + ! ... form f(y) + !----------------------------------------------------------------------- + call t_startf( 'prod_loss' ) + call imp_prod_loss( prod, loss, lsol, lrxt, lhet ) + call t_stopf( 'prod_loss' ) + do m = 1,clscnt4 + forcing(m) = solution(m)*dti - (iter_invariant(m) + prod(m) - loss(m)) + end do + !----------------------------------------------------------------------- + ! ... solve for the mixing ratio at t(n+1) + !----------------------------------------------------------------------- + call t_startf( 'lu_slv' ) + call lu_slv( sys_jac, forcing ) + call t_stopf( 'lu_slv' ) + do m = 1,clscnt4 + solution(m) = solution(m) + forcing(m) + end do + !----------------------------------------------------------------------- + ! ... convergence measures + !----------------------------------------------------------------------- + if( nr_iter > 1 ) then + do k = 1,clscnt4 + m = permute(k,4) + if( abs(solution(m)) > 1.e-20_r8 ) then + max_delta(k) = abs( forcing(m)/solution(m) ) + else + max_delta(k) = 0._r8 + end if + end do + end if + !----------------------------------------------------------------------- + ! ... limit iterate + !----------------------------------------------------------------------- + where( solution(:) < 0._r8 ) + solution(:) = 0._r8 + endwhere + !----------------------------------------------------------------------- + ! ... transfer latest solution back to work array + !----------------------------------------------------------------------- + do k = 1,clscnt4 + j = clsmap(k,4) + m = permute(k,4) + lsol(j) = solution(m) + end do + !----------------------------------------------------------------------- + ! ... check for convergence + !----------------------------------------------------------------------- + converged(:) = .true. + if( nr_iter > 1 ) then + do k = 1,clscnt4 + m = permute(k,4) + frc_mask = abs( forcing(m) ) > small + if( frc_mask ) then + converged(k) = abs(forcing(m)) <= epsilon(k)*abs(solution(m)) + else + converged(k) = .true. + end if + end do + convergence = all( converged(:) ) + if( convergence ) then + exit + end if + end if + end do iter_loop + !----------------------------------------------------------------------- + ! ... check for newton-raphson convergence + !----------------------------------------------------------------------- + if( .not. convergence ) then + !----------------------------------------------------------------------- + ! ... non-convergence + !----------------------------------------------------------------------- + fail_cnt = fail_cnt + 1 + nstep = get_nstep() + write(iulog,'('' imp_sol: Time step '',1p,e21.13,'' failed to converge @ (lchnk,lev,col,nstep) = '',4i6)') & + dt,lchnk,lev,i,nstep + stp_con_cnt = 0 + if( cut_cnt < cut_limit ) then + cut_cnt = cut_cnt + 1 + if( cut_cnt < cut_limit ) then + dt = .5_r8 * dt + else + dt = .1_r8 * dt + end if + cycle time_step_loop + else + write(iulog,'('' imp_sol: Failed to converge @ (lchnk,lev,col,nstep,dt,time) = '',4i6,1p,2e21.13)') & + lchnk,lev,i,nstep,dt,interval_done+dt + do m = 1,clscnt4 + if( .not. converged(m) ) then + write(iulog,'(1x,a8,1x,1pe10.3)') solsym(clsmap(m,4)), max_delta(m) + end if + end do + end if + end if + !----------------------------------------------------------------------- + ! ... check for interval done + !----------------------------------------------------------------------- + interval_done = interval_done + dt + if( abs( delt - interval_done ) <= .0001_r8 ) then + if( fail_cnt > 0 ) then + write(iulog,*) 'imp_sol : @ (lchnk,lev,col) = ',lchnk,lev,i,' failed ',fail_cnt,' times' + end if + exit time_step_loop + else + !----------------------------------------------------------------------- + ! ... transfer latest solution back to base array + !----------------------------------------------------------------------- + if( convergence ) then + stp_con_cnt = stp_con_cnt + 1 + end if + do m = 1,gas_pcnst + base_sol(i,lev,m) = lsol(m) + end do + if( stp_con_cnt >= 2 ) then + dt = 2._r8*dt + stp_con_cnt = 0 + end if + dt = min( dt,delt-interval_done ) + ! write(iulog,'('' imp_sol: New time step '',1p,e21.13)') dt + end if + end do time_step_loop + !----------------------------------------------------------------------- + ! ... Transfer latest solution back to base array + !----------------------------------------------------------------------- + cls_loop: do k = 1,clscnt4 + j = clsmap(k,4) + m = permute(k,4) + base_sol(i,lev,j) = solution(m) + ! output diagnostics + prod_out(i,lev,k) = prod(k) + ind_prd(i,lev,k) + loss_out(i,lev,k) = loss(k) + end do cls_loop + end do column_loop + end do level_loop + end subroutine imp_sol +end module mo_imp_sol diff --git a/src/chemistry/pp_trop_mam_oslo/mo_indprd.F90 b/src/chemistry/pp_trop_mam_oslo/mo_indprd.F90 new file mode 100644 index 0000000000..f9ec6830fb --- /dev/null +++ b/src/chemistry/pp_trop_mam_oslo/mo_indprd.F90 @@ -0,0 +1,56 @@ + module mo_indprd + use shr_kind_mod, only : r8 => shr_kind_r8 + private + public :: indprd + contains + subroutine indprd( class, prod, nprod, y, extfrc, rxt, ncol ) + use chem_mods, only : gas_pcnst, extcnt, rxntot + use ppgrid, only : pver + implicit none +!-------------------------------------------------------------------- +! ... dummy arguments +!-------------------------------------------------------------------- + integer, intent(in) :: class + integer, intent(in) :: ncol + integer, intent(in) :: nprod + real(r8), intent(in) :: y(ncol,pver,gas_pcnst) + real(r8), intent(in) :: rxt(ncol,pver,rxntot) + real(r8), intent(in) :: extfrc(ncol,pver,extcnt) + real(r8), intent(inout) :: prod(ncol,pver,nprod) +!-------------------------------------------------------------------- +! ... "independent" production for Implicit species +!-------------------------------------------------------------------- + if( class == 4 ) then + prod(:,:,1) = 0._r8 + prod(:,:,2) = + extfrc(:,:,1) + prod(:,:,3) =rxt(:,:,2) + prod(:,:,4) = 0._r8 + prod(:,:,5) = 0._r8 + prod(:,:,6) = 0._r8 + prod(:,:,7) = 0._r8 + prod(:,:,8) = + extfrc(:,:,6) + prod(:,:,9) = + extfrc(:,:,4) + prod(:,:,10) = + extfrc(:,:,3) + prod(:,:,11) = + extfrc(:,:,2) + prod(:,:,12) = 0._r8 + prod(:,:,13) = 0._r8 + prod(:,:,14) = 0._r8 + prod(:,:,15) = + extfrc(:,:,5) + prod(:,:,16) = 0._r8 + prod(:,:,17) = 0._r8 + prod(:,:,18) = 0._r8 + prod(:,:,19) = 0._r8 + prod(:,:,20) = 0._r8 + prod(:,:,21) = 0._r8 + prod(:,:,22) = 0._r8 + prod(:,:,23) = 0._r8 + prod(:,:,24) = 0._r8 + prod(:,:,25) = 0._r8 + prod(:,:,26) = 0._r8 + prod(:,:,27) = 0._r8 + prod(:,:,28) = 0._r8 + prod(:,:,29) = 0._r8 + prod(:,:,30) = + extfrc(:,:,7) + end if + end subroutine indprd + end module mo_indprd diff --git a/src/chemistry/pp_trop_mam_oslo/mo_lin_matrix.F90 b/src/chemistry/pp_trop_mam_oslo/mo_lin_matrix.F90 new file mode 100644 index 0000000000..e4c7687ebb --- /dev/null +++ b/src/chemistry/pp_trop_mam_oslo/mo_lin_matrix.F90 @@ -0,0 +1,74 @@ + module mo_lin_matrix + private + public :: linmat + contains + subroutine linmat01( mat, y, rxt, het_rates ) +!---------------------------------------------- +! ... linear matrix entries for implicit species +!---------------------------------------------- + use chem_mods, only : gas_pcnst, rxntot, nzcnt + use shr_kind_mod, only : r8 => shr_kind_r8 + implicit none +!---------------------------------------------- +! ... dummy arguments +!---------------------------------------------- + real(r8), intent(in) :: y(gas_pcnst) + real(r8), intent(in) :: rxt(rxntot) + real(r8), intent(in) :: het_rates(max(1,gas_pcnst)) + real(r8), intent(inout) :: mat(nzcnt) + mat(1) = -( rxt(4) + rxt(5) + rxt(7) + het_rates(3) ) + mat(5) = -( rxt(6) + het_rates(1) ) + mat(2) = rxt(4) + rxt(5) + .750_r8*rxt(7) + mat(7) = -( rxt(1) + rxt(3) + het_rates(4) ) + mat(9) = -( het_rates(5) ) + mat(10) = -( het_rates(6) ) + mat(11) = -( het_rates(7) ) + mat(12) = -( het_rates(8) ) + mat(13) = -( het_rates(9) ) + mat(14) = -( het_rates(10) ) + mat(15) = -( het_rates(11) ) + mat(16) = -( het_rates(12) ) + mat(17) = -( het_rates(13) ) + mat(18) = -( het_rates(14) ) + mat(19) = -( het_rates(15) ) + mat(20) = -( het_rates(16) ) + mat(21) = -( het_rates(17) ) + mat(22) = -( het_rates(18) ) + mat(23) = -( het_rates(19) ) + mat(24) = -( het_rates(20) ) + mat(25) = -( het_rates(21) ) + mat(26) = -( het_rates(22) ) + mat(27) = -( het_rates(23) ) + mat(28) = -( het_rates(2) ) + mat(6) = rxt(6) + mat(29) = -( het_rates(24) ) + mat(30) = -( het_rates(25) ) + mat(31) = -( het_rates(26) ) + mat(3) = .029_r8*rxt(7) + mat(33) = .150_r8*rxt(8) + mat(32) = -( het_rates(27) ) + mat(4) = .114_r8*rxt(7) + mat(34) = .150_r8*rxt(9) + .150_r8*rxt(10) + mat(36) = .050_r8*rxt(11) + .050_r8*rxt(12) + .050_r8*rxt(13) + mat(35) = -( rxt(8) + rxt(9) + rxt(10) + het_rates(28) ) + mat(37) = -( rxt(11) + rxt(12) + rxt(13) + het_rates(29) ) + mat(38) = -( het_rates(30) ) + mat(8) = rxt(3) + end subroutine linmat01 + subroutine linmat( mat, y, rxt, het_rates ) +!---------------------------------------------- +! ... linear matrix entries for implicit species +!---------------------------------------------- + use chem_mods, only : gas_pcnst, rxntot, nzcnt + use shr_kind_mod, only : r8 => shr_kind_r8 + implicit none +!---------------------------------------------- +! ... dummy arguments +!---------------------------------------------- + real(r8), intent(in) :: y(gas_pcnst) + real(r8), intent(in) :: rxt(rxntot) + real(r8), intent(in) :: het_rates(max(1,gas_pcnst)) + real(r8), intent(inout) :: mat(nzcnt) + call linmat01( mat, y, rxt, het_rates ) + end subroutine linmat + end module mo_lin_matrix diff --git a/src/chemistry/pp_trop_mam_oslo/mo_lu_factor.F90 b/src/chemistry/pp_trop_mam_oslo/mo_lu_factor.F90 new file mode 100644 index 0000000000..703de44018 --- /dev/null +++ b/src/chemistry/pp_trop_mam_oslo/mo_lu_factor.F90 @@ -0,0 +1,57 @@ + module mo_lu_factor + private + public :: lu_fac + contains + subroutine lu_fac01( lu ) + use shr_kind_mod, only : r8 => shr_kind_r8 + implicit none +!----------------------------------------------------------------------- +! ... dummy args +!----------------------------------------------------------------------- + real(r8), intent(inout) :: lu(:) + lu(1) = 1._r8 / lu(1) + lu(2) = lu(2) * lu(1) + lu(3) = lu(3) * lu(1) + lu(4) = lu(4) * lu(1) + lu(5) = 1._r8 / lu(5) + lu(6) = lu(6) * lu(5) + lu(7) = 1._r8 / lu(7) + lu(8) = lu(8) * lu(7) + lu(9) = 1._r8 / lu(9) + lu(10) = 1._r8 / lu(10) + lu(11) = 1._r8 / lu(11) + lu(12) = 1._r8 / lu(12) + lu(13) = 1._r8 / lu(13) + lu(14) = 1._r8 / lu(14) + lu(15) = 1._r8 / lu(15) + lu(16) = 1._r8 / lu(16) + lu(17) = 1._r8 / lu(17) + lu(18) = 1._r8 / lu(18) + lu(19) = 1._r8 / lu(19) + lu(20) = 1._r8 / lu(20) + lu(21) = 1._r8 / lu(21) + lu(22) = 1._r8 / lu(22) + lu(23) = 1._r8 / lu(23) + lu(24) = 1._r8 / lu(24) + lu(25) = 1._r8 / lu(25) + lu(26) = 1._r8 / lu(26) + lu(27) = 1._r8 / lu(27) + lu(28) = 1._r8 / lu(28) + lu(29) = 1._r8 / lu(29) + lu(30) = 1._r8 / lu(30) + lu(31) = 1._r8 / lu(31) + lu(32) = 1._r8 / lu(32) + lu(35) = 1._r8 / lu(35) + lu(37) = 1._r8 / lu(37) + lu(38) = 1._r8 / lu(38) + end subroutine lu_fac01 + subroutine lu_fac( lu ) + use shr_kind_mod, only : r8 => shr_kind_r8 + implicit none +!----------------------------------------------------------------------- +! ... dummy args +!----------------------------------------------------------------------- + real(r8), intent(inout) :: lu(:) + call lu_fac01( lu ) + end subroutine lu_fac + end module mo_lu_factor diff --git a/src/chemistry/pp_trop_mam_oslo/mo_lu_solve.F90 b/src/chemistry/pp_trop_mam_oslo/mo_lu_solve.F90 new file mode 100644 index 0000000000..862191c56b --- /dev/null +++ b/src/chemistry/pp_trop_mam_oslo/mo_lu_solve.F90 @@ -0,0 +1,90 @@ + module mo_lu_solve + private + public :: lu_slv + contains + subroutine lu_slv01( lu, b ) + use shr_kind_mod, only : r8 => shr_kind_r8 + use chem_mods, only : clscnt4, nzcnt + implicit none +!----------------------------------------------------------------------- +! ... Dummy args +!----------------------------------------------------------------------- + real(r8), intent(in) :: lu(:) + real(r8), intent(inout) :: b(:) +!----------------------------------------------------------------------- +! ... Local variables +!----------------------------------------------------------------------- +!----------------------------------------------------------------------- +! ... solve L * y = b +!----------------------------------------------------------------------- + b(2) = b(2) - lu(2) * b(1) + b(26) = b(26) - lu(3) * b(1) + b(27) = b(27) - lu(4) * b(1) + b(23) = b(23) - lu(6) * b(2) + b(30) = b(30) - lu(8) * b(3) + end subroutine lu_slv01 + subroutine lu_slv02( lu, b ) + use shr_kind_mod, only : r8 => shr_kind_r8 + use chem_mods, only : clscnt4, nzcnt + implicit none +!----------------------------------------------------------------------- +! ... Dummy args +!----------------------------------------------------------------------- + real(r8), intent(in) :: lu(:) + real(r8), intent(inout) :: b(:) +!----------------------------------------------------------------------- +! ... Local variables +!----------------------------------------------------------------------- +!----------------------------------------------------------------------- +! ... solve L * y = b +!----------------------------------------------------------------------- +!----------------------------------------------------------------------- +! ... Solve U * x = y +!----------------------------------------------------------------------- + b(30) = b(30) * lu(38) + b(29) = b(29) * lu(37) + b(27) = b(27) - lu(36) * b(29) + b(28) = b(28) * lu(35) + b(27) = b(27) - lu(34) * b(28) + b(26) = b(26) - lu(33) * b(28) + b(27) = b(27) * lu(32) + b(26) = b(26) * lu(31) + b(25) = b(25) * lu(30) + b(24) = b(24) * lu(29) + b(23) = b(23) * lu(28) + b(22) = b(22) * lu(27) + b(21) = b(21) * lu(26) + b(20) = b(20) * lu(25) + b(19) = b(19) * lu(24) + b(18) = b(18) * lu(23) + b(17) = b(17) * lu(22) + b(16) = b(16) * lu(21) + b(15) = b(15) * lu(20) + b(14) = b(14) * lu(19) + b(13) = b(13) * lu(18) + b(12) = b(12) * lu(17) + b(11) = b(11) * lu(16) + b(10) = b(10) * lu(15) + b(9) = b(9) * lu(14) + b(8) = b(8) * lu(13) + b(7) = b(7) * lu(12) + b(6) = b(6) * lu(11) + b(5) = b(5) * lu(10) + b(4) = b(4) * lu(9) + b(3) = b(3) * lu(7) + b(2) = b(2) * lu(5) + b(1) = b(1) * lu(1) + end subroutine lu_slv02 + subroutine lu_slv( lu, b ) + use shr_kind_mod, only : r8 => shr_kind_r8 + use chem_mods, only : clscnt4, nzcnt + implicit none +!----------------------------------------------------------------------- +! ... Dummy args +!----------------------------------------------------------------------- + real(r8), intent(in) :: lu(:) + real(r8), intent(inout) :: b(:) + call lu_slv01( lu, b ) + call lu_slv02( lu, b ) + end subroutine lu_slv + end module mo_lu_solve diff --git a/src/chemistry/pp_trop_mam_oslo/mo_nln_matrix.F90 b/src/chemistry/pp_trop_mam_oslo/mo_nln_matrix.F90 new file mode 100644 index 0000000000..3aa3cd3972 --- /dev/null +++ b/src/chemistry/pp_trop_mam_oslo/mo_nln_matrix.F90 @@ -0,0 +1,103 @@ + module mo_nln_matrix + use shr_kind_mod, only : r8 => shr_kind_r8 + private + public :: nlnmat + contains + subroutine nlnmat( mat, y, rxt, lmat, dti ) + use chem_mods, only : gas_pcnst, rxntot, nzcnt + implicit none +!---------------------------------------------- +! ... dummy arguments +!---------------------------------------------- + real(r8), intent(in) :: dti + real(r8), intent(in) :: lmat(nzcnt) + real(r8), intent(in) :: y(gas_pcnst) + real(r8), intent(in) :: rxt(rxntot) + real(r8), intent(inout) :: mat(nzcnt) + call nlnmat_finit( mat, lmat, dti ) + end subroutine nlnmat + subroutine nlnmat_finit( mat, lmat, dti ) + use chem_mods, only : gas_pcnst, rxntot, nzcnt + implicit none +!---------------------------------------------- +! ... dummy arguments +!---------------------------------------------- + real(r8), intent(in) :: dti + real(r8), intent(in) :: lmat(nzcnt) + real(r8), intent(inout) :: mat(nzcnt) +!---------------------------------------------- +! ... local variables +!---------------------------------------------- +!---------------------------------------------- +! ... complete matrix entries implicit species +!---------------------------------------------- + mat( 1) = lmat( 1) + mat( 2) = lmat( 2) + mat( 3) = lmat( 3) + mat( 4) = lmat( 4) + mat( 5) = lmat( 5) + mat( 6) = lmat( 6) + mat( 7) = lmat( 7) + mat( 8) = lmat( 8) + mat( 9) = lmat( 9) + mat( 10) = lmat( 10) + mat( 11) = lmat( 11) + mat( 12) = lmat( 12) + mat( 13) = lmat( 13) + mat( 14) = lmat( 14) + mat( 15) = lmat( 15) + mat( 16) = lmat( 16) + mat( 17) = lmat( 17) + mat( 18) = lmat( 18) + mat( 19) = lmat( 19) + mat( 20) = lmat( 20) + mat( 21) = lmat( 21) + mat( 22) = lmat( 22) + mat( 23) = lmat( 23) + mat( 24) = lmat( 24) + mat( 25) = lmat( 25) + mat( 26) = lmat( 26) + mat( 27) = lmat( 27) + mat( 28) = lmat( 28) + mat( 29) = lmat( 29) + mat( 30) = lmat( 30) + mat( 31) = lmat( 31) + mat( 32) = lmat( 32) + mat( 33) = lmat( 33) + mat( 34) = lmat( 34) + mat( 35) = lmat( 35) + mat( 36) = lmat( 36) + mat( 37) = lmat( 37) + mat( 38) = lmat( 38) + mat( 1) = mat( 1) - dti + mat( 5) = mat( 5) - dti + mat( 7) = mat( 7) - dti + mat( 9) = mat( 9) - dti + mat( 10) = mat( 10) - dti + mat( 11) = mat( 11) - dti + mat( 12) = mat( 12) - dti + mat( 13) = mat( 13) - dti + mat( 14) = mat( 14) - dti + mat( 15) = mat( 15) - dti + mat( 16) = mat( 16) - dti + mat( 17) = mat( 17) - dti + mat( 18) = mat( 18) - dti + mat( 19) = mat( 19) - dti + mat( 20) = mat( 20) - dti + mat( 21) = mat( 21) - dti + mat( 22) = mat( 22) - dti + mat( 23) = mat( 23) - dti + mat( 24) = mat( 24) - dti + mat( 25) = mat( 25) - dti + mat( 26) = mat( 26) - dti + mat( 27) = mat( 27) - dti + mat( 28) = mat( 28) - dti + mat( 29) = mat( 29) - dti + mat( 30) = mat( 30) - dti + mat( 31) = mat( 31) - dti + mat( 32) = mat( 32) - dti + mat( 35) = mat( 35) - dti + mat( 37) = mat( 37) - dti + mat( 38) = mat( 38) - dti + end subroutine nlnmat_finit + end module mo_nln_matrix diff --git a/src/chemistry/pp_trop_mam_oslo/mo_phtadj.F90 b/src/chemistry/pp_trop_mam_oslo/mo_phtadj.F90 new file mode 100644 index 0000000000..aaa43829fe --- /dev/null +++ b/src/chemistry/pp_trop_mam_oslo/mo_phtadj.F90 @@ -0,0 +1,24 @@ + module mo_phtadj + private + public :: phtadj + contains + subroutine phtadj( p_rate, inv, m, ncol, nlev ) + use chem_mods, only : nfs, phtcnt + use shr_kind_mod, only : r8 => shr_kind_r8 + implicit none +!-------------------------------------------------------------------- +! ... dummy arguments +!-------------------------------------------------------------------- + integer, intent(in) :: ncol, nlev + real(r8), intent(in) :: inv(ncol,nlev,max(1,nfs)) + real(r8), intent(in) :: m(ncol,nlev) + real(r8), intent(inout) :: p_rate(ncol,nlev,max(1,phtcnt)) +!-------------------------------------------------------------------- +! ... local variables +!-------------------------------------------------------------------- + integer :: k + real(r8) :: im(ncol,nlev) + do k = 1,nlev + end do + end subroutine phtadj + end module mo_phtadj diff --git a/src/chemistry/pp_trop_mam_oslo/mo_prod_loss.F90 b/src/chemistry/pp_trop_mam_oslo/mo_prod_loss.F90 new file mode 100644 index 0000000000..0cbb77be48 --- /dev/null +++ b/src/chemistry/pp_trop_mam_oslo/mo_prod_loss.F90 @@ -0,0 +1,97 @@ + module mo_prod_loss + use shr_kind_mod, only : r8 => shr_kind_r8 + private + public :: exp_prod_loss + public :: imp_prod_loss + contains + subroutine exp_prod_loss( prod, loss, y, rxt, het_rates ) + use ppgrid, only : pver + implicit none +!-------------------------------------------------------------------- +! ... dummy args +!-------------------------------------------------------------------- + real(r8), dimension(:,:,:), intent(out) :: & + prod, & + loss + real(r8), intent(in) :: y(:,:,:) + real(r8), intent(in) :: rxt(:,:,:) + real(r8), intent(in) :: het_rates(:,:,:) + end subroutine exp_prod_loss + subroutine imp_prod_loss( prod, loss, y, rxt, het_rates ) + use ppgrid, only : pver + implicit none +!-------------------------------------------------------------------- +! ... dummy args +!-------------------------------------------------------------------- + real(r8), dimension(:), intent(out) :: & + prod, & + loss + real(r8), intent(in) :: y(:) + real(r8), intent(in) :: rxt(:) + real(r8), intent(in) :: het_rates(:) +!-------------------------------------------------------------------- +! ... loss and production for Implicit method +!-------------------------------------------------------------------- + loss(1) = ( + rxt(4) + rxt(5) + rxt(7) + het_rates(3))* y(3) + prod(1) = 0._r8 + loss(2) = ( + rxt(6) + het_rates(1))* y(1) + prod(2) = (rxt(4) +rxt(5) +.750_r8*rxt(7))*y(3) + loss(3) = ( + rxt(1) + rxt(3) + het_rates(4))* y(4) + prod(3) = 0._r8 + loss(4) = ( + het_rates(5))* y(5) + prod(4) = 0._r8 + loss(5) = ( + het_rates(6))* y(6) + prod(5) = 0._r8 + loss(6) = ( + het_rates(7))* y(7) + prod(6) = 0._r8 + loss(7) = ( + het_rates(8))* y(8) + prod(7) = 0._r8 + loss(8) = ( + het_rates(9))* y(9) + prod(8) = 0._r8 + loss(9) = ( + het_rates(10))* y(10) + prod(9) = 0._r8 + loss(10) = ( + het_rates(11))* y(11) + prod(10) = 0._r8 + loss(11) = ( + het_rates(12))* y(12) + prod(11) = 0._r8 + loss(12) = ( + het_rates(13))* y(13) + prod(12) = 0._r8 + loss(13) = ( + het_rates(14))* y(14) + prod(13) = 0._r8 + loss(14) = ( + het_rates(15))* y(15) + prod(14) = 0._r8 + loss(15) = ( + het_rates(16))* y(16) + prod(15) = 0._r8 + loss(16) = ( + het_rates(17))* y(17) + prod(16) = 0._r8 + loss(17) = ( + het_rates(18))* y(18) + prod(17) = 0._r8 + loss(18) = ( + het_rates(19))* y(19) + prod(18) = 0._r8 + loss(19) = ( + het_rates(20))* y(20) + prod(19) = 0._r8 + loss(20) = ( + het_rates(21))* y(21) + prod(20) = 0._r8 + loss(21) = ( + het_rates(22))* y(22) + prod(21) = 0._r8 + loss(22) = ( + het_rates(23))* y(23) + prod(22) = 0._r8 + loss(23) = ( + het_rates(2))* y(2) + prod(23) =rxt(6)*y(1) + loss(24) = ( + het_rates(24))* y(24) + prod(24) = 0._r8 + loss(25) = ( + het_rates(25))* y(25) + prod(25) = 0._r8 + loss(26) = ( + het_rates(26))* y(26) + prod(26) =.029_r8*rxt(7)*y(3) +.150_r8*rxt(8)*y(28) + loss(27) = ( + het_rates(27))* y(27) + prod(27) = (.050_r8*rxt(11) +.050_r8*rxt(12) +.050_r8*rxt(13))*y(29) & + + (.150_r8*rxt(9) +.150_r8*rxt(10))*y(28) +.114_r8*rxt(7)*y(3) + loss(28) = ( + rxt(8) + rxt(9) + rxt(10) + het_rates(28))* y(28) + prod(28) = 0._r8 + loss(29) = ( + rxt(11) + rxt(12) + rxt(13) + het_rates(29))* y(29) + prod(29) = 0._r8 + loss(30) = ( + het_rates(30))* y(30) + prod(30) =rxt(3)*y(4) + end subroutine imp_prod_loss + end module mo_prod_loss diff --git a/src/chemistry/pp_trop_mam_oslo/mo_rxt_rates_conv.F90 b/src/chemistry/pp_trop_mam_oslo/mo_rxt_rates_conv.F90 new file mode 100644 index 0000000000..7f9000e78e --- /dev/null +++ b/src/chemistry/pp_trop_mam_oslo/mo_rxt_rates_conv.F90 @@ -0,0 +1,25 @@ +module mo_rxt_rates_conv + use shr_kind_mod, only : r8 => shr_kind_r8 + implicit none + private + public :: set_rates +contains + subroutine set_rates( rxt_rates, sol, ncol ) + real(r8), intent(inout) :: rxt_rates(:,:,:) + real(r8), intent(in) :: sol(:,:,:) + integer, intent(in) :: ncol + rxt_rates(:ncol,:, 1) = rxt_rates(:ncol,:, 1)*sol(:ncol,:, 4) ! rate_const*H2O2 + ! rate_const + rxt_rates(:ncol,:, 3) = rxt_rates(:ncol,:, 3)*sol(:ncol,:, 4) ! rate_const*OH*H2O2 + rxt_rates(:ncol,:, 4) = rxt_rates(:ncol,:, 4)*sol(:ncol,:, 3) ! rate_const*OH*DMS + rxt_rates(:ncol,:, 5) = rxt_rates(:ncol,:, 5)*sol(:ncol,:, 3) ! rate_const*NO3*DMS + rxt_rates(:ncol,:, 6) = rxt_rates(:ncol,:, 6)*sol(:ncol,:, 1) ! rate_const*OH*M*SO2 + rxt_rates(:ncol,:, 7) = rxt_rates(:ncol,:, 7)*sol(:ncol,:, 3) ! rate_const*OH*DMS + rxt_rates(:ncol,:, 8) = rxt_rates(:ncol,:, 8)*sol(:ncol,:, 28) ! rate_const*O3*monoterp + rxt_rates(:ncol,:, 9) = rxt_rates(:ncol,:, 9)*sol(:ncol,:, 28) ! rate_const*OH*monoterp + rxt_rates(:ncol,:, 10) = rxt_rates(:ncol,:, 10)*sol(:ncol,:, 28) ! rate_const*NO3*monoterp + rxt_rates(:ncol,:, 11) = rxt_rates(:ncol,:, 11)*sol(:ncol,:, 29) ! rate_const*O3*isoprene + rxt_rates(:ncol,:, 12) = rxt_rates(:ncol,:, 12)*sol(:ncol,:, 29) ! rate_const*OH*isoprene + rxt_rates(:ncol,:, 13) = rxt_rates(:ncol,:, 13)*sol(:ncol,:, 29) ! rate_const*NO3*isoprene + end subroutine set_rates +end module mo_rxt_rates_conv diff --git a/src/chemistry/pp_trop_mam_oslo/mo_setrxt.F90 b/src/chemistry/pp_trop_mam_oslo/mo_setrxt.F90 new file mode 100644 index 0000000000..b9909e2e6b --- /dev/null +++ b/src/chemistry/pp_trop_mam_oslo/mo_setrxt.F90 @@ -0,0 +1,90 @@ + + module mo_setrxt + + use shr_kind_mod, only : r8 => shr_kind_r8 + + private + public :: setrxt + public :: setrxt_hrates + + contains + + subroutine setrxt( rate, temp, m, ncol ) + + use ppgrid, only : pver, pcols + use shr_kind_mod, only : r8 => shr_kind_r8 + use chem_mods, only : rxntot + use mo_jpl, only : jpl + + implicit none + +!------------------------------------------------------- +! ... dummy arguments +!------------------------------------------------------- + integer, intent(in) :: ncol + real(r8), intent(in) :: temp(pcols,pver) + real(r8), intent(in) :: m(ncol,pver) + real(r8), intent(inout) :: rate(ncol,pver,rxntot) + +!------------------------------------------------------- +! ... local variables +!------------------------------------------------------- + integer :: n + real(r8) :: itemp(ncol,pver) + real(r8) :: exp_fac(ncol,pver) + real(r8) :: ko(ncol,pver) + real(r8) :: kinf(ncol,pver) + + itemp(:ncol,:) = 1._r8 / temp(:ncol,:) + n = ncol*pver + rate(:,:,3) = 2.9e-12_r8 * exp( -160._r8 * itemp(:,:) ) + rate(:,:,4) = 9.6e-12_r8 * exp( -234._r8 * itemp(:,:) ) + rate(:,:,5) = 1.9e-13_r8 * exp( 520._r8 * itemp(:,:) ) + rate(:,:,8) = 8.05e-16_r8 * exp( -640._r8 * itemp(:,:) ) + rate(:,:,9) = 1.2e-11_r8 * exp( 440._r8 * itemp(:,:) ) + rate(:,:,10) = 1.2e-12_r8 * exp( 490._r8 * itemp(:,:) ) + rate(:,:,11) = 1.03e-14_r8 * exp( -1995._r8 * itemp(:,:) ) + rate(:,:,12) = 2.7e-11_r8 * exp( 390._r8 * itemp(:,:) ) + rate(:,:,13) = 3.15e-12_r8 * exp( -450._r8 * itemp(:,:) ) + + itemp(:,:) = 300._r8 * itemp(:,:) + + ko(:,:) = 3.0e-31_r8 * itemp(:,:)**3.3_r8 + kinf(:,:) = 1.5e-12_r8 + call jpl( rate(1,1,6), m, 0.6_r8, ko, kinf, n ) + + end subroutine setrxt + + + subroutine setrxt_hrates( rate, temp, m, ncol, kbot ) + + use ppgrid, only : pver, pcols + use shr_kind_mod, only : r8 => shr_kind_r8 + use chem_mods, only : rxntot + use mo_jpl, only : jpl + + implicit none + +!------------------------------------------------------- +! ... dummy arguments +!------------------------------------------------------- + integer, intent(in) :: ncol + integer, intent(in) :: kbot + real(r8), intent(in) :: temp(pcols,pver) + real(r8), intent(in) :: m(ncol,pver) + real(r8), intent(inout) :: rate(ncol,pver,rxntot) + +!------------------------------------------------------- +! ... local variables +!------------------------------------------------------- + integer :: n + real(r8) :: itemp(ncol,kbot) + real(r8) :: exp_fac(ncol,kbot) + real(r8) :: ko(ncol,kbot) + real(r8) :: kinf(ncol,kbot) + real(r8) :: wrk(ncol,kbot) + + + end subroutine setrxt_hrates + + end module mo_setrxt diff --git a/src/chemistry/pp_trop_mam_oslo/mo_sim_dat.F90 b/src/chemistry/pp_trop_mam_oslo/mo_sim_dat.F90 new file mode 100644 index 0000000000..ff81ecfc5d --- /dev/null +++ b/src/chemistry/pp_trop_mam_oslo/mo_sim_dat.F90 @@ -0,0 +1,132 @@ + + module mo_sim_dat + + private + public :: set_sim_dat + + contains + + subroutine set_sim_dat + + use chem_mods, only : clscnt, cls_rxt_cnt, clsmap, permute, adv_mass, fix_mass, crb_mass + use chem_mods, only : diag_map + use chem_mods, only : phtcnt, rxt_tag_cnt, rxt_tag_lst, rxt_tag_map + use chem_mods, only : pht_alias_lst, pht_alias_mult + use chem_mods, only : extfrc_lst, inv_lst, slvd_lst + use chem_mods, only : enthalpy_cnt, cph_enthalpy, cph_rid, num_rnts, rxntot + use cam_abortutils,only : endrun + use mo_tracname, only : solsym + use chem_mods, only : frc_from_dataset + use chem_mods, only : is_scalar, is_vector + use shr_kind_mod, only : r8 => shr_kind_r8 + use cam_logfile, only : iulog + + implicit none + +!-------------------------------------------------------------- +! ... local variables +!-------------------------------------------------------------- + integer :: ios + + is_scalar = .true. + is_vector = .false. + + clscnt(:) = (/ 0, 0, 0, 30, 0 /) + + cls_rxt_cnt(:,4) = (/ 1, 12, 0, 30 /) + + solsym(: 30) = (/ 'SO2 ','H2SO4 ','DMS ','H2O2 ','SO4_NA ', & + 'SO4_A1 ','SO4_A2 ','SO4_AC ','SO4_PR ','BC_N ', & + 'BC_AX ','BC_NI ','BC_A ','BC_AI ','BC_AC ', & + 'OM_NI ','OM_AI ','OM_AC ','DST_A2 ','DST_A3 ', & + 'SS_A1 ','SS_A2 ','SS_A3 ','SOA_NA ','SOA_A1 ', & + 'SOA_LV ','SOA_SV ','monoterp ','isoprene ','H2O ' /) + + adv_mass(: 30) = (/ 64.064800_r8, 98.078400_r8, 62.132400_r8, 34.013600_r8, 98.078400_r8, & + 98.078400_r8, 115.107340_r8, 98.078400_r8, 98.078400_r8, 12.011000_r8, & + 12.011000_r8, 12.011000_r8, 12.011000_r8, 12.011000_r8, 12.011000_r8, & + 12.011000_r8, 12.011000_r8, 12.011000_r8, 135.064039_r8, 135.064039_r8, & + 58.442468_r8, 58.442468_r8, 58.442468_r8, 168.227200_r8, 168.227200_r8, & + 168.227200_r8, 168.227200_r8, 136.228400_r8, 68.114200_r8, 18.014200_r8 /) + + crb_mass(: 30) = (/ 0.000000_r8, 0.000000_r8, 24.022000_r8, 0.000000_r8, 0.000000_r8, & + 0.000000_r8, 0.000000_r8, 0.000000_r8, 0.000000_r8, 12.011000_r8, & + 12.011000_r8, 12.011000_r8, 12.011000_r8, 12.011000_r8, 12.011000_r8, & + 12.011000_r8, 12.011000_r8, 12.011000_r8, 0.000000_r8, 0.000000_r8, & + 0.000000_r8, 0.000000_r8, 0.000000_r8, 120.110000_r8, 120.110000_r8, & + 120.110000_r8, 120.110000_r8, 120.110000_r8, 60.055000_r8, 0.000000_r8 /) + + fix_mass(: 7) = (/ 0.00000000_r8, 28.0134800_r8, 31.9988000_r8, 47.9982000_r8, 17.0068000_r8, & + 62.0049400_r8, 33.0062000_r8 /) + + clsmap(: 30,4) = (/ 3, 1, 4, 5, 6, 7, 8, 9, 10, 11, & + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, & + 22, 23, 2, 24, 25, 26, 27, 28, 29, 30 /) + + permute(: 30,4) = (/ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, & + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, & + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 /) + + diag_map(: 30) = (/ 1, 5, 7, 9, 10, 11, 12, 13, 14, 15, & + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, & + 26, 27, 28, 29, 30, 31, 32, 35, 37, 38 /) + + extfrc_lst(: 7) = (/ 'SO2 ','BC_NI ','BC_AX ','BC_N ','OM_NI ', & + 'SO4_PR ','H2O ' /) + + frc_from_dataset(: 7) = (/ .true., .true., .true., .true., .true., & + .true., .true. /) + + inv_lst(: 7) = (/ 'M ', 'N2 ', 'O2 ', 'O3 ', 'OH ', & + 'NO3 ', 'HO2 ' /) + + if( allocated( rxt_tag_lst ) ) then + deallocate( rxt_tag_lst ) + end if + allocate( rxt_tag_lst(rxt_tag_cnt),stat=ios ) + if( ios /= 0 ) then + write(iulog,*) 'set_sim_dat: failed to allocate rxt_tag_lst; error = ',ios + call endrun + end if + if( allocated( rxt_tag_map ) ) then + deallocate( rxt_tag_map ) + end if + allocate( rxt_tag_map(rxt_tag_cnt),stat=ios ) + if( ios /= 0 ) then + write(iulog,*) 'set_sim_dat: failed to allocate rxt_tag_map; error = ',ios + call endrun + end if + rxt_tag_lst( 1: 3) = (/ 'jh2o2 ', 'usr_HO2_HO2 ', & + 'usr_DMS_OH ' /) + rxt_tag_map(:rxt_tag_cnt) = (/ 1, 2, 7 /) + if( allocated( pht_alias_lst ) ) then + deallocate( pht_alias_lst ) + end if + allocate( pht_alias_lst(phtcnt,2),stat=ios ) + if( ios /= 0 ) then + write(iulog,*) 'set_sim_dat: failed to allocate pht_alias_lst; error = ',ios + call endrun + end if + if( allocated( pht_alias_mult ) ) then + deallocate( pht_alias_mult ) + end if + allocate( pht_alias_mult(phtcnt,2),stat=ios ) + if( ios /= 0 ) then + write(iulog,*) 'set_sim_dat: failed to allocate pht_alias_mult; error = ',ios + call endrun + end if + pht_alias_lst(:,1) = (/ ' ' /) + pht_alias_lst(:,2) = (/ ' ' /) + pht_alias_mult(:,1) = (/ 1._r8 /) + pht_alias_mult(:,2) = (/ 1._r8 /) + allocate( num_rnts(rxntot-phtcnt),stat=ios ) + if( ios /= 0 ) then + write(iulog,*) 'set_sim_dat: failed to allocate num_rnts; error = ',ios + call endrun + end if + num_rnts(:) = (/ 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, & + 2, 2 /) + + end subroutine set_sim_dat + + end module mo_sim_dat From 9edda72781fce03a902f5897b61523f2224c0bce Mon Sep 17 00:00:00 2001 From: Steve Goldhaber Date: Tue, 5 Sep 2023 21:57:08 +0200 Subject: [PATCH 02/24] Compile Oslo Aero from source subdirectories --- bld/configure | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bld/configure b/bld/configure index ab49ec2fd9..0a634f12ff 100755 --- a/bld/configure +++ b/bld/configure @@ -2137,7 +2137,9 @@ sub write_filepath print $fh "$chem_src_dir\n"; } if ($chem =~/_oslo/) { - print $fh "$camsrcdir/cam/src/chemistry/oslo_aero\n"; + print $fh "$camsrcdir/cam/src/chemistry/oslo_aero/object\n"; + print $fh "$camsrcdir/cam/src/chemistry/oslo_aero/src\n"; + print $fh "$camsrcdir/cam/src/chemistry/oslo_aero/cam_intr\n"; } elsif ($chem =~ /_mam/) { print $fh "$camsrcdir/src/chemistry/modal_aero\n"; } else { From 466333f446969cf24c60cebd0500c20d36b9ade8 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Fri, 8 Sep 2023 16:34:58 +0200 Subject: [PATCH 03/24] fixes of run time errors --- bld/configure | 10 +- src/chemistry/aerosol/mo_setsox.F90 | 20 +- src/chemistry/mozart/chemistry.F90 | 36 ++- src/chemistry/mozart/mo_chm_diags.F90 | 187 ++++++++++++++- src/chemistry/mozart/mo_drydep.F90 | 5 +- src/chemistry/mozart/mo_gas_phase_chemdr.F90 | 70 +++++- src/chemistry/mozart/mo_neu_wetdep.F90 | 21 +- src/chemistry/mozart/mo_setaer.F90 | 6 +- src/chemistry/mozart/mo_srf_emissions.F90 | 18 +- src/chemistry/mozart/mo_usrrxt.F90 | 12 +- src/control/runtime_opts.F90 | 14 ++ src/physics/cam/vertical_diffusion.F90 | 26 ++- src/physics/cam/zm_microphysics.F90 | 2 + src/physics/rrtmg/radiation.F90 | 230 ++++++++++++++++++- src/physics/rrtmg/radlw.F90 | 4 + src/physics/rrtmg/radsw.F90 | 21 +- 16 files changed, 639 insertions(+), 43 deletions(-) diff --git a/bld/configure b/bld/configure index 0a634f12ff..f5680006fa 100755 --- a/bld/configure +++ b/bld/configure @@ -64,7 +64,7 @@ OPTIONS test_tracers, test_tracers2]. Default: none. -chem Build CAM with specified prognostic chemistry package - [ none | ghg_mam4 | terminator | trop_mam3 | trop_mam4 | trop_mam7 trop_mam_oslo | trop_mozart | trop_strat_mam4_ts2 | + [ none | ghg_mam4 | terminator | trop_mam3 | trop_mam4 | trop_mam7 | trop_mam_oslo | trop_mozart | trop_strat_mam4_ts2 | trop_strat_mam4_vbs | trop_strat_mam4_vbsext | trop_strat_mam5_ts2 | trop_strat_mam5_vbs | trop_strat_mam5_vbsext | waccm_ma | waccm_mad | waccm_ma_sulfur | waccm_sc | waccm_sc_mam4 | waccm_mad_mam4 | waccm_ma_mam4 | waccm_tsmlt_mam4 | waccm_tsmlt_mam4_vbsext | waccm_mad_mam5 | @@ -1415,6 +1415,8 @@ if ($chem_pkg =~ '_mam3') { $chem_cppdefs = ' -DMODAL_AERO -DMODAL_AERO_5MODE '; } elsif ($chem_pkg =~ '_mam7') { $chem_cppdefs = ' -DMODAL_AERO -DMODAL_AERO_7MODE '; +} elsif ($chem_pkg =~ '_oslo') { + $chem_cppdefs = ' -DOSLO_AERO'; } # CARMA sectional microphysics @@ -2137,9 +2139,9 @@ sub write_filepath print $fh "$chem_src_dir\n"; } if ($chem =~/_oslo/) { - print $fh "$camsrcdir/cam/src/chemistry/oslo_aero/object\n"; - print $fh "$camsrcdir/cam/src/chemistry/oslo_aero/src\n"; - print $fh "$camsrcdir/cam/src/chemistry/oslo_aero/cam_intr\n"; + # print $fh "$camsrcdir/src/chemistry/oslo_aero/object\n"; BUG: this does not compile + print $fh "$camsrcdir/src/chemistry/oslo_aero/src\n"; + print $fh "$camsrcdir/src/chemistry/oslo_aero/cam_intr\n"; } elsif ($chem =~ /_mam/) { print $fh "$camsrcdir/src/chemistry/modal_aero\n"; } else { diff --git a/src/chemistry/aerosol/mo_setsox.F90 b/src/chemistry/aerosol/mo_setsox.F90 index b994e32dd2..9543900de0 100644 --- a/src/chemistry/aerosol/mo_setsox.F90 +++ b/src/chemistry/aerosol/mo_setsox.F90 @@ -33,15 +33,21 @@ subroutine sox_inti use mo_chem_utls, only : get_spc_ndx, get_inv_ndx use spmd_utils, only : masterproc use phys_control, only : phys_getopts +#ifdef OSLO_AERO + use oslo_aero_sox_cldaero, only : sox_cldaero_init +#else use sox_cldaero_mod, only : sox_cldaero_init +#endif implicit none - - call phys_getopts( & - prog_modal_aero_out=modal_aerosols ) - +#ifdef OSLO_AERO + modal_aerosols = .true. + cloud_borne = .true. +#else + call phys_getopts(prog_modal_aero_out=modal_aerosols ) cloud_borne = modal_aerosols +#endif !----------------------------------------------------------------- ! ... get species indicies @@ -175,9 +181,13 @@ subroutine SETSOX( & use chem_mods, only : adv_mass use physconst, only : mwdry, gravit use mo_constants, only : pi +#ifdef OSLO_AERO + use oslo_aero_sox_cldaero, only : sox_cldaero_update, sox_cldaero_create_obj, sox_cldaero_destroy_obj + use oslo_aero_sox_cldaero, only : cldaero_conc_t +#else use sox_cldaero_mod, only : sox_cldaero_update, sox_cldaero_create_obj, sox_cldaero_destroy_obj use cldaero_mod, only : cldaero_conc_t - +#endif ! implicit none ! diff --git a/src/chemistry/mozart/chemistry.F90 b/src/chemistry/mozart/chemistry.F90 index ff42e870d9..b2f011549b 100644 --- a/src/chemistry/mozart/chemistry.F90 +++ b/src/chemistry/mozart/chemistry.F90 @@ -163,7 +163,11 @@ subroutine chem_register use cfc11star, only : register_cfc11star use mo_photo, only : photo_register use mo_aurora, only : aurora_register +#ifdef OSLO_AERO + use oslo_aero_model, only : aero_model_register +#else use aero_model, only : aero_model_register +#endif use physics_buffer, only : pbuf_add_field, dtype_r8 use upper_bc, only : ubc_fixed_conc @@ -333,8 +337,13 @@ subroutine chem_readnl(nlfile) use tracer_cnst, only: tracer_cnst_defaultopts, tracer_cnst_setopts use tracer_srcs, only: tracer_srcs_defaultopts, tracer_srcs_setopts +#ifdef OSLO_AERO + use oslo_aero_model, only: aero_model_readnl + use oslo_aero_dust, only: oslo_aero_dust_readnl +#else use aero_model, only: aero_model_readnl use dust_model, only: dust_readnl +#endif use gas_wetdep_opts, only: gas_wetdep_readnl use mo_drydep, only: drydep_srf_file use mo_sulf, only: sulf_readnl @@ -541,7 +550,11 @@ subroutine chem_readnl(nlfile) tracer_srcs_fixed_tod_in = tracer_srcs_fixed_tod ) call aero_model_readnl(nlfile) - call dust_readnl(nlfile) +#ifdef OSLO_AERO + call oslo_aero_dust_readnl(nlfile) +#else + call dust_readnl(nlfile) +#endif ! call gas_wetdep_readnl(nlfile) call gcr_ionization_readnl(nlfile) @@ -636,7 +649,11 @@ subroutine chem_init(phys_state, pbuf2d) use infnan, only : nan, assignment(=) use mo_chem_utls, only : get_spc_ndx use cam_abortutils, only : endrun +#ifdef OSLO_AERO + use oslo_aero_model, only : aero_model_init +#else use aero_model, only : aero_model_init +#endif use mo_setsox, only : sox_inti use constituents, only : sflxnam use fire_emissions, only : fire_emissions_init @@ -828,8 +845,13 @@ subroutine chem_init(phys_state, pbuf2d) contains pure logical function aero_has_emis(spcname) - use seasalt_model, only: seasalt_names +#ifdef OSLO_AERO + use oslo_aero_seasalt, only: seasalt_names + use oslo_aero_dust, only: dust_names +#else + use seasalt_model, only : seasalt_names use dust_model, only: dust_names +#endif character(len=*),intent(in) :: spcname @@ -843,7 +865,11 @@ end subroutine chem_init !================================================================================ subroutine chem_emissions( state, cam_in, pbuf ) use physics_buffer, only: physics_buffer_desc +#ifdef OSLO_AERO + use oslo_aero_model, only: aero_model_emissions +#else use aero_model, only: aero_model_emissions +#endif use camsrfexch, only: cam_in_t use constituents, only: sflxnam use cam_history, only: outfld @@ -924,8 +950,12 @@ subroutine chem_emissions( state, cam_in, pbuf ) ! fire surface emissions if not elevated forcing call fire_emissions_srf( lchnk, ncol, cam_in%fireflx, cam_in%cflx ) - ! air-sea exchange of trace gases +#ifndef OSLO_AERO + ! TODO oslo_aero: should this be added to OSLO_AERO - there was + ! not a pre-existing ocean salinity file capability air-sea + ! exchange of trace gases call ocean_emis_getflux(lchnk, ncol, state, cam_in%u10, cam_in%sst, cam_in%ocnfrac, cam_in%icefrac, cam_in%cflx) +#endif end subroutine chem_emissions diff --git a/src/chemistry/mozart/mo_chm_diags.F90 b/src/chemistry/mozart/mo_chm_diags.F90 index 5650403fee..25e2aae6e4 100644 --- a/src/chemistry/mozart/mo_chm_diags.F90 +++ b/src/chemistry/mozart/mo_chm_diags.F90 @@ -11,6 +11,13 @@ module mo_chm_diags use mo_jeuv, only : neuv use gas_wetdep_opts,only : gas_wetdep_method use mo_drydep, only : has_drydep +#ifdef OSLO_AERO + use phys_grid, only : pcols + use physics_buffer, only : pbuf_get_field, pbuf_get_index, physics_buffer_desc + use constituents, only : cnst_get_ind + use oslo_aero_share, only : getCloudTracerIndexDirect, getCloudTracerName, aerosolType, isAerosol + use oslo_aero_params +#endif implicit none private @@ -51,7 +58,7 @@ module mo_chm_diags character(len=fieldname_len) :: depflx_name(gas_pcnst) character(len=fieldname_len) :: wetdep_name(gas_pcnst) character(len=fieldname_len) :: wtrate_name(gas_pcnst) - + character(len=fieldname_len) :: wetdep_name_area(gas_pcnst) ! OSLO_AERO real(r8), parameter :: N_molwgt = 14.00674_r8 real(r8), parameter :: S_molwgt = 32.066_r8 @@ -104,7 +111,8 @@ subroutine chm_diags_inti logical :: history_chemspecies_srf ! output the chemistry constituents species in the surface layer logical :: history_dust integer :: bulkaero_species(20) - + integer :: cloudTracerIndex ! OSLO_AERO + character(len=20) :: cloudTracerName ! OSLO_AERO !----------------------------------------------------------------------- call phys_getopts( history_aerosol_out = history_aerosol, & @@ -423,12 +431,40 @@ subroutine chm_diags_inti call addfld( wtrate_name(m), (/ 'lev' /), 'A', '/s', spc_name//' wet deposition rate' ) endif +#ifdef OSLO_AERO + wetdep_name_area(m)='WD_A_'//trim(spc_name) + call addfld( wetdep_name_area(m), horiz_only, 'A', 'kg/m2/s ', spc_name//' wet deposition' ) + + !Needed for budget term of gases! Aerosols have their own budget terms + if(n.gt.0) then + if(.NOT. isAerosol(n))then + if(history_chemistry)then + call add_default( wetdep_name_area(m), 1, ' ') + end if + endif + end if +#endif + if (spc_name(1:3) == 'num') then unit_basename = ' 1' else unit_basename = 'kg' endif +#ifdef OSLO_AERO + if (n.gt.0) then + if ( any( aer_species == m ) .or. isAerosol(n) ) then + call addfld( spc_name, (/ 'lev' /), 'A', unit_basename//'/kg ', trim(attr)//' concentration') + call addfld( trim(spc_name)//'_SRF', horiz_only, 'A', unit_basename//'/kg', trim(attr)//" in bottom layer") + else + call addfld( spc_name, (/ 'lev' /), 'A', 'mol/mol', trim(attr)//' concentration') + call addfld( trim(spc_name)//'_SRF', horiz_only, 'A', 'mol/mol', trim(attr)//" in bottom layer") + endif + else + call addfld( spc_name, (/ 'lev' /), 'A', 'mol/mol', trim(attr)//' concentration') + call addfld( trim(spc_name)//'_SRF', horiz_only, 'A', 'mol/mol', trim(attr)//" in bottom layer") + endif +#else if ( any( aer_species == m ) ) then call addfld( spc_name, (/ 'lev' /), 'A', unit_basename//'/kg ', trim(attr)//' concentration') call addfld( trim(spc_name)//'_SRF', horiz_only, 'A', unit_basename//'/kg', trim(attr)//" in bottom layer") @@ -436,7 +472,7 @@ subroutine chm_diags_inti call addfld( spc_name, (/ 'lev' /), 'A', 'mol/mol', trim(attr)//' concentration') call addfld( trim(spc_name)//'_SRF', horiz_only, 'A', 'mol/mol', trim(attr)//" in bottom layer") endif - +#endif if ((m /= id_cly) .and. (m /= id_bry)) then if (history_aerosol.or.history_chemistry) then call add_default( spc_name, 1, ' ' ) @@ -477,13 +513,63 @@ subroutine chm_diags_inti if (m==id_cfc12 ) call add_default( spc_name, 1, ' ') endif +#ifdef OSLO_AERO + call add_default( spc_name, 1, ' ' ) + + ! output 3d-field of aersol tracer in cloud water + if (n > 0) then + cloudTracerIndex = getCloudTracerIndexDirect(n) + if(cloudTracerIndex > 0)then + cloudTracerName(1:len(CloudTracerName))=" " + cloudTracerName = getCloudTracerName(n) + call addfld( trim(cloudTracerName), (/'lev'/), 'A','kg/kg', & + trim(cloudTracerName)//' in cloud water') + call add_default( trim(cloudTracerName), 1, ' ' ) + + !Add column burden of cloud tracers + call addfld('cb_'//trim(cloudTracerName),horiz_only, 'A', 'kg/m2', & + 'cb_'//trim(cloudTracerName)//' column in cloud water') + call add_default('cb_'//trim(cloudTracerName),1,' ') + endif + !..and column burden in clean air + call addfld('cb_'//trim(spc_name),horiz_only, 'A', 'kg/m2', & + 'cb_'//trim(spc_name)//' in column') + call add_default('cb_'//trim(spc_name),1,' ' ) + + if (history_aerosol) then + if (cloudTracerIndex > 0) then + !Output budget-terms for cloud borne aerosols + call add_default (trim(cloudTracerName)//'GVF' , 1, ' ') + call add_default (trim(cloudTracerName)//'SFWET' , 1, ' ') + call add_default (trim(cloudTracerName)//'TBF' , 1, ' ') + call add_default (trim(cloudTracerName)//'DDF' , 1, ' ') + call add_default (trim(cloudTracerName)//'SFSBS' , 1, ' ') + call add_default (trim(cloudTracerName)//'SFSIC' , 1, ' ') + call add_default (trim(cloudTracerName)//'SFSBC' , 1, ' ') + call add_default (trim(cloudTracerName)//'SFSIS' , 1, ' ') + endif + endif + end if +#else + if (history_dust .and. (index(spc_name,'dst_') > 0)) call add_default( spc_name, 1, ' ') +#endif enddo call addfld( 'MASS', (/ 'lev' /), 'A', 'kg', 'mass of grid box' ) call addfld( 'AREA', horiz_only, 'A', 'm2', 'area of grid box' ) - +#ifdef OSLO_AERO + do n=1,N_AEROSOL_TYPES + call addfld('cb_'//trim(aerosol_type_name(n)),horiz_only, 'A', 'kg/m2',& + 'cb_'//trim(aerosol_type_name(n))//' column of aerosol type') + call add_default('cb_'//trim(aerosol_type_name(n)), 1, ' ') + + call addfld('mmr_'//trim(aerosol_type_name(n)),(/'lev'/),'A','kg/kg' ,& + 'mmr_'//trim(aerosol_type_name(n))//' mmr of aerosol type') + call add_default('mmr_'//trim(aerosol_type_name(n)), 1, ' ') + end do +#endif call addfld( 'dry_deposition_NOy_as_N', horiz_only, 'I', 'kg/m2/s', 'NOy dry deposition flux ' ) call addfld( 'DF_SOX', horiz_only, 'I', 'kg/m2/s', 'SOx dry deposition flux ' ) call addfld( 'dry_deposition_NHx_as_N', horiz_only, 'I', 'kg/m2/s', 'NHx dry deposition flux ' ) @@ -506,8 +592,13 @@ subroutine chm_diags_inti end subroutine chm_diags_inti +#ifdef OSLO_AERO + subroutine chm_diags( lchnk, ncol, vmr, mmr, rxt_rates, invariants, depvel, depflx, mmr_tend, pdel, pmid, ltrop, & + wetdepflx, nhx_nitrogen_flx, noy_nitrogen_flx, pbuf) +#else subroutine chm_diags( lchnk, ncol, vmr, mmr, rxt_rates, invariants, depvel, depflx, mmr_tend, pdel, pmid, ltrop, & wetdepflx, nhx_nitrogen_flx, noy_nitrogen_flx ) +#endif !-------------------------------------------------------------------- ! ... utility routine to output chemistry diagnostic variables !-------------------------------------------------------------------- @@ -538,11 +629,24 @@ subroutine chm_diags( lchnk, ncol, vmr, mmr, rxt_rates, invariants, depvel, depf real(r8), intent(in) :: wetdepflx(ncol, gas_pcnst) real(r8), intent(out) :: nhx_nitrogen_flx(ncol) ! kgN/m2/sec real(r8), intent(out) :: noy_nitrogen_flx(ncol) ! kgN/m2/sec +#ifdef OSLO_AERO + type(physics_buffer_desc), pointer :: pbuf(:) +#endif !-------------------------------------------------------------------- ! ... local variables !-------------------------------------------------------------------- - integer :: i, k, m +#ifdef OSLO_AERO + real(r8), pointer :: cloudTracerField(:,:) + integer :: cloudTracerIndex + character(len=20) :: cloudTracerName + real(r8) :: mass_tmp(pcols,pver) + real(r8) :: cb(pcols) + real(r8) :: cb_aerosol_type(pcols,N_AEROSOL_TYPES) !column burden aerosol types + real(r8) :: mmr_aerosol_type(pcols,pver,N_AEROSOL_TYPES) !concentration aerosol types + character(len=16) :: spc_name +#endif + integer :: i, k, m, n real(r8) :: wrk(ncol,pver) ! real(r8) :: tmp(ncol,pver) ! real(r8) :: m(ncol,pver) @@ -593,6 +697,11 @@ subroutine chm_diags( lchnk, ncol, vmr, mmr, rxt_rates, invariants, depvel, depf call outfld( 'AREA', area(:ncol), ncol, lchnk ) call outfld( 'MASS', mass(:ncol,:), ncol, lchnk ) +#ifdef OSLO_AERO + cb_aerosol_type(:,:) = 0.0_r8 + mmr_aerosol_type(:,:,:) = 0.0_r8 +#endif + do m = 1,gas_pcnst !...FOY (counting Fluorines, not chlorines or bromines) @@ -675,6 +784,49 @@ subroutine chm_diags( lchnk, ncol, vmr, mmr, rxt_rates, invariants, depvel, depf vmr_hox(:ncol,:) = vmr_hox(:ncol,:) + wgt * vmr(:ncol,:,m) endif +#ifdef OSLO_AERO + spc_name = trim(solsym(m)) + call cnst_get_ind(spc_name, n, abort=.false.) + + if (n.gt.0) then + if ( any( aer_species == m ) .or. isAerosol(n) ) then + call outfld( solsym(m), mmr(:ncol,:,m), ncol ,lchnk ) + call outfld( trim(solsym(m))//'_SRF', mmr(:ncol,pver,m), ncol ,lchnk ) + else + call outfld( solsym(m), vmr(:ncol,:,m), ncol ,lchnk ) + call outfld( trim(solsym(m))//'_SRF', vmr(:ncol,pver,m), ncol ,lchnk ) + endif + else + call outfld( solsym(m), vmr(:ncol,:,m), ncol ,lchnk ) + call outfld( trim(solsym(m))//'_SRF', vmr(:ncol,pver,m), ncol ,lchnk ) + end if + + if (n > 0) then + cloudTracerIndex = getCloudTracerIndexDirect(n) + if(cloudTracerIndex > 0)then + cloudTracerName = getCloudTracerName(n) + call pbuf_get_field(pbuf, cloudTracerIndex, cloudTracerField ) + call outfld ( trim(cloudTracerName), cloudTracerField, pcols, lchnk) + + ! Treat column burden (cloud tracer) + mass_tmp(:ncol,:) = cloudTracerField(:ncol,:) *pdel(:ncol,:) * rgrav + cb(:ncol) = sum(mass_tmp(:ncol,:),2) + call outfld(trim('cb_'//trim(cloudTracerName)), cb, pcols, lchnk) + endif + + ! Treat column burden (normal tracer) + mass_tmp(:ncol,:) = mmr(:ncol,:,m) * pdel(:ncol,:) * rgrav + cb(:ncol) = sum(mass_tmp(:ncol,:),2) + call outfld(trim('cb_'//trim(spc_name)), cb, pcols, lchnk) + + !Sum column burden per aerosol type + if (aerosolType(n) > 0) then + cb_aerosol_type(:ncol,aerosolType(n)) = cb_aerosol_type(:ncol,aerosolType(n)) + cb(:ncol) + !Total mass mixing ratio of aerosol type + mmr_aerosol_type(:ncol,:,aerosolType(n)) = mmr_aerosol_type(:ncol,:,aerosolType(n)) + mmr(:ncol,:,m) + endif + end if !Check if this is a chemistry tracer +#else if ( any( aer_species == m ) ) then call outfld( solsym(m), mmr(:ncol,:,m), ncol ,lchnk ) call outfld( trim(solsym(m))//'_SRF', mmr(:ncol,pver,m), ncol ,lchnk ) @@ -682,6 +834,7 @@ subroutine chm_diags( lchnk, ncol, vmr, mmr, rxt_rates, invariants, depvel, depf call outfld( solsym(m), vmr(:ncol,:,m), ncol ,lchnk ) call outfld( trim(solsym(m))//'_SRF', vmr(:ncol,pver,m), ncol ,lchnk ) endif +#endif if (has_drydep(solsym(m))) then call outfld( depvel_name(m), depvel(:ncol,m), ncol ,lchnk ) @@ -749,8 +902,12 @@ subroutine chm_diags( lchnk, ncol, vmr, mmr, rxt_rates, invariants, depvel, depf end if ! enddo - - +#ifdef OSLO_AERO + do n=1,N_AEROSOL_TYPES + call outfld("mmr_"//trim(aerosol_type_name(n)), mmr_aerosol_type(:ncol,:,n), ncol,lchnk) + call outfld("cb_"//trim(aerosol_type_name(n)) , cb_aerosol_type(:ncol,n) , ncol,lchnk) + enddo +#endif call outfld( 'NOX', vmr_nox (:ncol,:), ncol, lchnk ) call outfld( 'NOY', vmr_noy (:ncol,:), ncol, lchnk ) call outfld( 'HOX', vmr_hox (:ncol,:), ncol, lchnk ) @@ -880,7 +1037,11 @@ end subroutine chm_diags subroutine het_diags( het_rates, mmr, pdel, lchnk, ncol ) use cam_history, only : outfld +#ifdef OSLO_AERO + use phys_grid, only : get_wght_all_p, get_area_all_p +#else use phys_grid, only : get_wght_all_p +#endif integer, intent(in) :: lchnk integer, intent(in) :: ncol @@ -889,6 +1050,9 @@ subroutine het_diags( het_rates, mmr, pdel, lchnk, ncol ) real(r8), intent(in) :: pdel(ncol,pver) real(r8), dimension(ncol) :: noy_wk, sox_wk, nhx_wk, wrk_wd +#ifdef OSLO_AERO + real(r8), dimension(ncol) :: area +#endif integer :: m, k real(r8) :: wght(ncol) ! @@ -898,6 +1062,10 @@ subroutine het_diags( het_rates, mmr, pdel, lchnk, ncol ) sox_wk(:) = 0._r8 nhx_wk(:) = 0._r8 +#ifdef OSLO_AERO + call get_area_all_p(lchnk, ncol, area) + area = area * rearth**2 +#endif call get_wght_all_p(lchnk, ncol, wght) do m = 1,gas_pcnst @@ -912,7 +1080,10 @@ subroutine het_diags( het_rates, mmr, pdel, lchnk, ncol ) wrk_wd(:ncol) = wrk_wd(:ncol) * rgrav * wght(:ncol) * rearth**2 ! if (gas_wetdep_method=='MOZ') then - call outfld( wetdep_name(m), wrk_wd(:ncol), ncol, lchnk ) + call outfld( wetdep_name(m), wrk_wd(:ncol), ncol, lchnk ) +#ifdef OSLO_AERO + call outfld( wetdep_name_area(m), wrk_wd(:ncol)/area(:ncol) ,ncol, lchnk ) +#endif call outfld( wtrate_name(m), het_rates(:ncol,:,m), ncol, lchnk ) if ( any(noy_species == m ) ) then diff --git a/src/chemistry/mozart/mo_drydep.F90 b/src/chemistry/mozart/mo_drydep.F90 index a44db8416e..68a7e6ec07 100644 --- a/src/chemistry/mozart/mo_drydep.F90 +++ b/src/chemistry/mozart/mo_drydep.F90 @@ -322,8 +322,11 @@ subroutine dvel_inti_xactive( depvel_lnd_file ) logical :: prog_modal_aero ! determine if modal aerosols are active so that fraction_landuse array is initialized for modal aerosal dry dep +#ifdef OSLO_AERO + prog_modal_aero = .true. +#else call phys_getopts(prog_modal_aero_out=prog_modal_aero) - +#endif call dvel_inti_fromlnd() if( masterproc ) then diff --git a/src/chemistry/mozart/mo_gas_phase_chemdr.F90 b/src/chemistry/mozart/mo_gas_phase_chemdr.F90 index 68657d0739..76c864d542 100644 --- a/src/chemistry/mozart/mo_gas_phase_chemdr.F90 +++ b/src/chemistry/mozart/mo_gas_phase_chemdr.F90 @@ -25,6 +25,10 @@ module mo_gas_phase_chemdr integer :: het1_ndx integer :: ndx_cldfr, ndx_cmfdqr, ndx_nevapr, ndx_cldtop, ndx_prain integer :: ndx_h2so4 +#ifdef OSLO_AERO + logical :: inv_o3, inv_oh, inv_no3, inv_ho2 + integer :: id_o3, id_oh, id_no3, id_ho2 +#endif ! ! CCMI ! @@ -56,7 +60,11 @@ module mo_gas_phase_chemdr subroutine gas_phase_chemdr_inti() +#ifdef OSLO_AERO + use mo_chem_utls, only : get_spc_ndx, get_extfrc_ndx, get_rxt_ndx, get_inv_ndx +#else use mo_chem_utls, only : get_spc_ndx, get_extfrc_ndx, get_rxt_ndx, get_inv_ndx +#endif use cam_history, only : addfld,add_default,horiz_only use mo_chm_diags, only : chm_diags_inti use constituents, only : cnst_get_ind @@ -75,6 +83,16 @@ subroutine gas_phase_chemdr_inti() call phys_getopts( convproc_do_aer_out = convproc_do_aer, history_cesm_forcing_out=history_cesm_forcing ) +#ifdef OSLO_AERO + inv_o3 = get_inv_ndx('O3') > 0 + inv_oh = get_inv_ndx('OH') > 0 + inv_no3 = get_inv_ndx('NO3') > 0 + inv_ho2 = get_inv_ndx('HO2') > 0 + if (inv_o3) id_o3 = get_inv_ndx('O3') + if (inv_oh) id_oh = get_inv_ndx('OH') + if (inv_no3) id_no3 = get_inv_ndx('NO3') + if (inv_ho2) id_ho2 = get_inv_ndx('HO2') +#endif ndx_h2so4 = get_spc_ndx('H2SO4') ! ! CCMI @@ -193,11 +211,26 @@ subroutine gas_phase_chemdr_inti() call addfld( 'HCL_GAS', (/ 'lev' /), 'I', 'mol/mol', 'gas-phase hcl' ) call addfld( 'HCL_STS', (/ 'lev' /), 'I', 'mol/mol', 'STS condensed HCL' ) +#ifdef OSLO_AERO + ! Adding extra fields for oxi-output (before and after diurnal variations.) + call addfld ('OH_bef ', (/ 'lev' /), 'A','unit', 'OH invariants before adding diurnal variations' ) + call addfld ('HO2_bef ', (/ 'lev' /), 'A','unit', 'HO2 invariants before adding diurnal variations' ) + call addfld ('NO3_bef ', (/ 'lev' /), 'A','unit', 'NO3 invariants before adding diurnal variations' ) + call addfld ('OH_aft ', (/ 'lev' /), 'A','unit', 'OH invariants after adding diurnal variations' ) + call addfld ('HO2_aft ', (/ 'lev' /), 'A','unit', 'HO2 invariants after adding diurnal variations' ) + call addfld ('NO3_aft ', (/ 'lev' /), 'A','unit', 'NO3 invariants after adding diurnal variations' ) + + call add_default ('OH_bef ', 1, ' ') + call add_default ('HO2_bef ', 1, ' ') + call add_default ('NO3_bef ', 1, ' ') + call add_default ('OH_aft ', 1, ' ') + call add_default ('HO2_aft ', 1, ' ') + call add_default ('NO3_aft ', 1, ' ') +#endif if (het1_ndx>0) then call addfld( 'het1_total', (/ 'lev' /), 'I', '/s', 'total N2O5 + H2O het rate constant' ) endif call addfld( 'SZA', horiz_only, 'I', 'degrees', 'solar zenith angle' ) - call chm_diags_inti() call rate_diags_init() @@ -309,14 +342,17 @@ subroutine gas_phase_chemdr(lchnk, ncol, imozart, q, & use rate_diags, only : rate_diags_calc, rate_diags_o3s_loss use mo_mass_xforms, only : mmr2vmr, vmr2mmr, h2o_to_vmr, mmr2vmri use orbit, only : zenith - ! ! for aqueous chemistry and aerosol growth ! - use aero_model, only : aero_model_gasaerexch - - use aero_model, only : aero_model_strat_surfarea - +#ifdef OSLO_AERO + use oslo_aero_diurnal_var, only : set_diurnal_invariants + use oslo_aero_model, only : aero_model_gasaerexch + use oslo_aero_model, only : aero_model_strat_surfarea +#else + use aero_model, only : aero_model_gasaerexch + use aero_model, only : aero_model_strat_surfarea +#endif !----------------------------------------------------------------------- ! ... Dummy arguments !----------------------------------------------------------------------- @@ -620,6 +656,21 @@ subroutine gas_phase_chemdr(lchnk, ncol, imozart, q, & !----------------------------------------------------------------------- call setinv( invariants, tfld, h2ovmr, vmr, pmid, ncol, lchnk, pbuf ) +#ifdef OSLO_AERO + !----------------------------------------------------------------------- + ! ... Set the "day/night cycle for prescribed oxidants" + !----------------------------------------------------------------------- + call outfld('OH_bef', invariants(:,:,id_oh), ncol, lchnk) + call outfld('HO2_bef', invariants(:,:,id_ho2), ncol, lchnk) + call outfld('NO3_bef', invariants(:,:,id_no3), ncol, lchnk) + if (inv_oh.or.inv_ho2.or.inv_no3) then + call set_diurnal_invariants(invariants,delt,ncol,lchnk,inv_oh,inv_ho2,id_oh,id_ho2,inv_no3,id_no3) + end if + call outfld('OH_aft', invariants(:,:,id_oh), ncol, lchnk) + call outfld('HO2_aft', invariants(:,:,id_ho2), ncol, lchnk) + call outfld('NO3_aft', invariants(:,:,id_no3), ncol, lchnk) +#endif + !----------------------------------------------------------------------- ! ... stratosphere aerosol surface area !----------------------------------------------------------------------- @@ -1097,10 +1148,17 @@ subroutine gas_phase_chemdr(lchnk, ncol, imozart, q, & endif endif +#ifdef OSLO_AERO + call chm_diags( lchnk, ncol, vmr(:ncol,:,:), mmr_new(:ncol,:,:), & + reaction_rates(:ncol,:,:), invariants(:ncol,:,:), depvel(:ncol,:), sflx(:ncol,:), & + mmr_tend(:ncol,:,:), pdel(:ncol,:), pmid(:ncol,:), troplev(:ncol), wetdepflx_diag(:ncol,:), & + nhx_nitrogen_flx(:ncol), noy_nitrogen_flx(:ncol), pbuf ) +#else call chm_diags( lchnk, ncol, vmr(:ncol,:,:), mmr_new(:ncol,:,:), & reaction_rates(:ncol,:,:), invariants(:ncol,:,:), depvel(:ncol,:), sflx(:ncol,:), & mmr_tend(:ncol,:,:), pdel(:ncol,:), pmid(:ncol,:), troplev(:ncol), wetdepflx_diag(:ncol,:), & nhx_nitrogen_flx(:ncol), noy_nitrogen_flx(:ncol) ) +#endif call rate_diags_calc( reaction_rates(:,:,:), vmr(:,:,:), invariants(:,:,indexm), ncol, lchnk ) ! diff --git a/src/chemistry/mozart/mo_neu_wetdep.F90 b/src/chemistry/mozart/mo_neu_wetdep.F90 index c3974b7e37..df8ff28483 100644 --- a/src/chemistry/mozart/mo_neu_wetdep.F90 +++ b/src/chemistry/mozart/mo_neu_wetdep.F90 @@ -14,6 +14,8 @@ module mo_neu_wetdep use cam_abortutils, only : endrun use shr_drydep_mod, only : n_species_table, species_name_table, dheff use gas_wetdep_opts, only : gas_wetdep_method, gas_wetdep_list, gas_wetdep_cnt + use phys_control, only: phys_getopts ! OSLO_AERO + use mo_constants, only: rgrav ! OSLO_AERO ! implicit none ! @@ -260,9 +262,9 @@ subroutine neu_wetdep_tend(lchnk,ncol,mmr,pmid,pdel,zint,tfld,delt, & real(r8) :: e298, dhr real(r8), dimension(ncol) :: dk1s,dk2s,wrk real(r8) :: lats(pcols) - + real(r8) :: wrk_wd(pcols) ! OSLO_AERO + logical :: history_aerosol ! OSLO_AERO real(r8), parameter :: rad2deg = 180._r8/pi - ! ! from cam/src/physics/cam/stratiform.F90 ! @@ -458,6 +460,21 @@ subroutine neu_wetdep_tend(lchnk,ncol,mmr,pmid,pdel,zint,tfld,delt, & ! end do ! +#ifdef OSLO_AERO + !This is output normally in mo_chm_diags, but if neu wetdep, we have to output it here! + call phys_getopts( history_aerosol_out = history_aerosol) + if (history_aerosol) then + do m=1,gas_wetdep_cnt + wrk_wd(:ncol) = 0.0_r8 + do k=1,pver + !Note sign: tendency is negative, so this becomes a positive flux! + wrk_wd(:ncol) = wrk_wd(:ncol) - wd_tend(1:ncol,k,mapping_to_mmr(m))*pdel(:ncol,k)*rgrav !kg/m2/sec + end do + call outfld('WD_A_'//trim(gas_wetdep_list(m)),wrk_wd(:ncol),ncol,lchnk) + end do + end if +#endif + if ( do_diag ) then call outfld('QT_RAIN_HNO3', qt_rain, ncol, lchnk ) call outfld('QT_RIME_HNO3', qt_rime, ncol, lchnk ) diff --git a/src/chemistry/mozart/mo_setaer.F90 b/src/chemistry/mozart/mo_setaer.F90 index 34442f5ae5..bb23050be4 100644 --- a/src/chemistry/mozart/mo_setaer.F90 +++ b/src/chemistry/mozart/mo_setaer.F90 @@ -655,9 +655,13 @@ subroutine setaer( z, airden, rh, aocs1, aocs2, acbs1, acbs2,& use chem_mods, only : adv_mass use mo_constants, only : avogadro use mo_chem_utls, only : get_spc_ndx +#ifdef OSLO_AERO + use oslo_aero_dust, only : dust_names + use oslo_aero_seasalt,only : sslt_names=>seasalt_names +#else use dust_model, only : dust_names use seasalt_model, only : sslt_names=>seasalt_names - +#endif implicit none !----------------------------------------------------------------------------- diff --git a/src/chemistry/mozart/mo_srf_emissions.F90 b/src/chemistry/mozart/mo_srf_emissions.F90 index 80afe7f474..7dd439cd39 100644 --- a/src/chemistry/mozart/mo_srf_emissions.F90 +++ b/src/chemistry/mozart/mo_srf_emissions.F90 @@ -10,6 +10,9 @@ module mo_srf_emissions use ioFileMod, only : getfil use cam_logfile, only : iulog use tracer_data, only : trfld,trfile +#ifdef OSLO_AERO + use oslo_aero_ocean, only: oslo_aero_dms_inq +#endif implicit none @@ -36,6 +39,7 @@ module mo_srf_emissions type(emission), allocatable :: emissions(:) integer :: n_emis_files integer :: c10h16_ndx, isop_ndx + integer :: dms_ndx contains @@ -285,7 +289,9 @@ subroutine srf_emissions_inti( srf_emis_specifier, emis_type_in, emis_cycle_yr, c10h16_ndx = get_spc_ndx('C10H16') isop_ndx = get_spc_ndx('ISOP') - +#ifdef OSLO_AERO + dms_ndx = get_spc_ndx('DMS') +#endif end subroutine srf_emissions_inti subroutine set_srf_emissions_time( pbuf2d, state ) @@ -402,6 +408,16 @@ subroutine set_srf_emissions( lchnk, ncol, sflx ) declination = dec_max * cos((doy_loc - 172._r8)*twopi/dayspy) tod = (calday - doy_loc) + .5_r8 +#ifdef OSLO_AERO + ! Zero DMS emissions if option is not "from file" + ! oslo_aero_dms_inq() Returns "true" if "emissions from file" + if (.not. oslo_aero_dms_inq()) then + if (dms_ndx > 0) then + sflx(:ncol,dms_ndx) = 0.0_r8 + end if + end if +#endif + do i = 1,ncol ! polar_day = .false. diff --git a/src/chemistry/mozart/mo_usrrxt.F90 b/src/chemistry/mozart/mo_usrrxt.F90 index 6c6edddaad..663d25b638 100644 --- a/src/chemistry/mozart/mo_usrrxt.F90 +++ b/src/chemistry/mozart/mo_usrrxt.F90 @@ -3,6 +3,9 @@ module mo_usrrxt use shr_kind_mod, only : r8 => shr_kind_r8 use cam_logfile, only : iulog use ppgrid, only : pver, pcols +#ifdef OSLO_AERO + use oslo_aero_params, only: nmodes_oslo=> nmodes +#endif implicit none @@ -606,7 +609,11 @@ subroutine usrrxt( rxt, temp, tempi, tempe, invariants, h2ovmr, & use mo_setinv, only : inv_o2_ndx=>o2_ndx, inv_h2o_ndx=>h2o_ndx use physics_buffer,only : physics_buffer_desc use carma_flags_mod, only : carma_hetchem_feedback +#ifdef OSLO_AERO + use oslo_aero_model, only : aero_model_surfarea +#else use aero_model, only : aero_model_surfarea +#endif use rad_constituents,only : rad_cnst_get_info implicit none @@ -770,8 +777,11 @@ subroutine usrrxt( rxt, temp, tempi, tempe, invariants, h2ovmr, & ! get info about the modal aerosols ! get ntot_amode +#ifdef OSLO_AERO + ntot_amode = nmodes_oslo +#else call rad_cnst_get_info(0, nmodes=ntot_amode) - +#endif if (ntot_amode>0) then allocate(sfc_array(pcols,pver,ntot_amode), dm_array(pcols,pver,ntot_amode) ) else diff --git a/src/control/runtime_opts.F90 b/src/control/runtime_opts.F90 index 3d4cb35c95..e4f6499e11 100644 --- a/src/control/runtime_opts.F90 +++ b/src/control/runtime_opts.F90 @@ -39,6 +39,9 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon) use air_composition, only: air_composition_readnl use physics_buffer, only: pbuf_readnl use phys_control, only: phys_ctl_readnl +#ifdef OSLO_AERO + use oslo_aero_control, only: oslo_aero_ctl_readnl +#endif use wv_saturation, only: wv_sat_readnl use ref_pres, only: ref_pres_readnl use cam3_aero_data, only: cam3_aero_data_readnl @@ -46,7 +49,11 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon) use dadadj_cam, only: dadadj_readnl use macrop_driver, only: macrop_driver_readnl use microp_driver, only: microp_driver_readnl +#ifdef OSLO_AERO + use oslo_aero_microp, only: oslo_aero_microp_readnl +#else use microp_aero, only: microp_aero_readnl +#endif use subcol, only: subcol_readnl use cloud_fraction, only: cldfrc_readnl use cldfrc2m, only: cldfrc2m_readnl @@ -148,7 +155,11 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon) call dadadj_readnl(nlfilename) call macrop_driver_readnl(nlfilename) call microp_driver_readnl(nlfilename) +#ifdef OSLO_AERO + call oslo_aero_microp_readnl(nlfilename) +#else call microp_aero_readnl(nlfilename) +#endif call clubb_readnl(nlfilename) call subcol_readnl(nlfilename) call cldfrc_readnl(nlfilename) @@ -193,6 +204,9 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon) call rayleigh_friction_readnl(nlfilename) #if ( defined OFFLINE_DYN ) call metdata_readnl(nlfilename) +#endif +#ifdef OSLO_AERO + call oslo_aero_ctl_readnl(nlfilename) #endif call offline_driver_readnl(nlfilename) call analytic_ic_readnl(nlfilename) diff --git a/src/physics/cam/vertical_diffusion.F90 b/src/physics/cam/vertical_diffusion.F90 index dd2cc721f3..af78c84cd1 100644 --- a/src/physics/cam/vertical_diffusion.F90 +++ b/src/physics/cam/vertical_diffusion.F90 @@ -72,6 +72,9 @@ module vertical_diffusion use ref_pres, only : do_molec_diff, nbot_molec use phys_control, only : phys_getopts use time_manager, only : is_first_step +#ifdef OSLO_AERO +use oslo_aero_share, only: getNumberOfAerosolTracers, fillAerosolTracerList +#endif implicit none private @@ -317,16 +320,23 @@ subroutine vertical_diffusion_init(pbuf2d) call cnst_get_ind( 'NUMICE', ixnumice, abort=.false. ) ! prog_modal_aero determines whether prognostic modal aerosols are present in the run. +#ifdef OSLO_AERO + prog_modal_aero = .true. +#else call phys_getopts(prog_modal_aero_out=prog_modal_aero) +#endif if (prog_modal_aero) then - ! Get the constituent indices of the number and mass mixing ratios of the modal ! aerosols. ! ! N.B. - This implementation assumes that the prognostic modal aerosols are ! impacting the climate calculation (i.e., can get info from list 0). ! - +#ifdef OSLO_AERO + pmam_ncnst = getNumberOfAerosolTracers() + allocate(pmam_cnst_idx(pmam_ncnst)) + call fillAerosolTracerList(pmam_cnst_idx) +#else ! First need total number of mam constituents call rad_cnst_get_info(0, nmodes=nmodes) do m = 1, nmodes @@ -347,7 +357,8 @@ subroutine vertical_diffusion_init(pbuf2d) im = im + 1 end do end do - end if +#endif + end if ! end of if prog_model_aero ! Initialize upper boundary condition module @@ -571,6 +582,10 @@ subroutine vertical_diffusion_init(pbuf2d) if( history_budget ) then call add_default( vdiffnam(ixcldliq), history_budget_histfile_num, ' ' ) call add_default( vdiffnam(ixcldice), history_budget_histfile_num, ' ' ) +#ifdef OSLO_AERO + call add_default( vdiffnam(ixnumliq), history_budget_histfile_num, ' ' ) + call add_default( vdiffnam(ixnumice), history_budget_histfile_num, ' ' ) +#endif if( history_budget_histfile_num > 1 ) then call add_default( vdiffnam(1), history_budget_histfile_num, ' ' ) call add_default( 'DTV' , history_budget_histfile_num, ' ' ) @@ -1172,6 +1187,10 @@ subroutine vertical_diffusion_tend( & end if +#ifdef OSLO_AERO + ! Oslo aero adds emissions together with dry deposition - so do not add the explicit + ! surface fluxes to the lowest layer +#else if (prog_modal_aero) then ! Modal aerosol species not diffused, so just add the explicit surface fluxes to the @@ -1183,6 +1202,7 @@ subroutine vertical_diffusion_tend( & q_tmp(:ncol,pver,l) = q_tmp(:ncol,pver,l) + tmp1(:ncol) * cflux(:ncol,l) enddo end if +#endif ! -------------------------------------------------------- ! ! Diagnostics and output writing after applying PBL scheme ! diff --git a/src/physics/cam/zm_microphysics.F90 b/src/physics/cam/zm_microphysics.F90 index b54e1e684e..18f9ab5204 100644 --- a/src/physics/cam/zm_microphysics.F90 +++ b/src/physics/cam/zm_microphysics.F90 @@ -1475,11 +1475,13 @@ subroutine zm_mphy(su, qu, mu, du, eu, cmel, cmei, zf, pm, te, end if +#ifndef OSLO_AERO call activate_aerosol( & wu(i,k), wmix, wdiab, wmin, wmax, & t(i,k), rho(i,k), naermod, aero%nmodes, vaerosol, & hygro, aero_props_obj, fn, fm, & fluxn, fluxm, flux_fullact, in_cloud_in=in_cloud, smax_f=smax_f) +#endif do m = 1, aero%nmodes nlsrc = nlsrc + fn(m)*naermod(m) ! number nucleated diff --git a/src/physics/rrtmg/radiation.F90 b/src/physics/rrtmg/radiation.F90 index 31e33b183d..88da5dc2b0 100644 --- a/src/physics/rrtmg/radiation.F90 +++ b/src/physics/rrtmg/radiation.F90 @@ -42,6 +42,11 @@ module radiation use error_messages, only: handle_err use perf_mod, only: t_startf, t_stopf use cam_logfile, only: iulog +#ifdef OSLO_AERO +use prescribed_volcaero, only: has_prescribed_volcaero +use oslo_aero_optical_params, only: oslo_aero_optical_params_calc +use oslo_aero_params, only: nmodes_oslo => nmodes, nbmodes +#endif implicit none private @@ -144,6 +149,9 @@ module radiation integer :: cldfsnow_idx = 0 integer :: cld_idx = 0 integer :: cldfgrau_idx = 0 +#ifdef OSLO_AERO +integer :: volc_idx = 0 +#endif character(len=4) :: diag(0:N_DIAG) =(/' ','_d1 ','_d2 ','_d3 ','_d4 ','_d5 ','_d6 ','_d7 ','_d8 ','_d9 ','_d10'/) @@ -155,6 +163,13 @@ module radiation ! PIO descriptors (for restarts) type(var_desc_t) :: cospcnt_desc type(var_desc_t) :: nextsw_cday_desc + +#ifdef AEROCOM +logical :: do_aerocom = .true. +#else +logical :: do_aerocom = .false. +#endif + !=============================================================================== contains !=============================================================================== @@ -541,6 +556,11 @@ subroutine radiation_init(pbuf2d) end if end do +#ifdef OSLO_AERO + call addfld('FDSCDRF', (/ 'ilev' /), 'A', 'W/m2', 'Shortwave clear-sky downward flux') + call addfld('FUSCDRF', (/ 'ilev' /), 'A', 'W/m2', 'Shortwave clear-sky upward flux') +#endif + if (scm_crm_mode) then call add_default('FUS ', 1, ' ') call add_default('FUSC ', 1, ' ') @@ -750,6 +770,13 @@ subroutine radiation_tend( & use tropopause, only: tropopause_find, TROP_ALG_HYBSTOB, TROP_ALG_CLIMATE use cospsimulator_intr, only: docosp, cospsimulator_intr_run, cosp_nradsteps +#ifdef OSLO_AERO + use constituents, only: pcnst + use physics_buffer, only: pbuf_get_index + use oslo_aero_control, only: oslo_aero_getopts + use oslo_aero_params + use oslo_aero_share +#endif ! Arguments type(physics_state), intent(in), target :: state @@ -764,6 +791,14 @@ subroutine radiation_tend( & ! Local variables +#ifdef OSLO_AERO + real(r8) :: volc_fraction_coarse ! Fraction of volcanic aerosols going to coarse mode + integer :: band + character(len=3) :: c3 + real(r8), pointer :: rvolcmmr(:,:) ! Read in stratospheric volcanoes aerosol mmr + real(r8), pointer :: volcopt(:,:) ! Read in stratospheric volcano SW optical parameter (CMIP6) +#endif + logical :: idrf type(rad_out_t), pointer :: rd ! allow rd_out to be optional by allocating a local object ! if the argument is not present logical :: write_output @@ -865,10 +900,46 @@ subroutine radiation_tend( & real(r8) :: aer_tau_w_f(pcols,0:pver,nswbands) ! aerosol forward scattered fraction * w * tau real(r8) :: aer_lw_abs (pcols,pver,nlwbands) ! aerosol absorption optics depth (LW) - real(r8) :: fns(pcols,pverp) ! net shortwave flux - real(r8) :: fcns(pcols,pverp) ! net clear-sky shortwave flux - real(r8) :: fnl(pcols,pverp) ! net longwave flux - real(r8) :: fcnl(pcols,pverp) ! net clear-sky longwave flux +#ifdef OSLO_AERO + ! Local variables used for calculating aerosol optics and direct and indirect forcings. + ! aodvis and absvis are AOD and absorptive AOD for visible wavelength close to 0.55 um (0.35-0.64) + ! Note that aodvis and absvis output should be devided by dayfoc to give physical (A)AOD values + integer :: ns ! spectral loop index + real(r8) :: qdirind(pcols,pver,pcnst) ! Common tracers for indirect and direct calculations + real(r8) :: aodvis(pcols) ! AOD vis + real(r8) :: absvis(pcols) ! absorptive AOD vis + real(r8) :: clearodvis(pcols) + real(r8) :: clearabsvis(pcols) + real(r8) :: cloudfree(pcols) + real(r8) :: cloudfreemax(pcols) + real(r8) :: dod440(pcols) ! AERCOM + real(r8) :: dod550(pcols) ! AERCOM + real(r8) :: dod870(pcols) ! AERCOM + real(r8) :: abs550(pcols) ! AERCOM + real(r8) :: abs550alt(pcols) ! AERCOM + real(r8) :: clearod440(pcols) ! AERCOM + real(r8) :: clearod550(pcols) ! AERCOM + real(r8) :: clearod870(pcols) ! AERCOM + real(r8) :: clearabs550(pcols) ! AERCOM + real(r8) :: clearabs550alt(pcols) ! AERCOM + real(r8) :: ftem_1d(pcols) ! work-array to avoid NAN and pcols/ncol confusion + real(r8) :: Nnatk(pcols,pver,0:nmodes_oslo) ! Modal aerosol number concentration + real(r8) :: per_tau (pcols,0:pver,nswbands) ! aerosol extinction optical depth + real(r8) :: per_tau_w (pcols,0:pver,nswbands) ! aerosol single scattering albedo * tau + real(r8) :: per_tau_w_g(pcols,0:pver,nswbands) ! aerosol assymetry parameter * w * tau + real(r8) :: per_tau_w_f(pcols,0:pver,nswbands) ! aerosol forward scattered fraction * w * tau + real(r8) :: per_lw_abs (pcols,pver,nlwbands) ! aerosol absorption optics depth (LW) + real(r8) :: volc_ext_sun(pcols,pver,nswbands) ! volcanic aerosol extinction for solar bands ! CMIP6 + real(r8) :: volc_omega_sun(pcols,pver,nswbands) ! volcanic aerosol SSA for solar bands ! CMIP6 + real(r8) :: volc_g_sun(pcols,pver,nswbands) ! volcanic aerosol g for solar bands ! CMIP6 + real(r8) :: volc_ext_earth(pcols,pver,nlwbands) ! volcanic aerosol extinction for terrestrial bands ! CMIP6 + real(r8) :: volc_omega_earth(pcols,pver,nlwbands) ! volcanic aerosol SSA for terrestrial bands ! CMIP6 +#endif + + real(r8) :: fns(pcols,pverp) ! net shortwave flux + real(r8) :: fcns(pcols,pverp) ! net clear-sky shortwave flux + real(r8) :: fnl(pcols,pverp) ! net longwave flux + real(r8) :: fcnl(pcols,pverp) ! net clear-sky longwave flux ! for COSP real(r8) :: emis(pcols,pver) ! Cloud longwave emissivity @@ -886,6 +957,14 @@ subroutine radiation_tend( & lchnk = state%lchnk ncol = state%ncol +#ifdef OSLO_AERO + per_lw_abs(:,:,:) = 0._r8 + per_tau(:,:,:) = 0._r8 + per_tau_w(:,:,:) = 0._r8 + per_tau_w_g(:,:,:) = 0._r8 + per_tau_w_f(:,:,:) = 0._r8 +#endif + if (present(rd_out)) then rd => rd_out write_output = .false. @@ -962,6 +1041,16 @@ subroutine radiation_tend( & end do end if +#ifdef OSLO_AERO + qdirind(:ncol,:,:) = state%q(:ncol,:,:) + if (has_prescribed_volcaero) then + call oslo_aero_getopts(volc_fraction_coarse_out = volc_fraction_coarse) + call pbuf_get_field(pbuf, volc_idx, rvolcmmr, start=(/1,1,itim_old/), kount=(/pcols,pver,1/) ) + qdirind(:ncol,:,l_so4_pr) = qdirind(:ncol,:,l_so4_pr) + (1.0_r8 - volc_fraction_coarse)*rvolcmmr(:ncol,:) + qdirind(:ncol,:,l_ss_a3) = qdirind(:ncol,:,l_ss_a3) + volc_fraction_coarse*rvolcmmr(:ncol,:) + end if +#endif + ! Find tropopause height if needed for diagnostic output if (hist_fld_active('FSNR') .or. hist_fld_active('FLNR')) then call tropopause_find(state, troplev, tropP=p_trop, primary=TROP_ALG_HYBSTOB, backup=TROP_ALG_CLIMATE) @@ -1194,6 +1283,28 @@ subroutine radiation_tend( & if (dosw) then +#ifdef OSLO_AERO + ! Volcanic optics for solar (SW) bands + do band = 1,nswbands + volc_ext_sun(1:ncol,1:pver,band) = 0.0_r8 + volc_omega_sun(1:ncol,1:pver,band) = 0.999_r8 + volc_g_sun(1:ncol,1:pver,band) = 0.5_r8 + enddo + + ! Volcanic optics for terrestrial (LW) bands (g is not used here) + do band = 1,nlwbands + volc_ext_earth(1:ncol,1:pver,band) = 0.0_r8 + volc_omega_earth(1:ncol,1:pver,band) = 0.999_r8 + enddo + + ! No aerocom variables passed for now + ! dod440, dod550, dod870, abs550, abs550alt + call oslo_aero_optical_params_calc(lchnk, ncol, 10.0_r8*state%pint, state%pmid, & + coszrs, state, state%t, cld, qdirind, Nnatk, & + per_tau, per_tau_w, per_tau_w_g, per_tau_w_f, per_lw_abs, & + volc_ext_sun, volc_omega_sun, volc_g_sun, volc_ext_earth, volc_omega_earth, & + aodvis, absvis) +#endif call get_variability(sfac) ! Get the active climate/diagnostic shortwave calculations @@ -1207,8 +1318,54 @@ subroutine radiation_tend( & ! update the concentrations in the RRTMG state object call rrtmg_state_update(state, pbuf, icall, r_state) +#ifdef OSLO_AERO + !call aer_rad_props_sw(icall, state, pbuf, nnite, idxnite, & + ! aer_tau, aer_tau_w, aer_tau_w_g, aer_tau_w_f) + ! A first call with Oslo aerosols set to zero for radiative forcing diagnostics + ! follwoing the Ghan (2013) method: + + ! for calculation of direct radiative forcing, not necessarily "offline" as such anymore + ! (just nudged), but with an extra call with 0 aerosol extiction. + ! + idrf = .true. + call rad_rrtmg_sw( & + lchnk, ncol, num_rrtmg_levs, r_state, state%pmid, & + cldfprime, per_tau*0.0_r8, per_tau_w, per_tau_w_g, per_tau_w_f, & + eccf, coszrs, rd%solin, sfac, cam_in%asdir, & + cam_in%asdif, cam_in%aldir, cam_in%aldif, qrs, rd%qrsc, & + fsnt, rd%fsntc, rd%fsntoa, rd%fsutoa, rd%fsntoac, & + rd%fsnirt, rd%fsnrtc, rd%fsnirtsq, fsns, rd%fsnsc, & + rd%fsdsc, fsds, cam_out%sols, cam_out%soll, cam_out%solsd, & + cam_out%solld, fns, fcns, Nday, Nnite, & + IdxDay, IdxNite, su, sd, E_cld_tau=c_cld_tau, & + E_cld_tau_w=c_cld_tau_w, E_cld_tau_w_g=c_cld_tau_w_g, & + E_cld_tau_w_f=c_cld_tau_w_f, old_convert=.false., idrf=idrf) + + ftem(:ncol,:pver) = qrs(:ncol,:pver)/cpair + ! + ! Dump shortwave radiation information to history tape buffer (diagnostics) + ! + ! Note that DRF fields are now from the per_tau=0 call (clean), no longer with per_tau from pmxsub + call outfld('QRS_DRF ',ftem ,pcols,lchnk) + ftem(:ncol,:pver) = rd%qrsc(:ncol,:pver)/cpair + call outfld('QRSC_DRF',ftem ,pcols,lchnk) + call outfld('FSNT_DRF',fsnt(:) ,pcols,lchnk) + call outfld('FSNS_DRF',fsns(:) ,pcols,lchnk) + call outfld('FSNTCDRF',rd%fsntc(:) ,pcols,lchnk) + call outfld('FSNSCDRF',rd%fsnsc(:) ,pcols,lchnk) + if (do_aerocom) then + call outfld('FSUTADRF',rd%fsutoa(:),pcols,lchnk) + call outfld('FSDS_DRF',fsds(:) ,pcols,lchnk) + ftem_1d(1:ncol) = fsds(1:ncol)-fsns(1:ncol) + call outfld('FSUS_DRF',ftem_1d,pcols,lchnk) + call outfld('FSDSCDRF',rd%fsdsc(:) ,pcols,lchnk) + end if + idrf = .false. +#else call aer_rad_props_sw(icall, state, pbuf, nnite, idxnite, & aer_tau, aer_tau_w, aer_tau_w_g, aer_tau_w_f) + idrf = .false. +#endif rd%cld_tau_cloudsim(:ncol,:) = cld_tau(rrtmg_sw_cloudsim_band,:ncol,:) rd%aer_tau550(:ncol,:) = aer_tau(:ncol,:,idx_sw_diag) @@ -1226,7 +1383,7 @@ subroutine radiation_tend( & cam_out%solld, fns, fcns, Nday, Nnite, & IdxDay, IdxNite, su, sd, E_cld_tau=c_cld_tau, & E_cld_tau_w=c_cld_tau_w, E_cld_tau_w_g=c_cld_tau_w_g, & - E_cld_tau_w_f=c_cld_tau_w_f, old_convert=.false.) + E_cld_tau_w_f=c_cld_tau_w_f, old_convert=.false., idrf=idrf) ! Output net fluxes at 200 mb call vertinterp(ncol, pcols, pverp, state%pint, 20000._r8, fcns, rd%fsn200c) @@ -1244,6 +1401,46 @@ subroutine radiation_tend( & end if +#ifdef OSLO_AERO + !Calculate cloud-free fraction assuming random overlap + !(kind of duplicated from cloud_cover_diags::cldsav) + cloudfree(1:ncol) = 1.0_r8 + cloudfreemax(1:ncol) = 1.0_r8 + !Find cloud-free fraction (note this duplicated code and may not be consistent with cldtot calculated elsewhere) + do k = 1, pver + do i=1,ncol + cloudfree(i) = cloudfree(i) * cloudfreemax(i) + cloudfreemax(i) = min(cloudfreemax(i),1.0_r8-cld(i,k)) + end do + end do + + !Calculate AOD (visible) for cloud free + do i = 1, ncol + clearodvis(i)=cloudfree(i)*aodvis(i) + clearabsvis(i)=cloudfree(i)*absvis(i) + end do + + ! clear-sky AOD and absorptive AOD for visible wavelength close to 0.55 um (0.35-0.64) + ! Note that caodvis and cabsvis output should be devided by dayfoc*cloudfree to give physical (A)AOD values + call outfld('CAODVIS ',clearodvis,pcols,lchnk) + call outfld('CABSVIS ',clearabsvis,pcols,lchnk) + call outfld('CLDFREE ',cloudfree,pcols,lchnk) + if (do_aerocom) then + do i = 1, ncol + clearod440(i)=cloudfree(i)*dod440(i) + clearod550(i)=cloudfree(i)*dod550(i) + clearod870(i)=cloudfree(i)*dod870(i) + clearabs550(i)=cloudfree(i)*abs550(i) + clearabs550alt(i)=cloudfree(i)*abs550alt(i) + end do + call outfld('CDOD440 ',clearod440 ,pcols,lchnk) + call outfld('CDOD550 ',clearod550 ,pcols,lchnk) + call outfld('CDOD870 ',clearod870 ,pcols,lchnk) + call outfld('CABS550 ',clearabs550 ,pcols,lchnk) + call outfld('CABS550A',clearabs550alt,pcols,lchnk) + end if +#endif + ! Output aerosol mmr call rad_cnst_out(0, state, pbuf) @@ -1263,12 +1460,35 @@ subroutine radiation_tend( & call aer_rad_props_lw(icall, state, pbuf, aer_lw_abs) +#ifdef OSLO_AERO + call rad_rrtmg_lw( & + lchnk, ncol, num_rrtmg_levs, r_state, state%pmid, & + per_lw_abs*0.0_r8, cldfprime, c_cld_lw_abs, qrl, rd%qrlc, & + flns, flnt, rd%flnsc, rd%flntc, cam_out%flwds, & + rd%flut, rd%flutc, fnl, fcnl, rd%fldsc, & + lu, ld) + + call outfld('FLNT_DRF',flnt(:) ,pcols,lchnk) + call outfld('FLNTCDRF',rd%flntc(:) ,pcols,lchnk) + + call rad_rrtmg_lw( & + lchnk, ncol, num_rrtmg_levs, r_state, state%pmid, & + per_lw_abs, cldfprime, c_cld_lw_abs, qrl, rd%qrlc, & + flns, flnt, rd%flnsc, rd%flntc, cam_out%flwds, & + rd%flut, rd%flutc, fnl, fcnl, rd%fldsc, & + lu, ld) + + ! FLNT_ORG is just for temporary testing vs. FLNT + ftem_1d(1:ncol) = cam_out%flwds(1:ncol) - flns(1:ncol) + call outfld('FLUS ',ftem_1d ,pcols,lchnk) +#else call rad_rrtmg_lw( & lchnk, ncol, num_rrtmg_levs, r_state, state%pmid, & aer_lw_abs, cldfprime, c_cld_lw_abs, qrl, rd%qrlc, & flns, flnt, rd%flnsc, rd%flntc, cam_out%flwds, & rd%flut, rd%flutc, fnl, fcnl, rd%fldsc, & lu, ld) +#endif ! Output fluxes at 200 mb call vertinterp(ncol, pcols, pverp, state%pint, 20000._r8, fnl, rd%fln200) diff --git a/src/physics/rrtmg/radlw.F90 b/src/physics/rrtmg/radlw.F90 index b2b56a751c..7e2d80de68 100644 --- a/src/physics/rrtmg/radlw.F90 +++ b/src/physics/rrtmg/radlw.F90 @@ -227,12 +227,16 @@ subroutine rad_rrtmg_lw(lchnk ,ncol ,rrtmg_levs,r_state, & fsul(:ncol,pverp-rrtmg_levs+1:pverp)=uflxc(:ncol,rrtmg_levs:1:-1) fsdl(:ncol,pverp-rrtmg_levs+1:pverp)=dflxc(:ncol,rrtmg_levs:1:-1) +#ifndef OSLO_AERO if (single_column.and.scm_crm_mode) then +#endif call outfld('FUL ',ful,pcols,lchnk) call outfld('FDL ',fdl,pcols,lchnk) call outfld('FULC ',fsul,pcols,lchnk) call outfld('FDLC ',fsdl,pcols,lchnk) +#ifndef OSLO_AERO endif +#endif fnl(:ncol,:) = ful(:ncol,:) - fdl(:ncol,:) ! mji/ cam excluded this? diff --git a/src/physics/rrtmg/radsw.F90 b/src/physics/rrtmg/radsw.F90 index df222557dd..5df39fdbda 100644 --- a/src/physics/rrtmg/radsw.F90 +++ b/src/physics/rrtmg/radsw.F90 @@ -53,7 +53,7 @@ subroutine rad_rrtmg_sw(lchnk,ncol ,rrtmg_levs ,r_state , & Nday ,Nnite ,IdxDay ,IdxNite , & su ,sd , & E_cld_tau, E_cld_tau_w, E_cld_tau_w_g, E_cld_tau_w_f, & - old_convert) + old_convert, idrf) !----------------------------------------------------------------------- @@ -132,7 +132,8 @@ subroutine rad_rrtmg_sw(lchnk,ncol ,rrtmg_levs ,r_state , & real(r8), optional, intent(in) :: E_cld_tau_w (nbndsw, pcols, pver) ! cloud optical real(r8), optional, intent(in) :: E_cld_tau_w_g(nbndsw, pcols, pver) ! cloud optical real(r8), optional, intent(in) :: E_cld_tau_w_f(nbndsw, pcols, pver) ! cloud optical - logical, optional, intent(in) :: old_convert + logical , optional, intent(in) :: old_convert + logical , optional, intent(in) :: idrf ! Output arguments @@ -304,12 +305,16 @@ subroutine rad_rrtmg_sw(lchnk,ncol ,rrtmg_levs ,r_state , & qrsc(1:ncol,1:pver) = 0.0_r8 fns(1:ncol,1:pverp) = 0.0_r8 fcns(1:ncol,1:pverp) = 0.0_r8 +#ifndef OSLO_AERO if (single_column.and.scm_crm_mode) then +#endif fus(1:ncol,1:pverp) = 0.0_r8 fds(1:ncol,1:pverp) = 0.0_r8 fusc(:ncol,:pverp) = 0.0_r8 fdsc(:ncol,:pverp) = 0.0_r8 +#ifndef OSLO_AERO endif +#endif if (associated(su)) su(1:ncol,:,:) = 0.0_r8 if (associated(sd)) sd(1:ncol,:,:) = 0.0_r8 @@ -622,7 +627,9 @@ subroutine rad_rrtmg_sw(lchnk,ncol ,rrtmg_levs ,r_state , & end if ! these outfld calls don't work for spmd only outfield in scm mode (nonspmd) +#ifndef OSLO_AERO if (single_column .and. scm_crm_mode) then +#endif ! Following outputs added for CRM call ExpDayNite(fus,Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pverp) call ExpDayNite(fds,Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pverp) @@ -632,7 +639,15 @@ subroutine rad_rrtmg_sw(lchnk,ncol ,rrtmg_levs ,r_state , & call outfld('FDS ', fds, pcols, lchnk) call outfld('FUSC ', fusc, pcols, lchnk) call outfld('FDSC ', fdsc, pcols, lchnk) - endif +#ifndef OSLO_AERO + end if +#endif + if (present(idrf)) then + if (idrf) then + call outfld('FUSCDRF ', fusc, pcols, lchnk) + call outfld('FDSCDRF ', fdsc, pcols, lchnk) + endif + end if end subroutine rad_rrtmg_sw From b4efb864d0edc7ae52274190740d0a59bc6b48b0 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Fri, 8 Sep 2023 22:32:42 +0200 Subject: [PATCH 04/24] more updates to fix errors in the run --- bld/build-namelist | 134 ++++++++++++++++++- bld/namelist_files/namelist_defaults_cam.xml | 14 ++ bld/namelist_files/namelist_definition.xml | 122 +++++++++++++++++ src/chemistry/mozart/mo_srf_emissions.F90 | 2 + 4 files changed, 269 insertions(+), 3 deletions(-) diff --git a/bld/build-namelist b/bld/build-namelist index efd42d4949..1ddc31a2fa 100755 --- a/bld/build-namelist +++ b/bld/build-namelist @@ -569,6 +569,11 @@ if ($cfg->get('debug')) { my $prescribe_aerosols = $TRUE; if ($simple_phys) {$prescribe_aerosols = $FALSE;} +if( $chem =~ /_oslo/){ +$prescribe_aerosols = $FALSE; +print " ==> Using Oslo aerosols: PRESCRIBED AERO = FALSE (not yet implemented) \n" +} + # Chemistry deposition lists if ( ($chem ne 'none') or ( $prog_species ) ){ my $chem_proc_src = $cfg->get('chem_proc_src'); @@ -928,7 +933,15 @@ else { my $aer_model = 'bam'; if ($prescribed_aero_model eq 'modal' or $chem =~ /_mam/) {$aer_model = 'mam';} -if ($aer_model eq 'mam' ) { +if ($chem =~ /_mam_oslo/) {$aer_model = 'oslo';} + + #do nothing here + +if ($aer_model eq 'oslo') { + + #do nothing here + +} elsif ($aer_model eq 'mam' ) { my $aero_modes = '3mode'; if ($chem =~ /_mam7/) {$aero_modes = '7mode';} @@ -1542,7 +1555,7 @@ elsif ($carma eq 'tholin') { # turn on stratospheric aerosol forcings in CAM6 configurations my $chem_has_ocs = chem_has_species($cfg, 'OCS'); -if (($phys =~ /cam6/ or $phys =~ /cam_dev/) and $chem =~ /_mam/) { +if (($phys =~ /cam6/ or $phys =~ /cam_dev/) and $chem =~ /_mam/ and $chem ne 'trop_mam_oslo') { # turn on volc forcings in cam6 -- prognostic or prescribed if ( $chem_has_ocs ) { # turn on prognostic stratospheric aerosols @@ -1684,6 +1697,7 @@ if ($chem =~ /ghg_mam4/) { } add_default($nl, 'flbc_file'); } + if ( $prog_species ) { my $ddval; my $emisval; @@ -2594,10 +2608,96 @@ if (($chem eq 'trop_mam4') or ($chem eq 'waccm_sc_mam4') or ($chem eq 'ghg_mam4' add_default($nl, $file); } } -if ($chem eq 'trop_mam7') { + +if ($chem eq 'trop_mam_oslo' ) { my %species; + # Surface emission datasets: + %species = (); + %species = (%species, + 'DMS -> ' => 'dms_oslo_emis_file', + 'SO2 -> ' => 'so2_oslo_emis_file', + 'BC_AX -> ' => 'bc_ax_oslo_emis_file', + 'BC_N -> ' =>'bc_n_oslo_emis_file', + 'BC_NI -> ' =>'bc_ni_oslo_emis_file', + 'SO4_PR -> ' =>'so4_pr_oslo_emis_file', + 'OM_NI -> ' =>'om_ni_oslo_emis_file', + 'monoterp -> ' => 'monoterp_oslo_emis_file', + 'isoprene -> ' => 'isoprene_oslo_emis_file', + ); + + my $first = 1; + my $pre = ""; + my $val = ""; + foreach my $id (sort keys %species) { + my $rel_filepath = get_default_value($species{$id} ); + my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir); + $val .= $pre . quote_string($id . $abs_filepath); + if ($first) { + $pre = ","; + $first = 0; + } + } + add_default($nl, 'srf_emis_specifier', 'val'=>$val); + unless (defined $nl->get_value('srf_emis_type')) { + add_default($nl, 'srf_emis_type', 'val'=>'CYCLICAL'); + add_default($nl, 'srf_emis_cycle_yr', 'val'=>'2000'); + } + + # Vertical emission datasets: + %species = (); + %species = ('SO2 -> ' => 'so2_oslo_ext_file', + 'BC_AX -> ' => 'bc_ax_oslo_ext_file', + 'BC_N -> ' => 'bc_n_oslo_ext_file', + 'BC_NI -> ' => 'bc_ni_oslo_ext_file', + 'OM_NI -> ' => 'om_ni_oslo_ext_file', + 'SO4_PR -> ' => 'so4_pr_oslo_ext_file'); + + $first = 1; + $pre = ""; + $val = ""; + foreach my $id (sort keys %species) { + my $rel_filepath = get_default_value($species{$id} ); + my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir); + $val .= $pre . quote_string($id . $abs_filepath); + if ($first) { + $pre = ","; + $first = 0; + } + } + add_default($nl, 'ext_frc_specifier', 'val'=>$val); + unless (defined $nl->get_value('ext_frc_type')) { + add_default($nl, 'ext_frc_type', 'val'=>"'CYCLICAL'"); + add_default($nl, 'ext_frc_cycle_yr', 'val'=>'2000'); + } + + # Prescribed species + add_default($nl, 'tracer_cnst_specifier', 'val'=>"'O3','OH','NO3','HO2'"); + unless (defined $nl->get_value('tracer_cnst_type')) { + add_default($nl, 'tracer_cnst_type', 'ver'=>'fixed_ox'); + add_default($nl, 'tracer_cnst_cycle_yr','ver'=>'fixed_ox'); + } + + my @files = ('tracer_cnst_datapath', 'tracer_cnst_file', 'tracer_cnst_filelist'); + foreach my $file (@files) { + add_default($nl, $file, 'ver'=>'fixed_ox'); + } + + add_default($nl, 'fstrat_list', 'val'=>"' '"); + add_default($nl, 'flbc_list', 'val'=>"' '"); + + # Datasets + my @files = ('soil_erod_file', + 'xs_long_file', 'rsf_file', 'exo_coldens_file' ); + foreach my $file (@files) { + add_default($nl, $file); + } +} + +if ($chem eq 'trop_mam7') { + my %species; + # Surface emission datasets: %species = (); %species = ('DMS -> ' => 'dms_emis_file', @@ -2625,6 +2725,7 @@ if ($chem eq 'trop_mam7') { $first = 0; } } + add_default($nl, 'srf_emis_specifier', 'val'=>$val); unless (defined $nl->get_value('srf_emis_type')) { add_default($nl, 'srf_emis_type', 'val'=>'CYCLICAL'); @@ -2807,6 +2908,7 @@ if ($chem =~ /waccm_ma/ or $chem =~ /waccm_tsmlt/) { add_default($nl, 'efield_potential_max', 'val'=>'120.D0'); } + # Determine the source of the prescribed GHG values. my $lbc_file = $nl->get_value('flbc_file'); @@ -2917,6 +3019,32 @@ $use_simple_phys = '.false.'; if ($simple_phys) {$use_simple_phys = '.true.';} $nl->set_variable_value('phys_ctl_nl', 'use_simple_phys', $use_simple_phys); +#Cam-Oslo options + add_default($nl, 'volc_fraction_coarse'); + add_default($nl, 'aerotab_table_dir'); + add_default($nl, 'ocean_filepath'); + add_default($nl, 'dms_source'); + add_default($nl, 'opom_source'); +#add_default($nl, 'dms_source_type'); +#add_default($nl, 'dms_cycle_year'); +#add_default($nl, 'ocean_filename'); +#add_default($nl, 'ocean_filepath'); +#add_default($nl, 'opom_source'); +unless (defined $nl->get_value('ocean_filename')) { + add_default($nl, 'ocean_filename'); +} +unless (defined $nl->get_value('opom_source_type')) { + add_default($nl, 'opom_source_type'); + add_default($nl, 'opom_cycle_year'); +} +unless (defined $nl->get_value('dms_source_type')) { + add_default($nl, 'dms_source_type'); + add_default($nl, 'dms_cycle_year'); +} +#add_default($nl, 'opom_source_type'); +#add_default($nl, 'opom_cycle_year'); +if ($chem =~ /_mam_oslo/) {$nl->set_variable_value('phys_ctl_nl','use_hetfrz_classnuc','.true.');} + # WACCM-X runtime options add_default($nl, 'waccmx_opt'); diff --git a/bld/namelist_files/namelist_defaults_cam.xml b/bld/namelist_files/namelist_defaults_cam.xml index 6eb81ca2e8..776eda9aca 100644 --- a/bld/namelist_files/namelist_defaults_cam.xml +++ b/bld/namelist_files/namelist_defaults_cam.xml @@ -3338,6 +3338,7 @@ ' C3H6_O3 + ISOP_O3 + MVK_O3 + MACR_O3 + MTERP_O3 + BCARY_O3 + S_O3 + SO_O3' + .false. atm/cam/geoschem/emis/ExtData/HEMCO @@ -3365,4 +3366,17 @@ 144 91 + +.true. +0.0 +noresm-only/atm/cam/camoslo/AeroTab_8jun17/ +lana +CYCLICAL +2000 +odowd +CYCLICAL +2000 +Lana_ocean_1849_2006.nc +noresm-only/atm/cam/camoslo + diff --git a/bld/namelist_files/namelist_definition.xml b/bld/namelist_files/namelist_definition.xml index 3ba59737e0..224b9d80c8 100644 --- a/bld/namelist_files/namelist_definition.xml +++ b/bld/namelist_files/namelist_definition.xml @@ -9292,4 +9292,126 @@ Last year to loop over for Nitrogen Deposition data Simulation year that aligns with stream_year_first_ndep value + + + + + +Fraction of volcanic aerosols which will end up in coarse mode +Default: 0.0 + + +Directory where we will expect to find the CAM-Oslo tables +created from AeroTab + + + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + AeroTab file + + +Type of DMS data source +Default: emission_file + + + +Type of DMS data source type +Default: CYCLICAL + + + +DMS cycle year +Default: 2000 + + + +Type of ocean POM data source +Default: no_file + + + +Type of ocean POM data source type +Default: CYCLICAL + + + +Ocean POM cycle year +Default: 2000 + + + +Filename for ocean concentration of DMS, chlorophyll and poc +Default: name + + + +Path to ocean file +Default: path + + diff --git a/src/chemistry/mozart/mo_srf_emissions.F90 b/src/chemistry/mozart/mo_srf_emissions.F90 index 7dd439cd39..5942cf41b5 100644 --- a/src/chemistry/mozart/mo_srf_emissions.F90 +++ b/src/chemistry/mozart/mo_srf_emissions.F90 @@ -39,7 +39,9 @@ module mo_srf_emissions type(emission), allocatable :: emissions(:) integer :: n_emis_files integer :: c10h16_ndx, isop_ndx +#ifdef OSLO_AERO integer :: dms_ndx +#endif contains From 15d12f3e1057e823584da9d41d5f08d4d0ac6ac1 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Tue, 12 Sep 2023 11:46:44 +0200 Subject: [PATCH 05/24] changed Externals_CAM --- Externals_CAM.cfg | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Externals_CAM.cfg b/Externals_CAM.cfg index 83a9db2bcf..17b5cbfc2d 100644 --- a/Externals_CAM.cfg +++ b/Externals_CAM.cfg @@ -63,15 +63,19 @@ required = True [camnor_phys] protocol = git -tag = camnor_noresm_v0.0.3 -repo_url = https://github.com/NorESMhub/CAM-Nor-physics +#tag = camnor_noresm_v0.0.3 +branch = feature/oslo_aero_integrate +#repo_url = https://github.com/NorESMhub/CAM-Nor-physics +repo_url = https://github.com/mvertens/CAM-Nor-physics local_path = src/physics/camnor_phys required = True [oslo_aero] protocol = git -branch = noresm_develop -repo_url = https://github.com/NorESMhub/OSLO_AERO +#branch = noresm_develop +branch = feature/oslo_aero_integrate +#repo_url = https://github.com/NorESMhub/OSLO_AERO +repo_url = https://github.com/mvertens/OSLO_AERO local_path = src/chemistry/oslo_aero required = True From e5db0d8f7509455cd20ba0c542d3b6007dc71c55 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Tue, 12 Sep 2023 13:41:57 +0200 Subject: [PATCH 06/24] simplified usage of OSLO_AERO --- .../use_cases/2000_cam6_noresm.xml | 163 ++++++++++++++++++ src/control/runtime_opts.F90 | 14 -- src/physics/cam/vertical_diffusion.F90 | 98 ++++++----- src/physics/rrtmg/radiation.F90 | 2 +- 4 files changed, 216 insertions(+), 61 deletions(-) create mode 100644 bld/namelist_files/use_cases/2000_cam6_noresm.xml diff --git a/bld/namelist_files/use_cases/2000_cam6_noresm.xml b/bld/namelist_files/use_cases/2000_cam6_noresm.xml new file mode 100644 index 0000000000..a1830459ae --- /dev/null +++ b/bld/namelist_files/use_cases/2000_cam6_noresm.xml @@ -0,0 +1,163 @@ + + + + + + + + + +'atm/cam/solar/SolarForcingCMIP6_18491230-22991231_c171031.nc' +20000101 +FIXED + + +'CHEM_LBC_FILE' + + +atm/waccm/lb/LBC_1750-2015_CMIP6_GlobAnnAvg_c180926.nc +'FIXED' +'CO2','CH4','N2O','CFC11eq','CFC12' +20000702 + + +'atm/cam/ozone_strataero' +'ozone_strataero_WACCM_L70_zm5day_18500101-20150103_CMIP6ensAvg_c180923.nc' +'O3' +'CYCLICAL' +2000 + + +'atm/cam/tracer_cnst' +'tracer_cnst_halons_3D_L70_1849-2015_CMIP6ensAvg_c180927.nc' +'O3','OH','NO3','HO2' +'CYCLICAL' +'' +2000 + + +CYCLICAL +2000 + + 'H2O -> $INPUTDATA_ROOT/atm/cam/chem/emis/elev/H2OemissionCH4oxidationx2_3D_L70_1849-2015_CMIP6ensAvg_c180927.nc', + 'BC_AX -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_AX_airALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'BC_AX -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_AX_anthroprofALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'BC_N -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_N_airALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'BC_N -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_N_anthroprofALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'BC_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_NI_bbALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_airALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_anthroprofALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_bbALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_airALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_anthroprofALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_bbALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_volcALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_airALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_anthroprofALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_bbALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_volcALL_vertical_1849-2015_0.9x1.25_version20180512.nc' + + + 'H2O -> $INPUTDATA_ROOT/atm/cam/chem/emis/elev/H2OemissionCH4oxidationx2_3D_L70_1849-2015_CMIP6ensAvg_c180927.nc', + 'BC_AX -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_AX_airALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'BC_AX -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_AX_anthroprofALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'BC_N -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_N_airALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'BC_N -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_N_anthroprofALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'BC_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_NI_bbALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_airALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_anthroprofALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_bbALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_airALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_anthroprofALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_bbALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_volcALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_airALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_anthroprofALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_bbALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_volcALL_vertical_1849-2015_1.9x2.5_version20180512.nc' + + + +CYCLICAL +2000 + + 'BC_AX -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_AX_anthrosurfALL_surface_1849-2015_0.9x1.25_version20180512.nc', + 'BC_N -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_N_anthrosurfALL_surface_1849-2015_0.9x1.25_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_anthrosurfALL_surface_1849-2015_0.9x1.25_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_anthrosurfALL_surface_1849-2015_0.9x1.25_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_anthrosurfALL_surface_1849-2015_0.9x1.25_version20180512.nc' + + + 'BC_AX -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_AX_anthrosurfALL_surface_1849-2015_1.9x2.5_version20180512.nc', + 'BC_N -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_N_anthrosurfALL_surface_1849-2015_1.9x2.5_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_anthrosurfALL_surface_1849-2015_1.9x2.5_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_anthrosurfALL_surface_1849-2015_1.9x2.5_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_anthrosurfALL_surface_1849-2015_1.9x2.5_version20180512.nc' + + + + + + + +0.286 +0.264 + + +.false. +.true. +.true. +.true. +.true. +.true. + + +.true. + + +.true. + + +0.0200D0 +0.0200D0 +8.0E-6 +8.0E-6 + + +5.5e-4 +5.0e-4 + + +.true. + + +4 + + +0.90D0 + + +'isoprene = isoprene','monoterp = myrcene + sabinene + limonene+ carene_3 + ocimene_t_b + pinene_b + pinene_a' + + +noresm-only/atm/cam/chem/trop_mozart_aero/emis/soanucl/bvocgcmFV19_isopr_1850_2000_zero.nc +noresm-only/atm/cam/chem/trop_mozart_aero/emis/soanucl/bvocgcmFV19_monoterp_1850_2000_zero.nc + + +1850 + + + + + + + + + + + + +'A:Q:H2O','N:O2:O2','N:CO2:CO2','N:ozone:O3','N:N2O:N2O','N:CH4:CH4','N:CFC11:CFC11','N:CFC12:CFC12' + + + diff --git a/src/control/runtime_opts.F90 b/src/control/runtime_opts.F90 index e4f6499e11..3d4cb35c95 100644 --- a/src/control/runtime_opts.F90 +++ b/src/control/runtime_opts.F90 @@ -39,9 +39,6 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon) use air_composition, only: air_composition_readnl use physics_buffer, only: pbuf_readnl use phys_control, only: phys_ctl_readnl -#ifdef OSLO_AERO - use oslo_aero_control, only: oslo_aero_ctl_readnl -#endif use wv_saturation, only: wv_sat_readnl use ref_pres, only: ref_pres_readnl use cam3_aero_data, only: cam3_aero_data_readnl @@ -49,11 +46,7 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon) use dadadj_cam, only: dadadj_readnl use macrop_driver, only: macrop_driver_readnl use microp_driver, only: microp_driver_readnl -#ifdef OSLO_AERO - use oslo_aero_microp, only: oslo_aero_microp_readnl -#else use microp_aero, only: microp_aero_readnl -#endif use subcol, only: subcol_readnl use cloud_fraction, only: cldfrc_readnl use cldfrc2m, only: cldfrc2m_readnl @@ -155,11 +148,7 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon) call dadadj_readnl(nlfilename) call macrop_driver_readnl(nlfilename) call microp_driver_readnl(nlfilename) -#ifdef OSLO_AERO - call oslo_aero_microp_readnl(nlfilename) -#else call microp_aero_readnl(nlfilename) -#endif call clubb_readnl(nlfilename) call subcol_readnl(nlfilename) call cldfrc_readnl(nlfilename) @@ -204,9 +193,6 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon) call rayleigh_friction_readnl(nlfilename) #if ( defined OFFLINE_DYN ) call metdata_readnl(nlfilename) -#endif -#ifdef OSLO_AERO - call oslo_aero_ctl_readnl(nlfilename) #endif call offline_driver_readnl(nlfilename) call analytic_ic_readnl(nlfilename) diff --git a/src/physics/cam/vertical_diffusion.F90 b/src/physics/cam/vertical_diffusion.F90 index af78c84cd1..c3860b081a 100644 --- a/src/physics/cam/vertical_diffusion.F90 +++ b/src/physics/cam/vertical_diffusion.F90 @@ -141,6 +141,12 @@ module vertical_diffusion logical :: do_pbl_diags = .false. logical :: waccmx_mode = .false. +#ifdef OSLO_AERO +logical :: oslo_aero = .true. +#else +logical :: oslo_aero = .false. +#endif + contains ! =============================================================================== ! @@ -320,11 +326,11 @@ subroutine vertical_diffusion_init(pbuf2d) call cnst_get_ind( 'NUMICE', ixnumice, abort=.false. ) ! prog_modal_aero determines whether prognostic modal aerosols are present in the run. -#ifdef OSLO_AERO - prog_modal_aero = .true. -#else - call phys_getopts(prog_modal_aero_out=prog_modal_aero) -#endif + if (oslo_aero) then + prog_modal_aero = .true. + else + call phys_getopts(prog_modal_aero_out=prog_modal_aero) + end if if (prog_modal_aero) then ! Get the constituent indices of the number and mass mixing ratios of the modal ! aerosols. @@ -332,32 +338,32 @@ subroutine vertical_diffusion_init(pbuf2d) ! N.B. - This implementation assumes that the prognostic modal aerosols are ! impacting the climate calculation (i.e., can get info from list 0). ! -#ifdef OSLO_AERO - pmam_ncnst = getNumberOfAerosolTracers() - allocate(pmam_cnst_idx(pmam_ncnst)) - call fillAerosolTracerList(pmam_cnst_idx) -#else - ! First need total number of mam constituents - call rad_cnst_get_info(0, nmodes=nmodes) - do m = 1, nmodes - call rad_cnst_get_info(0, m, nspec=nspec) - pmam_ncnst = pmam_ncnst + 1 + nspec - end do + if (oslo_aero) then + pmam_ncnst = getNumberOfAerosolTracers() + allocate(pmam_cnst_idx(pmam_ncnst)) + call fillAerosolTracerList(pmam_cnst_idx) + else + ! First need total number of mam constituents + call rad_cnst_get_info(0, nmodes=nmodes) + do m = 1, nmodes + call rad_cnst_get_info(0, m, nspec=nspec) + pmam_ncnst = pmam_ncnst + 1 + nspec + end do - allocate(pmam_cnst_idx(pmam_ncnst)) + allocate(pmam_cnst_idx(pmam_ncnst)) - ! Get the constituent indicies - im = 1 - do m = 1, nmodes - call rad_cnst_get_mode_num_idx(m, pmam_cnst_idx(im)) - im = im + 1 - call rad_cnst_get_info(0, m, nspec=nspec) - do l = 1, nspec - call rad_cnst_get_mam_mmr_idx(m, l, pmam_cnst_idx(im)) + ! Get the constituent indicies + im = 1 + do m = 1, nmodes + call rad_cnst_get_mode_num_idx(m, pmam_cnst_idx(im)) im = im + 1 + call rad_cnst_get_info(0, m, nspec=nspec) + do l = 1, nspec + call rad_cnst_get_mam_mmr_idx(m, l, pmam_cnst_idx(im)) + im = im + 1 + end do end do - end do -#endif + end if end if ! end of if prog_model_aero ! Initialize upper boundary condition module @@ -582,10 +588,10 @@ subroutine vertical_diffusion_init(pbuf2d) if( history_budget ) then call add_default( vdiffnam(ixcldliq), history_budget_histfile_num, ' ' ) call add_default( vdiffnam(ixcldice), history_budget_histfile_num, ' ' ) -#ifdef OSLO_AERO - call add_default( vdiffnam(ixnumliq), history_budget_histfile_num, ' ' ) - call add_default( vdiffnam(ixnumice), history_budget_histfile_num, ' ' ) -#endif + if (oslo_aero) then + call add_default( vdiffnam(ixnumliq), history_budget_histfile_num, ' ' ) + call add_default( vdiffnam(ixnumice), history_budget_histfile_num, ' ' ) + end if if( history_budget_histfile_num > 1 ) then call add_default( vdiffnam(1), history_budget_histfile_num, ' ' ) call add_default( 'DTV' , history_budget_histfile_num, ' ' ) @@ -1187,22 +1193,22 @@ subroutine vertical_diffusion_tend( & end if -#ifdef OSLO_AERO - ! Oslo aero adds emissions together with dry deposition - so do not add the explicit - ! surface fluxes to the lowest layer -#else - if (prog_modal_aero) then - - ! Modal aerosol species not diffused, so just add the explicit surface fluxes to the - ! lowest layer. **NOTE** This code assumes wet mmr. - - tmp1(:ncol) = ztodt * gravit * state%rpdel(:ncol,pver) - do m = 1, pmam_ncnst - l = pmam_cnst_idx(m) - q_tmp(:ncol,pver,l) = q_tmp(:ncol,pver,l) + tmp1(:ncol) * cflux(:ncol,l) - enddo + if (oslo_aero) then + ! Do nothing + ! Oslo aero adds emissions together with dry deposition - so do not add the explicit + ! surface fluxes to the lowest layer + else + if (prog_modal_aero) then + ! Modal aerosol species not diffused, so just add the explicit surface fluxes to the + ! lowest layer. **NOTE** This code assumes wet mmr. + + tmp1(:ncol) = ztodt * gravit * state%rpdel(:ncol,pver) + do m = 1, pmam_ncnst + l = pmam_cnst_idx(m) + q_tmp(:ncol,pver,l) = q_tmp(:ncol,pver,l) + tmp1(:ncol) * cflux(:ncol,l) + enddo + end if end if -#endif ! -------------------------------------------------------- ! ! Diagnostics and output writing after applying PBL scheme ! diff --git a/src/physics/rrtmg/radiation.F90 b/src/physics/rrtmg/radiation.F90 index 88da5dc2b0..f350a8014b 100644 --- a/src/physics/rrtmg/radiation.F90 +++ b/src/physics/rrtmg/radiation.F90 @@ -42,8 +42,8 @@ module radiation use error_messages, only: handle_err use perf_mod, only: t_startf, t_stopf use cam_logfile, only: iulog +use prescribed_volcaero, only: has_prescribed_volcaero #ifdef OSLO_AERO -use prescribed_volcaero, only: has_prescribed_volcaero use oslo_aero_optical_params, only: oslo_aero_optical_params_calc use oslo_aero_params, only: nmodes_oslo => nmodes, nbmodes #endif From 56eb9012dc72c82474159ed88ff7adf195697721 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Tue, 12 Sep 2023 20:50:19 +0200 Subject: [PATCH 07/24] added logic for getting dms flux from ocean to nuopc cap --- src/cpl/nuopc/atm_import_export.F90 | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/cpl/nuopc/atm_import_export.F90 b/src/cpl/nuopc/atm_import_export.F90 index 8c28b120fa..dc21bf7392 100644 --- a/src/cpl/nuopc/atm_import_export.F90 +++ b/src/cpl/nuopc/atm_import_export.F90 @@ -62,6 +62,7 @@ module atm_import_export integer :: emis_nflds = -huge(1) ! number of fire emission fields from lnd-> atm integer, public :: ndep_nflds = -huge(1) ! number of nitrogen deposition fields from atm->lnd/ocn logical :: atm_provides_lightning = .false. ! cld to grnd lightning flash freq (min-1) + logical, public :: dms_from_ocn = .false. ! dms is obtained from ocean as atm import data character(*),parameter :: F01 = "('(cam_import_export) ',a,i8,2x,i8,2x,d21.14)" character(*),parameter :: F02 = "('(cam_import_export) ',a,i8,2x,i8,2x,i8,2x,d21.14)" character(*),parameter :: u_FILE_u = __FILE__ @@ -113,6 +114,7 @@ subroutine advertise_fields(gcomp, flds_scalar_name, rc) logical :: flds_co2a ! use case logical :: flds_co2b ! use case logical :: flds_co2c ! use case + logical :: ispresent, isset character(len=128) :: fldname character(len=*), parameter :: subname='(atm_import_export:advertise_fields)' !------------------------------------------------------------------------------- @@ -141,6 +143,15 @@ subroutine advertise_fields(gcomp, flds_scalar_name, rc) read(cvalue,*) flds_co2c if (masterproc) write(iulog,'(a)') trim(subname)//'flds_co2c = '// trim(cvalue) + call NUOPC_CompAttributeGet(gcomp, name='dms_ocn2atm', value=cvalue, ispresent=ispresent, isset=isset, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (ispresent .and. isset) then + read(cvalue,*) dms_from_ocn + else + dms_from_ocn = .false. + end if + if (masterproc) write(iulog,'(a,l)') trim(subname)//'dms_from_ocn = ',dms_from_ocn + !-------------------------------- ! Export fields !-------------------------------- @@ -289,6 +300,11 @@ subroutine advertise_fields(gcomp, flds_scalar_name, rc) call set_active_Sl_soilw(.true.) ! check for carma end if + ! DMS source from ocean + if (dms_from_ocn) then + call fldlist_add(fldsToAtm_num, fldsToAtm, 'Faoo_dms_ocn') ! optional + end if + ! ------------------------------------------ ! Now advertise above import fields ! ------------------------------------------ From 45dfaba97b564e7a80429d81b4622dd88c78d9bb Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Wed, 13 Sep 2023 11:08:57 +0200 Subject: [PATCH 08/24] removed trailing whitespace --- src/chemistry/aerosol/mo_setsox.F90 | 68 +++---- src/chemistry/mozart/chemistry.F90 | 4 +- src/chemistry/mozart/mo_chm_diags.F90 | 2 +- src/chemistry/mozart/mo_srf_emissions.F90 | 4 +- src/chemistry/mozart/mo_usrrxt.F90 | 2 +- src/chemistry/pp_trop_mam_oslo/chem_mech.doc | 188 +++++++++---------- src/physics/rrtmg/radiation.F90 | 33 ++-- 7 files changed, 150 insertions(+), 151 deletions(-) diff --git a/src/chemistry/aerosol/mo_setsox.F90 b/src/chemistry/aerosol/mo_setsox.F90 index 9543900de0..3a7708bc28 100644 --- a/src/chemistry/aerosol/mo_setsox.F90 +++ b/src/chemistry/aerosol/mo_setsox.F90 @@ -23,12 +23,12 @@ module MO_SETSOX contains -!----------------------------------------------------------------------- -!----------------------------------------------------------------------- +!----------------------------------------------------------------------- +!----------------------------------------------------------------------- subroutine sox_inti - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- ! ... initialize the hetero sox routine - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- use mo_chem_utls, only : get_spc_ndx, get_inv_ndx use spmd_utils, only : masterproc @@ -52,7 +52,7 @@ subroutine sox_inti !----------------------------------------------------------------- ! ... get species indicies !----------------------------------------------------------------- - + if (cloud_borne) then id_h2so4 = get_spc_ndx( 'H2SO4' ) else @@ -125,16 +125,16 @@ subroutine sox_inti write(iulog,*) 'mozart will do sox aerosols' write(iulog,*) '-----------------------------------------' endif - else + else return end if call sox_cldaero_init() end subroutine sox_inti - -!----------------------------------------------------------------------- -!----------------------------------------------------------------------- + +!----------------------------------------------------------------------- +!----------------------------------------------------------------------- subroutine SETSOX( & ncol, & lchnk, & @@ -161,7 +161,7 @@ subroutine SETSOX( & aqso4_o3_3d & ) - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- ! ... Compute heterogeneous reactions of SOX ! ! (0) using initial PH to calculate PH @@ -174,7 +174,7 @@ subroutine SETSOX( & ! (b) PARTIONING ! (c) REACTION rates ! (d) PREDICTION - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- ! use ppgrid, only : pcols, pver use chem_mods, only : gas_pcnst, nfs @@ -191,9 +191,9 @@ subroutine SETSOX( & ! implicit none ! - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- ! ... Dummy arguments - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- integer, intent(in) :: ncol ! num of columns in chunk integer, intent(in) :: lchnk ! chunk id integer, intent(in) :: loffset ! offset of chem tracers in the advected tracers array @@ -220,11 +220,11 @@ subroutine SETSOX( & real(r8), intent(out), optional :: aqso4_o3_3d(:, :) ! 3D SO4 aqueous phase chemistry due to O3 (kg/m2) - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- ! ... Local variables ! ! xhno3 ... in mixing ratio - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- integer, parameter :: itermax = 20 real(r8), parameter :: ph0 = 5.0_r8 ! INITIAL PH VALUES real(r8), parameter :: const0 = 1.e3_r8/6.023e23_r8 @@ -259,10 +259,10 @@ subroutine SETSOX( & real(r8) :: hno3g(ncol,pver), nh3g(ncol,pver) ! - !----------------------------------------------------------------------- - ! for Ho2(g) -> H2o2(a) formation + !----------------------------------------------------------------------- + ! for Ho2(g) -> H2o2(a) formation ! schwartz JGR, 1984, 11589 - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- real(r8) :: kh4 ! kh2+kh3 real(r8) :: xam ! air density /cm3 real(r8) :: ho2s ! ho2s = ho2(a)+o2- @@ -313,7 +313,7 @@ subroutine SETSOX( & xph0 = 10._r8**(-ph0) ! initial PH value do k = 1,pver - cfact(:,k) = xhnm(:,k) & ! /cm3(a) + cfact(:,k) = xhnm(:,k) & ! /cm3(a) * 1.e6_r8 & ! /m3(a) * 1.38e-23_r8/287._r8 & ! Kg(a)/m3(a) * 1.e-3_r8 ! Kg(a)/L(a) @@ -374,13 +374,13 @@ subroutine SETSOX( & if (id_msa > 0) xmsa (:,k) = qin(:,k,id_msa) end do - + !----------------------------------------------------------------- ! ... Temperature dependent Henry constants !----------------------------------------------------------------- ver_loop0: do k = 1,pver !! pver loop for STEP 0 col_loop0: do i = 1,ncol - + if (cloud_borne .and. cldfrc(i,k)>0._r8) then xso4(i,k) = xso4c(i,k) / cldfrc(i,k) xnh4(i,k) = xnh4c(i,k) / cldfrc(i,k) @@ -596,7 +596,7 @@ subroutine SETSOX( & xph(i,k) = 10.0_r8**(-yph) converged = .true. exit - else + else ! do another iteration converged = .false. end if @@ -647,9 +647,9 @@ subroutine SETSOX( & patm = press(i,k)/101300._r8 ! press is in pascal xam = press(i,k)/(1.38e-23_r8*tz) ! air density /M3 - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- ! ... hno3 - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- xk = 2.1e5_r8 *EXP( 8700._r8*work1(i) ) xe = 15.4_r8 hehno3(i,k) = xk*(1._r8 + xe/xph(i,k)) @@ -685,7 +685,7 @@ subroutine SETSOX( & heo3(i,k) = xk !------------------------------------------------------------------------ - ! ... for Ho2(g) -> H2o2(a) formation + ! ... for Ho2(g) -> H2o2(a) formation ! schwartz JGR, 1984, 11589 !------------------------------------------------------------------------ kh4 = (kh2 + kh3*kh1/xph(i,k)) / ((1._r8 + kh1/xph(i,k))**2) @@ -707,7 +707,7 @@ subroutine SETSOX( & endif !----------------------------------------------- - ! ... Partioning + ! ... Partioning !----------------------------------------------- !----------------------------------------------------------------- @@ -765,8 +765,8 @@ subroutine SETSOX( & !----------------------------------------------------------------- ! ... Prediction after aqueous phase ! so4 - ! When Cloud is present - ! + ! When Cloud is present + ! ! S(IV) + H2O2 = S(VI) ! S(IV) + O3 = S(VI) ! @@ -774,12 +774,12 @@ subroutine SETSOX( & ! (1) Seinfeld ! (2) Benkovitz !----------------------------------------------------------------- - + !............................ ! S(IV) + H2O2 = S(VI) !............................ - - IF (XL .ge. 1.e-8_r8) THEN !! WHEN CLOUD IS PRESENTED + + IF (XL .ge. 1.e-8_r8) THEN !! WHEN CLOUD IS PRESENTED if (cloud_borne) then patm_x = patm @@ -835,7 +835,7 @@ subroutine SETSOX( & xso2(i,k) = xso2(i,k) - ccc end if END IF - + if (modal_aerosols) then xdelso4hp(i,k) = xso4(i,k) - xso4_init(i,k) endif @@ -849,7 +849,7 @@ subroutine SETSOX( & * xl & ! [mole/L(a)/s] / const0 & ! [/L(a)/s] / xhnm(i,k) ! [mixing ratio/s] - + ccc = pso4*dtime ccc = max(ccc, 1.e-30_r8) @@ -872,7 +872,7 @@ subroutine SETSOX( & ncol, lchnk, loffset, dtime, mbar, pdel, press, tfld, cldnum, cldfrc, cfact, cldconc%xlwc, & xdelso4hp, xh2so4, xso4, xso4_init, nh3g, hno3g, xnh3, xhno3, xnh4c, xno3c, xmsa, xso2, xh2o2, qcw, qin, & aqso4, aqh2so4, aqso4_h2o2, aqso4_o3, aqso4_h2o2_3d=aqso4_h2o2_3d, aqso4_o3_3d=aqso4_o3_3d ) - + xphlwc(:,:) = 0._r8 do k = 1, pver do i = 1, ncol diff --git a/src/chemistry/mozart/chemistry.F90 b/src/chemistry/mozart/chemistry.F90 index b2f011549b..5e9ddaf24d 100644 --- a/src/chemistry/mozart/chemistry.F90 +++ b/src/chemistry/mozart/chemistry.F90 @@ -551,9 +551,9 @@ subroutine chem_readnl(nlfile) call aero_model_readnl(nlfile) #ifdef OSLO_AERO - call oslo_aero_dust_readnl(nlfile) + call oslo_aero_dust_readnl(nlfile) #else - call dust_readnl(nlfile) + call dust_readnl(nlfile) #endif ! call gas_wetdep_readnl(nlfile) diff --git a/src/chemistry/mozart/mo_chm_diags.F90 b/src/chemistry/mozart/mo_chm_diags.F90 index 25e2aae6e4..9e4739efba 100644 --- a/src/chemistry/mozart/mo_chm_diags.F90 +++ b/src/chemistry/mozart/mo_chm_diags.F90 @@ -443,7 +443,7 @@ subroutine chm_diags_inti end if endif end if -#endif +#endif if (spc_name(1:3) == 'num') then unit_basename = ' 1' diff --git a/src/chemistry/mozart/mo_srf_emissions.F90 b/src/chemistry/mozart/mo_srf_emissions.F90 index 5942cf41b5..e44393bcc1 100644 --- a/src/chemistry/mozart/mo_srf_emissions.F90 +++ b/src/chemistry/mozart/mo_srf_emissions.F90 @@ -12,7 +12,7 @@ module mo_srf_emissions use tracer_data, only : trfld,trfile #ifdef OSLO_AERO use oslo_aero_ocean, only: oslo_aero_dms_inq -#endif +#endif implicit none @@ -413,7 +413,7 @@ subroutine set_srf_emissions( lchnk, ncol, sflx ) #ifdef OSLO_AERO ! Zero DMS emissions if option is not "from file" ! oslo_aero_dms_inq() Returns "true" if "emissions from file" - if (.not. oslo_aero_dms_inq()) then + if (.not. oslo_aero_dms_inq()) then if (dms_ndx > 0) then sflx(:ncol,dms_ndx) = 0.0_r8 end if diff --git a/src/chemistry/mozart/mo_usrrxt.F90 b/src/chemistry/mozart/mo_usrrxt.F90 index 663d25b638..9d61bdbd06 100644 --- a/src/chemistry/mozart/mo_usrrxt.F90 +++ b/src/chemistry/mozart/mo_usrrxt.F90 @@ -3,7 +3,7 @@ module mo_usrrxt use shr_kind_mod, only : r8 => shr_kind_r8 use cam_logfile, only : iulog use ppgrid, only : pver, pcols -#ifdef OSLO_AERO +#ifdef OSLO_AERO use oslo_aero_params, only: nmodes_oslo=> nmodes #endif diff --git a/src/chemistry/pp_trop_mam_oslo/chem_mech.doc b/src/chemistry/pp_trop_mam_oslo/chem_mech.doc index 328b93a925..21b2e3ca25 100644 --- a/src/chemistry/pp_trop_mam_oslo/chem_mech.doc +++ b/src/chemistry/pp_trop_mam_oslo/chem_mech.doc @@ -1,5 +1,5 @@ - - + + |--------------------------------------------------------------------------------------------------| | | | | @@ -9,13 +9,13 @@ | | | | |--------------------------------------------------------------------------------------------------| - - + + Solution species - ( 1) SO2 - ( 2) H2SO4 + ( 1) SO2 + ( 2) H2SO4 ( 3) DMS (CH3SCH3) - ( 4) H2O2 + ( 4) H2O2 ( 5) SO4_NA (H2SO4) ( 6) SO4_A1 (H2SO4) ( 7) SO4_A2 (NH4HSO4) @@ -41,70 +41,70 @@ ( 27) SOA_SV (C10H16O2) ( 28) monoterp (C10H16) ( 29) isoprene (C5H8) - ( 30) H2O - - + ( 30) H2O + + Invariant species - ( 1) M - ( 2) N2 - ( 3) O2 - ( 4) O3 - ( 5) OH - ( 6) NO3 - ( 7) HO2 - - + ( 1) M + ( 2) N2 + ( 3) O2 + ( 4) O3 + ( 5) OH + ( 6) NO3 + ( 7) HO2 + + Column integrals ( 1) O3 - 0.000E+00 ( 2) O2 - 0.000E+00 - + Class List ========== - - Implicit + + Implicit -------- - ( 1) DMS - ( 2) SO2 - ( 3) H2O2 - ( 4) SO4_NA - ( 5) SO4_A1 - ( 6) SO4_A2 - ( 7) SO4_AC - ( 8) SO4_PR - ( 9) BC_N - ( 10) BC_AX - ( 11) BC_NI - ( 12) BC_A - ( 13) BC_AI - ( 14) BC_AC - ( 15) OM_NI - ( 16) OM_AI - ( 17) OM_AC - ( 18) DST_A2 - ( 19) DST_A3 - ( 20) SS_A1 - ( 21) SS_A2 - ( 22) SS_A3 - ( 23) H2SO4 - ( 24) SOA_NA - ( 25) SOA_A1 - ( 26) SOA_LV - ( 27) SOA_SV - ( 28) monoterp - ( 29) isoprene - ( 30) H2O - + ( 1) DMS + ( 2) SO2 + ( 3) H2O2 + ( 4) SO4_NA + ( 5) SO4_A1 + ( 6) SO4_A2 + ( 7) SO4_AC + ( 8) SO4_PR + ( 9) BC_N + ( 10) BC_AX + ( 11) BC_NI + ( 12) BC_A + ( 13) BC_AI + ( 14) BC_AC + ( 15) OM_NI + ( 16) OM_AI + ( 17) OM_AC + ( 18) DST_A2 + ( 19) DST_A3 + ( 20) SS_A1 + ( 21) SS_A2 + ( 22) SS_A3 + ( 23) H2SO4 + ( 24) SOA_NA + ( 25) SOA_A1 + ( 26) SOA_LV + ( 27) SOA_SV + ( 28) monoterp + ( 29) isoprene + ( 30) H2O + Photolysis jh2o2 ( 1) H2O2 + hv -> (No products) rate = ** User defined ** ( 1) - + Reactions usr_HO2_HO2 ( 1) HO2 + HO2 -> H2O2 rate = ** User defined ** ( 2) ( 2) H2O2 + OH -> H2O + HO2 rate = 2.90E-12*exp( -160./t) ( 3) ( 3) DMS + OH -> SO2 rate = 9.60E-12*exp( -234./t) ( 4) ( 4) DMS + NO3 -> SO2 + {HNO3} rate = 1.90E-13*exp( 520./t) ( 5) ( 5) SO2 + OH + M -> H2SO4 + M troe : ko=3.00E-31*(300/t)**3.30 ( 6) - ki=1.50E-12 - f=0.60 + ki=1.50E-12 + f=0.60 usr_DMS_OH ( 6) DMS + OH -> .75*SO2 + .5*HO2 + 0.029*SOA_LV + 0.114*SOA_SV rate = ** User defined ** ( 7) ( 7) monoterp + O3 -> .15*SOA_LV rate = 8.05E-16*exp( -640./t) ( 8) ( 8) monoterp + OH -> .15*SOA_SV rate = 1.20E-11*exp( 440./t) ( 9) @@ -112,9 +112,9 @@ Class List ( 10) isoprene + O3 -> .05*SOA_SV rate = 1.03E-14*exp( -1995./t) ( 11) ( 11) isoprene + OH -> .05*SOA_SV rate = 2.70E-11*exp( 390./t) ( 12) ( 12) isoprene + NO3 -> .05*SOA_SV rate = 3.15E-12*exp( -450./t) ( 13) - + Heterogeneous loss species - + Extraneous prod/loss species ( 1) SO2 (dataset) ( 2) BC_NI (dataset) @@ -123,40 +123,40 @@ Extraneous prod/loss species ( 5) OM_NI (dataset) ( 6) SO4_PR (dataset) ( 7) H2O (dataset) - - + + Equation Report - - d(SO2)/dt = r3*OH*DMS + r4*NO3*DMS + .75*r6*OH*DMS - - r5*OH*M*SO2 - d(H2SO4)/dt = r5*OH*M*SO2 - d(DMS)/dt = - r3*OH*DMS - r4*NO3*DMS - r6*OH*DMS - d(H2O2)/dt = r1 - - j1*H2O2 - r2*OH*H2O2 - d(SO4_NA)/dt = 0 - d(SO4_A1)/dt = 0 - d(SO4_A2)/dt = 0 - d(SO4_AC)/dt = 0 - d(SO4_PR)/dt = 0 - d(BC_N)/dt = 0 - d(BC_AX)/dt = 0 - d(BC_NI)/dt = 0 - d(BC_A)/dt = 0 - d(BC_AI)/dt = 0 - d(BC_AC)/dt = 0 - d(OM_NI)/dt = 0 - d(OM_AI)/dt = 0 - d(OM_AC)/dt = 0 - d(DST_A2)/dt = 0 - d(DST_A3)/dt = 0 - d(SS_A1)/dt = 0 - d(SS_A2)/dt = 0 - d(SS_A3)/dt = 0 - d(SOA_NA)/dt = 0 - d(SOA_A1)/dt = 0 - d(SOA_LV)/dt = .029*r6*OH*DMS + .15*r7*O3*monoterp - d(SOA_SV)/dt = .114*r6*OH*DMS + .15*r8*OH*monoterp + .15*r9*NO3*monoterp + .05*r10*O3*isoprene - + .05*r11*OH*isoprene + .05*r12*NO3*isoprene - d(monoterp)/dt = - r7*O3*monoterp - r8*OH*monoterp - r9*NO3*monoterp - d(isoprene)/dt = - r10*O3*isoprene - r11*OH*isoprene - r12*NO3*isoprene - d(H2O)/dt = r2*OH*H2O2 + + d(SO2)/dt = r3*OH*DMS + r4*NO3*DMS + .75*r6*OH*DMS + - r5*OH*M*SO2 + d(H2SO4)/dt = r5*OH*M*SO2 + d(DMS)/dt = - r3*OH*DMS - r4*NO3*DMS - r6*OH*DMS + d(H2O2)/dt = r1 + - j1*H2O2 - r2*OH*H2O2 + d(SO4_NA)/dt = 0 + d(SO4_A1)/dt = 0 + d(SO4_A2)/dt = 0 + d(SO4_AC)/dt = 0 + d(SO4_PR)/dt = 0 + d(BC_N)/dt = 0 + d(BC_AX)/dt = 0 + d(BC_NI)/dt = 0 + d(BC_A)/dt = 0 + d(BC_AI)/dt = 0 + d(BC_AC)/dt = 0 + d(OM_NI)/dt = 0 + d(OM_AI)/dt = 0 + d(OM_AC)/dt = 0 + d(DST_A2)/dt = 0 + d(DST_A3)/dt = 0 + d(SS_A1)/dt = 0 + d(SS_A2)/dt = 0 + d(SS_A3)/dt = 0 + d(SOA_NA)/dt = 0 + d(SOA_A1)/dt = 0 + d(SOA_LV)/dt = .029*r6*OH*DMS + .15*r7*O3*monoterp + d(SOA_SV)/dt = .114*r6*OH*DMS + .15*r8*OH*monoterp + .15*r9*NO3*monoterp + .05*r10*O3*isoprene + + .05*r11*OH*isoprene + .05*r12*NO3*isoprene + d(monoterp)/dt = - r7*O3*monoterp - r8*OH*monoterp - r9*NO3*monoterp + d(isoprene)/dt = - r10*O3*isoprene - r11*OH*isoprene - r12*NO3*isoprene + d(H2O)/dt = r2*OH*H2O2 diff --git a/src/physics/rrtmg/radiation.F90 b/src/physics/rrtmg/radiation.F90 index f350a8014b..d7d43e1989 100644 --- a/src/physics/rrtmg/radiation.F90 +++ b/src/physics/rrtmg/radiation.F90 @@ -557,7 +557,7 @@ subroutine radiation_init(pbuf2d) end do #ifdef OSLO_AERO - call addfld('FDSCDRF', (/ 'ilev' /), 'A', 'W/m2', 'Shortwave clear-sky downward flux') + call addfld('FDSCDRF', (/ 'ilev' /), 'A', 'W/m2', 'Shortwave clear-sky downward flux') call addfld('FUSCDRF', (/ 'ilev' /), 'A', 'W/m2', 'Shortwave clear-sky upward flux') #endif @@ -771,7 +771,7 @@ subroutine radiation_tend( & use cospsimulator_intr, only: docosp, cospsimulator_intr_run, cosp_nradsteps #ifdef OSLO_AERO - use constituents, only: pcnst + use constituents, only: pcnst use physics_buffer, only: pbuf_get_index use oslo_aero_control, only: oslo_aero_getopts use oslo_aero_params @@ -795,8 +795,8 @@ subroutine radiation_tend( & real(r8) :: volc_fraction_coarse ! Fraction of volcanic aerosols going to coarse mode integer :: band character(len=3) :: c3 - real(r8), pointer :: rvolcmmr(:,:) ! Read in stratospheric volcanoes aerosol mmr - real(r8), pointer :: volcopt(:,:) ! Read in stratospheric volcano SW optical parameter (CMIP6) + real(r8), pointer :: rvolcmmr(:,:) ! Read in stratospheric volcanoes aerosol mmr + real(r8), pointer :: volcopt(:,:) ! Read in stratospheric volcano SW optical parameter (CMIP6) #endif logical :: idrf type(rad_out_t), pointer :: rd ! allow rd_out to be optional by allocating a local object @@ -903,7 +903,7 @@ subroutine radiation_tend( & #ifdef OSLO_AERO ! Local variables used for calculating aerosol optics and direct and indirect forcings. ! aodvis and absvis are AOD and absorptive AOD for visible wavelength close to 0.55 um (0.35-0.64) - ! Note that aodvis and absvis output should be devided by dayfoc to give physical (A)AOD values + ! Note that aodvis and absvis output should be devided by dayfoc to give physical (A)AOD values integer :: ns ! spectral loop index real(r8) :: qdirind(pcols,pver,pcnst) ! Common tracers for indirect and direct calculations real(r8) :: aodvis(pcols) ! AOD vis @@ -1284,14 +1284,14 @@ subroutine radiation_tend( & if (dosw) then #ifdef OSLO_AERO - ! Volcanic optics for solar (SW) bands + ! Volcanic optics for solar (SW) bands do band = 1,nswbands volc_ext_sun(1:ncol,1:pver,band) = 0.0_r8 volc_omega_sun(1:ncol,1:pver,band) = 0.999_r8 volc_g_sun(1:ncol,1:pver,band) = 0.5_r8 enddo - ! Volcanic optics for terrestrial (LW) bands (g is not used here) + ! Volcanic optics for terrestrial (LW) bands (g is not used here) do band = 1,nlwbands volc_ext_earth(1:ncol,1:pver,band) = 0.0_r8 volc_omega_earth(1:ncol,1:pver,band) = 0.999_r8 @@ -1302,7 +1302,7 @@ subroutine radiation_tend( & call oslo_aero_optical_params_calc(lchnk, ncol, 10.0_r8*state%pint, state%pmid, & coszrs, state, state%t, cld, qdirind, Nnatk, & per_tau, per_tau_w, per_tau_w_g, per_tau_w_f, per_lw_abs, & - volc_ext_sun, volc_omega_sun, volc_g_sun, volc_ext_earth, volc_omega_earth, & + volc_ext_sun, volc_omega_sun, volc_g_sun, volc_ext_earth, volc_omega_earth, & aodvis, absvis) #endif call get_variability(sfac) @@ -1323,9 +1323,9 @@ subroutine radiation_tend( & ! aer_tau, aer_tau_w, aer_tau_w_g, aer_tau_w_f) ! A first call with Oslo aerosols set to zero for radiative forcing diagnostics ! follwoing the Ghan (2013) method: - - ! for calculation of direct radiative forcing, not necessarily "offline" as such anymore - ! (just nudged), but with an extra call with 0 aerosol extiction. + + ! for calculation of direct radiative forcing, not necessarily "offline" as such anymore + ! (just nudged), but with an extra call with 0 aerosol extiction. ! idrf = .true. call rad_rrtmg_sw( & @@ -1345,7 +1345,7 @@ subroutine radiation_tend( & ! ! Dump shortwave radiation information to history tape buffer (diagnostics) ! - ! Note that DRF fields are now from the per_tau=0 call (clean), no longer with per_tau from pmxsub + ! Note that DRF fields are now from the per_tau=0 call (clean), no longer with per_tau from pmxsub call outfld('QRS_DRF ',ftem ,pcols,lchnk) ftem(:ncol,:pver) = rd%qrsc(:ncol,:pver)/cpair call outfld('QRSC_DRF',ftem ,pcols,lchnk) @@ -1360,7 +1360,7 @@ subroutine radiation_tend( & call outfld('FSUS_DRF',ftem_1d,pcols,lchnk) call outfld('FSDSCDRF',rd%fsdsc(:) ,pcols,lchnk) end if - idrf = .false. + idrf = .false. #else call aer_rad_props_sw(icall, state, pbuf, nnite, idxnite, & aer_tau, aer_tau_w, aer_tau_w_g, aer_tau_w_f) @@ -1402,7 +1402,7 @@ subroutine radiation_tend( & end if #ifdef OSLO_AERO - !Calculate cloud-free fraction assuming random overlap + !Calculate cloud-free fraction assuming random overlap !(kind of duplicated from cloud_cover_diags::cldsav) cloudfree(1:ncol) = 1.0_r8 cloudfreemax(1:ncol) = 1.0_r8 @@ -1414,14 +1414,14 @@ subroutine radiation_tend( & end do end do - !Calculate AOD (visible) for cloud free + !Calculate AOD (visible) for cloud free do i = 1, ncol clearodvis(i)=cloudfree(i)*aodvis(i) clearabsvis(i)=cloudfree(i)*absvis(i) end do ! clear-sky AOD and absorptive AOD for visible wavelength close to 0.55 um (0.35-0.64) - ! Note that caodvis and cabsvis output should be devided by dayfoc*cloudfree to give physical (A)AOD values + ! Note that caodvis and cabsvis output should be devided by dayfoc*cloudfree to give physical (A)AOD values call outfld('CAODVIS ',clearodvis,pcols,lchnk) call outfld('CABSVIS ',clearabsvis,pcols,lchnk) call outfld('CLDFREE ',cloudfree,pcols,lchnk) @@ -1784,4 +1784,3 @@ end subroutine calc_col_mean !=============================================================================== end module radiation - From fd3a7901a1d69279d3a1e69abf59f209bbac533d Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Thu, 14 Sep 2023 11:48:08 +0200 Subject: [PATCH 09/24] updated testing and compsets --- cime_config/config_component.xml | 12 +++++++----- cime_config/config_compsets.xml | 8 ++++++++ cime_config/testdefs/testlist_cam.xml | 16 ++++++++++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml index 02ca4efc54..ae3a6a710b 100644 --- a/cime_config/config_component.xml +++ b/cime_config/config_component.xml @@ -8,12 +8,12 @@ CAM =============== --> - CAM cam6 physics: + CAM cam6 physics: CAM cam5 physics: CAM cam4 physics: CAM cam3 physics: - CAM simplified and non-versioned physics : - CAM7 development physics: + CAM simplified and non-versioned physics : + CAM7 development physics: CYCLICAL 2000 - + 'H2O -> $INPUTDATA_ROOT/atm/cam/chem/emis/elev/H2OemissionCH4oxidationx2_3D_L70_1849-2015_CMIP6ensAvg_c180927.nc', 'BC_AX -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_AX_airALL_vertical_1849-2015_0.9x1.25_version20180512.nc', 'BC_AX -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_AX_anthroprofALL_vertical_1849-2015_0.9x1.25_version20180512.nc', @@ -80,7 +80,7 @@ CYCLICAL 2000 - + 'BC_AX -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_AX_anthrosurfALL_surface_1849-2015_0.9x1.25_version20180512.nc', 'BC_N -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_N_anthrosurfALL_surface_1849-2015_0.9x1.25_version20180512.nc', 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_anthrosurfALL_surface_1849-2015_0.9x1.25_version20180512.nc', diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml index ae3a6a710b..f116f227fb 100644 --- a/cime_config/config_component.xml +++ b/cime_config/config_component.xml @@ -8,12 +8,12 @@ CAM =============== --> - CAM cam6 physics: + CAM cam6 physics: CAM cam5 physics: CAM cam4 physics: CAM cam3 physics: CAM simplified and non-versioned physics : - CAM7 development physics: + CAM7 development physics: - CAM cam6 physics: - CAM cam5 physics: - CAM cam4 physics: - CAM cam3 physics: - CAM simplified and non-versioned physics : - CAM7 development physics: + CAM cam6 physics: + CAM cam5 physics: + CAM cam4 physics: + CAM cam3 physics: + CAM simplified and non-versioned physics : + CAM7 development physics: - - NF2000climo - 2000_CAM60%NORESM_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV - - NF2000dev 2000_CAM%DEV%NORESM_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV @@ -53,6 +48,28 @@ NF2000oslo 2000_CAM%DEV%CAMoslo_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV + + NF2000tmam4 + 2000_CAM%DEV%TROPMAM4_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV + + + + NF2000LTdev + 2000_CAM%DEV%LT%NORESM_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV + + + NF2000LToslo + 2000_CAM%DEV%LT%CAMoslo_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV + + + NF2000LTtmam4 + 2000_CAM%DEV%LT%TROPMAM4_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV + + + + NF2000climo + 2000_CAM60%NORESM_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV + NF1850 From e30526ee12ff358afe76868b98e74237a4e3fea8 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Wed, 4 Oct 2023 15:35:40 +0200 Subject: [PATCH 16/24] test updates --- cime_config/config_component.xml | 4 ++-- cime_config/config_compsets.xml | 24 ++++++++++++------------ cime_config/testdefs/testlist_cam.xml | 24 ++++++++++++------------ 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml index 7a2154e9f5..2834e39509 100644 --- a/cime_config/config_component.xml +++ b/cime_config/config_component.xml @@ -146,8 +146,8 @@ -chem ghg_mam4 -chem trop_strat_mam5_vbs -camnor - -camnor -chem trop_mam4 - -camnor -chem trop_mam_oslo + -chem trop_mam4 + -chem trop_mam_oslo -chem trop_mam7 -chem trop_strat_mam5_vbsext -chem trop_strat_mam5_ts2 diff --git a/cime_config/config_compsets.xml b/cime_config/config_compsets.xml index 64d54b95bf..480d3e1273 100644 --- a/cime_config/config_compsets.xml +++ b/cime_config/config_compsets.xml @@ -42,28 +42,28 @@ NF2000dev - 2000_CAM%DEV%NORESM_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV + 2000_CAM%DEV%LT%NORESM_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV NF2000oslo - 2000_CAM%DEV%CAMoslo_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV + 2000_CAM%DEV%LT%NORESM%CAMoslo_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV - NF2000tmam4 - 2000_CAM%DEV%TROPMAM4_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV + NF2000tropmam4 + 2000_CAM%DEV%LT%NORESM%TROPMAM4_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV - NF2000LTdev - 2000_CAM%DEV%LT%NORESM_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV + NF2000devL32 + 2000_CAM%DEV%NORESM_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV - NF2000LToslo - 2000_CAM%DEV%LT%CAMoslo_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV + NF2000osloL32 + 2000_CAM%DEV%NORESM%CAMoslo_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV - NF2000LTtmam4 - 2000_CAM%DEV%LT%TROPMAM4_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV + NF2000tropmam4l32 + 2000_CAM%DEV%NORESM%TROPMAM4_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV @@ -77,7 +77,7 @@ NF1850oslo - 1850_CAM60%CAMoslo_CLM51%FATES-SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV + 1850_CAM60%NORESM%CAMoslo_CLM51%FATES-SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV @@ -86,7 +86,7 @@ NFLTHISToslo_v0d - HIST_CAM%DEV%LT%CAMoslo_CLM51%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV + HIST_CAM%DEV%LT%NORESM%CAMoslo_CLM51%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV diff --git a/cime_config/testdefs/testlist_cam.xml b/cime_config/testdefs/testlist_cam.xml index cff413ebdb..eae2c6a75c 100644 --- a/cime_config/testdefs/testlist_cam.xml +++ b/cime_config/testdefs/testlist_cam.xml @@ -10,7 +10,7 @@ - + @@ -18,7 +18,7 @@ - + @@ -27,7 +27,7 @@ - + @@ -35,7 +35,7 @@ - + @@ -46,7 +46,7 @@ - + @@ -97,7 +97,7 @@ - + @@ -107,7 +107,7 @@ - + @@ -116,7 +116,7 @@ - + From 530388d258592f2ebb0b4f9038bfcace36f69fdc Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Fri, 6 Oct 2023 11:06:35 +0200 Subject: [PATCH 17/24] simplification of how radiation interacts with oslo_aero --- src/physics/rrtmg/radiation.F90 | 59 ++++----------------------------- 1 file changed, 7 insertions(+), 52 deletions(-) diff --git a/src/physics/rrtmg/radiation.F90 b/src/physics/rrtmg/radiation.F90 index 0dca7377ab..2f7caf1ec3 100644 --- a/src/physics/rrtmg/radiation.F90 +++ b/src/physics/rrtmg/radiation.F90 @@ -44,9 +44,7 @@ module radiation use cam_logfile, only: iulog use prescribed_volcaero, only: has_prescribed_volcaero #ifdef OSLO_AERO -use prescribed_volcaero, only: has_prescribed_volcaero use oslo_aero_optical_params, only: oslo_aero_optical_params_calc -use oslo_aero_params, only: nmodes_oslo => nmodes #ifdef AEROCOM use oslo_aero_aerocom, only: dod440, dod550, dod870, abs550, abs550alt #endif @@ -153,9 +151,6 @@ module radiation integer :: cldfsnow_idx = 0 integer :: cld_idx = 0 integer :: cldfgrau_idx = 0 -#ifdef OSLO_AERO -integer :: volc_idx = 0 -#endif character(len=4) :: diag(0:N_DIAG) =(/' ','_d1 ','_d2 ','_d3 ','_d4 ','_d5 ','_d6 ','_d7 ','_d8 ','_d9 ','_d10'/) @@ -769,10 +764,6 @@ subroutine radiation_tend( & use cospsimulator_intr, only: docosp, cospsimulator_intr_run, cosp_nradsteps #ifdef OSLO_AERO - use constituents, only: pcnst - use physics_buffer, only: pbuf_get_index - use oslo_aero_control, only: oslo_aero_getopts - use oslo_aero_params use oslo_aero_share #endif @@ -789,12 +780,6 @@ subroutine radiation_tend( & ! Local variables -#ifdef OSLO_AERO - real(r8) :: volc_fraction_coarse ! Fraction of volcanic aerosols going to coarse mode - integer :: band - character(len=3) :: c3 - real(r8), pointer :: rvolcmmr(:,:) ! Read in stratospheric volcanoes aerosol mmr -#endif logical :: idrf type(rad_out_t), pointer :: rd ! allow rd_out to be optional by allocating a local object ! if the argument is not present @@ -902,9 +887,13 @@ subroutine radiation_tend( & ! aodvis and absvis are AOD and absorptive AOD for visible wavelength close to 0.55 um (0.35-0.64) ! Note that aodvis and absvis output should be devided by dayfoc to give physical (A)AOD values integer :: ns ! spectral loop index - real(r8) :: qdirind(pcols,pver,pcnst) ! Common tracers for indirect and direct calculations real(r8) :: aodvis(pcols) ! AOD vis real(r8) :: absvis(pcols) ! absorptive AOD vis + real(r8) :: per_tau (pcols,0:pver,nswbands) ! aerosol extinction optical depth + real(r8) :: per_tau_w (pcols,0:pver,nswbands) ! aerosol single scattering albedo * tau + real(r8) :: per_tau_w_g(pcols,0:pver,nswbands) ! aerosol assymetry parameter * w * tau + real(r8) :: per_tau_w_f(pcols,0:pver,nswbands) ! aerosol forward scattered fraction * w * tau + real(r8) :: per_lw_abs (pcols,pver,nlwbands) ! aerosol absorption optics depth (LW) real(r8) :: clearodvis(pcols) real(r8) :: clearabsvis(pcols) real(r8) :: cloudfree(pcols) @@ -915,17 +904,6 @@ subroutine radiation_tend( & real(r8) :: clearabs550(pcols) ! AERCOM real(r8) :: clearabs550alt(pcols) ! AERCOM real(r8) :: ftem_1d(pcols) ! work-array to avoid NAN and pcols/ncol confusion - real(r8) :: Nnatk(pcols,pver,0:nmodes) ! modal aerosol number concentration - real(r8) :: per_tau (pcols,0:pver,nswbands) ! aerosol extinction optical depth - real(r8) :: per_tau_w (pcols,0:pver,nswbands) ! aerosol single scattering albedo * tau - real(r8) :: per_tau_w_g(pcols,0:pver,nswbands) ! aerosol assymetry parameter * w * tau - real(r8) :: per_tau_w_f(pcols,0:pver,nswbands) ! aerosol forward scattered fraction * w * tau - real(r8) :: per_lw_abs (pcols,pver,nlwbands) ! aerosol absorption optics depth (LW) - real(r8) :: volc_ext_sun(pcols,pver,nswbands) ! volcanic aerosol extinction for solar bands, CMIP6 - real(r8) :: volc_omega_sun(pcols,pver,nswbands) ! volcanic aerosol SSA for solar bands, CMIP6 - real(r8) :: volc_g_sun(pcols,pver,nswbands) ! volcanic aerosol g for solar bands, CMIP6 - real(r8) :: volc_ext_earth(pcols,pver,nlwbands) ! volcanic aerosol extinction for terrestrial bands, CMIP6 - real(r8) :: volc_omega_earth(pcols,pver,nlwbands) ! volcanic aerosol SSA for terrestrial bands, CMIP6 #endif real(r8) :: fns(pcols,pverp) ! net shortwave flux @@ -1268,32 +1246,9 @@ subroutine radiation_tend( & per_tau_w_g(:,:,:) = 0._r8 per_tau_w_f(:,:,:) = 0._r8 - ! Volcanic optics for solar (SW) bands - do band=1,nswbands - volc_ext_sun(1:ncol,1:pver,band) = 0.0_r8 - volc_omega_sun(1:ncol,1:pver,band) = 0.999_r8 - volc_g_sun(1:ncol,1:pver,band) = 0.5_r8 - enddo - ! Volcanic optics for terrestrial (LW) bands (g is not used here) - do band=1,nlwbands - volc_ext_earth(1:ncol,1:pver,band) = 0.0_r8 - volc_omega_earth(1:ncol,1:pver,band) = 0.999_r8 - enddo - - qdirind(:ncol,:,:) = state%q(:ncol,:,:) - if (has_prescribed_volcaero) then - call oslo_aero_getopts(volc_fraction_coarse_out = volc_fraction_coarse) - ! TODO: Note that voc_idx here is still zero - so the following will not make any sense - call pbuf_get_field(pbuf, volc_idx, rvolcmmr, start=(/1,1,itim_old/), kount=(/pcols,pver,1/) ) - qdirind(:ncol,:,l_so4_pr) = qdirind(:ncol,:,l_so4_pr) + (1.0_r8 - volc_fraction_coarse)*rvolcmmr(:ncol,:) - qdirind(:ncol,:,l_ss_a3) = qdirind(:ncol,:,l_ss_a3) + volc_fraction_coarse*rvolcmmr(:ncol,:) - end if - call oslo_aero_optical_params_calc(lchnk, ncol, 10.0_r8*state%pint, state%pmid, & - coszrs, state, state%t, cld, qdirind, Nnatk, & - per_tau, per_tau_w, per_tau_w_g, per_tau_w_f, per_lw_abs, & - volc_ext_sun, volc_omega_sun, volc_g_sun, volc_ext_earth, volc_omega_earth, & - aodvis, absvis) + coszrs, pbuf, state, state%t, cld, & + per_tau, per_tau_w, per_tau_w_g, per_tau_w_f, per_lw_abs, aodvis, absvis) call get_variability(sfac) From 4a851dc0a5be30fa4374b04f44a5344a8ea14cbc Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Fri, 6 Oct 2023 12:06:08 +0200 Subject: [PATCH 18/24] fixed bug in radiation.F90 --- src/physics/rrtmg/radiation.F90 | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/physics/rrtmg/radiation.F90 b/src/physics/rrtmg/radiation.F90 index 2f7caf1ec3..d7d90350a5 100644 --- a/src/physics/rrtmg/radiation.F90 +++ b/src/physics/rrtmg/radiation.F90 @@ -763,9 +763,6 @@ subroutine radiation_tend( & use tropopause, only: tropopause_find, TROP_ALG_HYBSTOB, TROP_ALG_CLIMATE use cospsimulator_intr, only: docosp, cospsimulator_intr_run, cosp_nradsteps -#ifdef OSLO_AERO - use oslo_aero_share -#endif ! Arguments type(physics_state), intent(in), target :: state @@ -886,14 +883,13 @@ subroutine radiation_tend( & ! Local variables used for calculating aerosol optics and direct and indirect forcings. ! aodvis and absvis are AOD and absorptive AOD for visible wavelength close to 0.55 um (0.35-0.64) ! Note that aodvis and absvis output should be devided by dayfoc to give physical (A)AOD values - integer :: ns ! spectral loop index - real(r8) :: aodvis(pcols) ! AOD vis - real(r8) :: absvis(pcols) ! absorptive AOD vis real(r8) :: per_tau (pcols,0:pver,nswbands) ! aerosol extinction optical depth real(r8) :: per_tau_w (pcols,0:pver,nswbands) ! aerosol single scattering albedo * tau real(r8) :: per_tau_w_g(pcols,0:pver,nswbands) ! aerosol assymetry parameter * w * tau real(r8) :: per_tau_w_f(pcols,0:pver,nswbands) ! aerosol forward scattered fraction * w * tau real(r8) :: per_lw_abs (pcols,pver,nlwbands) ! aerosol absorption optics depth (LW) + real(r8) :: aodvis(pcols) ! AOD vis + real(r8) :: absvis(pcols) ! absorptive AOD vis real(r8) :: clearodvis(pcols) real(r8) :: clearabsvis(pcols) real(r8) :: cloudfree(pcols) @@ -1302,15 +1298,9 @@ subroutine radiation_tend( & call outfld('FSDSCDRF',rd%fsdsc(:) ,pcols,lchnk) #endif idrf = .false. - - rd%cld_tau_cloudsim(:ncol,:) = cld_tau(rrtmg_sw_cloudsim_band,:ncol,:) - rd%aer_tau550(:ncol,:) = aer_tau(:ncol,:,idx_sw_diag) - rd%aer_tau400(:ncol,:) = aer_tau(:ncol,:,idx_sw_diag+1) - rd%aer_tau700(:ncol,:) = aer_tau(:ncol,:,idx_sw_diag-1) - call rad_rrtmg_sw( & lchnk, ncol, num_rrtmg_levs, r_state, state%pmid, & - cldfprime, aer_tau, aer_tau_w, aer_tau_w_g, aer_tau_w_f, & + cldfprime, per_tau, per_tau_w, per_tau_w_g, per_tau_w_f, & eccf, coszrs, rd%solin, sfac, cam_in%asdir, & cam_in%asdif, cam_in%aldir, cam_in%aldif, qrs, rd%qrsc, & fsnt, rd%fsntc, rd%fsntoa, rd%fsutoa, rd%fsntoac, & From 793f22e8f34ada2b52d145ec4ee0e29bd58276bc Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Fri, 6 Oct 2023 12:52:34 +0200 Subject: [PATCH 19/24] moved all files with OSLO_AERO ifdefs to src/chemistry/oslo_aero/src_cam and reset files to the original noresm_develop versions --- bld/configure | 4 + src/chemistry/aerosol/mo_setsox.F90 | 88 +++---- src/chemistry/mozart/chemistry.F90 | 34 +-- src/chemistry/mozart/mo_chm_diags.F90 | 188 +------------- src/chemistry/mozart/mo_drydep.F90 | 5 +- src/chemistry/mozart/mo_gas_phase_chemdr.F90 | 70 +---- src/chemistry/mozart/mo_neu_wetdep.F90 | 21 +- src/chemistry/mozart/mo_setaer.F90 | 6 +- src/chemistry/mozart/mo_srf_emissions.F90 | 20 +- src/chemistry/mozart/mo_usrrxt.F90 | 12 +- src/physics/cam/vertical_diffusion.F90 | 38 +-- src/physics/cam/zm_microphysics.F90 | 2 - src/physics/rrtmg/radiation.F90 | 254 +------------------ src/physics/rrtmg/radlw.F90 | 4 - src/physics/rrtmg/radsw.F90 | 21 +- 15 files changed, 89 insertions(+), 678 deletions(-) diff --git a/bld/configure b/bld/configure index f5680006fa..06446ef39b 100755 --- a/bld/configure +++ b/bld/configure @@ -2102,6 +2102,10 @@ sub write_filepath } } + if ($chem =~/_oslo/) { + print $fh "$camsrcdir/src/chemistry/oslo_aero/src_cam\n"; + } + # offline unit driver (defaults to stub) print $fh "$camsrcdir/src/unit_drivers\n"; print $fh "$camsrcdir/src/unit_drivers/${offline_drv}\n"; diff --git a/src/chemistry/aerosol/mo_setsox.F90 b/src/chemistry/aerosol/mo_setsox.F90 index 3a7708bc28..b994e32dd2 100644 --- a/src/chemistry/aerosol/mo_setsox.F90 +++ b/src/chemistry/aerosol/mo_setsox.F90 @@ -23,36 +23,30 @@ module MO_SETSOX contains -!----------------------------------------------------------------------- -!----------------------------------------------------------------------- +!----------------------------------------------------------------------- +!----------------------------------------------------------------------- subroutine sox_inti - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- ! ... initialize the hetero sox routine - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- use mo_chem_utls, only : get_spc_ndx, get_inv_ndx use spmd_utils, only : masterproc use phys_control, only : phys_getopts -#ifdef OSLO_AERO - use oslo_aero_sox_cldaero, only : sox_cldaero_init -#else use sox_cldaero_mod, only : sox_cldaero_init -#endif implicit none -#ifdef OSLO_AERO - modal_aerosols = .true. - cloud_borne = .true. -#else - call phys_getopts(prog_modal_aero_out=modal_aerosols ) + + call phys_getopts( & + prog_modal_aero_out=modal_aerosols ) + cloud_borne = modal_aerosols -#endif !----------------------------------------------------------------- ! ... get species indicies !----------------------------------------------------------------- - + if (cloud_borne) then id_h2so4 = get_spc_ndx( 'H2SO4' ) else @@ -125,16 +119,16 @@ subroutine sox_inti write(iulog,*) 'mozart will do sox aerosols' write(iulog,*) '-----------------------------------------' endif - else + else return end if call sox_cldaero_init() end subroutine sox_inti - -!----------------------------------------------------------------------- -!----------------------------------------------------------------------- + +!----------------------------------------------------------------------- +!----------------------------------------------------------------------- subroutine SETSOX( & ncol, & lchnk, & @@ -161,7 +155,7 @@ subroutine SETSOX( & aqso4_o3_3d & ) - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- ! ... Compute heterogeneous reactions of SOX ! ! (0) using initial PH to calculate PH @@ -174,26 +168,22 @@ subroutine SETSOX( & ! (b) PARTIONING ! (c) REACTION rates ! (d) PREDICTION - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- ! use ppgrid, only : pcols, pver use chem_mods, only : gas_pcnst, nfs use chem_mods, only : adv_mass use physconst, only : mwdry, gravit use mo_constants, only : pi -#ifdef OSLO_AERO - use oslo_aero_sox_cldaero, only : sox_cldaero_update, sox_cldaero_create_obj, sox_cldaero_destroy_obj - use oslo_aero_sox_cldaero, only : cldaero_conc_t -#else use sox_cldaero_mod, only : sox_cldaero_update, sox_cldaero_create_obj, sox_cldaero_destroy_obj use cldaero_mod, only : cldaero_conc_t -#endif + ! implicit none ! - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- ! ... Dummy arguments - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- integer, intent(in) :: ncol ! num of columns in chunk integer, intent(in) :: lchnk ! chunk id integer, intent(in) :: loffset ! offset of chem tracers in the advected tracers array @@ -220,11 +210,11 @@ subroutine SETSOX( & real(r8), intent(out), optional :: aqso4_o3_3d(:, :) ! 3D SO4 aqueous phase chemistry due to O3 (kg/m2) - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- ! ... Local variables ! ! xhno3 ... in mixing ratio - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- integer, parameter :: itermax = 20 real(r8), parameter :: ph0 = 5.0_r8 ! INITIAL PH VALUES real(r8), parameter :: const0 = 1.e3_r8/6.023e23_r8 @@ -259,10 +249,10 @@ subroutine SETSOX( & real(r8) :: hno3g(ncol,pver), nh3g(ncol,pver) ! - !----------------------------------------------------------------------- - ! for Ho2(g) -> H2o2(a) formation + !----------------------------------------------------------------------- + ! for Ho2(g) -> H2o2(a) formation ! schwartz JGR, 1984, 11589 - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- real(r8) :: kh4 ! kh2+kh3 real(r8) :: xam ! air density /cm3 real(r8) :: ho2s ! ho2s = ho2(a)+o2- @@ -313,7 +303,7 @@ subroutine SETSOX( & xph0 = 10._r8**(-ph0) ! initial PH value do k = 1,pver - cfact(:,k) = xhnm(:,k) & ! /cm3(a) + cfact(:,k) = xhnm(:,k) & ! /cm3(a) * 1.e6_r8 & ! /m3(a) * 1.38e-23_r8/287._r8 & ! Kg(a)/m3(a) * 1.e-3_r8 ! Kg(a)/L(a) @@ -374,13 +364,13 @@ subroutine SETSOX( & if (id_msa > 0) xmsa (:,k) = qin(:,k,id_msa) end do - + !----------------------------------------------------------------- ! ... Temperature dependent Henry constants !----------------------------------------------------------------- ver_loop0: do k = 1,pver !! pver loop for STEP 0 col_loop0: do i = 1,ncol - + if (cloud_borne .and. cldfrc(i,k)>0._r8) then xso4(i,k) = xso4c(i,k) / cldfrc(i,k) xnh4(i,k) = xnh4c(i,k) / cldfrc(i,k) @@ -596,7 +586,7 @@ subroutine SETSOX( & xph(i,k) = 10.0_r8**(-yph) converged = .true. exit - else + else ! do another iteration converged = .false. end if @@ -647,9 +637,9 @@ subroutine SETSOX( & patm = press(i,k)/101300._r8 ! press is in pascal xam = press(i,k)/(1.38e-23_r8*tz) ! air density /M3 - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- ! ... hno3 - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- xk = 2.1e5_r8 *EXP( 8700._r8*work1(i) ) xe = 15.4_r8 hehno3(i,k) = xk*(1._r8 + xe/xph(i,k)) @@ -685,7 +675,7 @@ subroutine SETSOX( & heo3(i,k) = xk !------------------------------------------------------------------------ - ! ... for Ho2(g) -> H2o2(a) formation + ! ... for Ho2(g) -> H2o2(a) formation ! schwartz JGR, 1984, 11589 !------------------------------------------------------------------------ kh4 = (kh2 + kh3*kh1/xph(i,k)) / ((1._r8 + kh1/xph(i,k))**2) @@ -707,7 +697,7 @@ subroutine SETSOX( & endif !----------------------------------------------- - ! ... Partioning + ! ... Partioning !----------------------------------------------- !----------------------------------------------------------------- @@ -765,8 +755,8 @@ subroutine SETSOX( & !----------------------------------------------------------------- ! ... Prediction after aqueous phase ! so4 - ! When Cloud is present - ! + ! When Cloud is present + ! ! S(IV) + H2O2 = S(VI) ! S(IV) + O3 = S(VI) ! @@ -774,12 +764,12 @@ subroutine SETSOX( & ! (1) Seinfeld ! (2) Benkovitz !----------------------------------------------------------------- - + !............................ ! S(IV) + H2O2 = S(VI) !............................ - - IF (XL .ge. 1.e-8_r8) THEN !! WHEN CLOUD IS PRESENTED + + IF (XL .ge. 1.e-8_r8) THEN !! WHEN CLOUD IS PRESENTED if (cloud_borne) then patm_x = patm @@ -835,7 +825,7 @@ subroutine SETSOX( & xso2(i,k) = xso2(i,k) - ccc end if END IF - + if (modal_aerosols) then xdelso4hp(i,k) = xso4(i,k) - xso4_init(i,k) endif @@ -849,7 +839,7 @@ subroutine SETSOX( & * xl & ! [mole/L(a)/s] / const0 & ! [/L(a)/s] / xhnm(i,k) ! [mixing ratio/s] - + ccc = pso4*dtime ccc = max(ccc, 1.e-30_r8) @@ -872,7 +862,7 @@ subroutine SETSOX( & ncol, lchnk, loffset, dtime, mbar, pdel, press, tfld, cldnum, cldfrc, cfact, cldconc%xlwc, & xdelso4hp, xh2so4, xso4, xso4_init, nh3g, hno3g, xnh3, xhno3, xnh4c, xno3c, xmsa, xso2, xh2o2, qcw, qin, & aqso4, aqh2so4, aqso4_h2o2, aqso4_o3, aqso4_h2o2_3d=aqso4_h2o2_3d, aqso4_o3_3d=aqso4_o3_3d ) - + xphlwc(:,:) = 0._r8 do k = 1, pver do i = 1, ncol diff --git a/src/chemistry/mozart/chemistry.F90 b/src/chemistry/mozart/chemistry.F90 index 5e9ddaf24d..ff42e870d9 100644 --- a/src/chemistry/mozart/chemistry.F90 +++ b/src/chemistry/mozart/chemistry.F90 @@ -163,11 +163,7 @@ subroutine chem_register use cfc11star, only : register_cfc11star use mo_photo, only : photo_register use mo_aurora, only : aurora_register -#ifdef OSLO_AERO - use oslo_aero_model, only : aero_model_register -#else use aero_model, only : aero_model_register -#endif use physics_buffer, only : pbuf_add_field, dtype_r8 use upper_bc, only : ubc_fixed_conc @@ -337,13 +333,8 @@ subroutine chem_readnl(nlfile) use tracer_cnst, only: tracer_cnst_defaultopts, tracer_cnst_setopts use tracer_srcs, only: tracer_srcs_defaultopts, tracer_srcs_setopts -#ifdef OSLO_AERO - use oslo_aero_model, only: aero_model_readnl - use oslo_aero_dust, only: oslo_aero_dust_readnl -#else use aero_model, only: aero_model_readnl use dust_model, only: dust_readnl -#endif use gas_wetdep_opts, only: gas_wetdep_readnl use mo_drydep, only: drydep_srf_file use mo_sulf, only: sulf_readnl @@ -550,11 +541,7 @@ subroutine chem_readnl(nlfile) tracer_srcs_fixed_tod_in = tracer_srcs_fixed_tod ) call aero_model_readnl(nlfile) -#ifdef OSLO_AERO - call oslo_aero_dust_readnl(nlfile) -#else call dust_readnl(nlfile) -#endif ! call gas_wetdep_readnl(nlfile) call gcr_ionization_readnl(nlfile) @@ -649,11 +636,7 @@ subroutine chem_init(phys_state, pbuf2d) use infnan, only : nan, assignment(=) use mo_chem_utls, only : get_spc_ndx use cam_abortutils, only : endrun -#ifdef OSLO_AERO - use oslo_aero_model, only : aero_model_init -#else use aero_model, only : aero_model_init -#endif use mo_setsox, only : sox_inti use constituents, only : sflxnam use fire_emissions, only : fire_emissions_init @@ -845,13 +828,8 @@ subroutine chem_init(phys_state, pbuf2d) contains pure logical function aero_has_emis(spcname) -#ifdef OSLO_AERO - use oslo_aero_seasalt, only: seasalt_names - use oslo_aero_dust, only: dust_names -#else - use seasalt_model, only : seasalt_names + use seasalt_model, only: seasalt_names use dust_model, only: dust_names -#endif character(len=*),intent(in) :: spcname @@ -865,11 +843,7 @@ end subroutine chem_init !================================================================================ subroutine chem_emissions( state, cam_in, pbuf ) use physics_buffer, only: physics_buffer_desc -#ifdef OSLO_AERO - use oslo_aero_model, only: aero_model_emissions -#else use aero_model, only: aero_model_emissions -#endif use camsrfexch, only: cam_in_t use constituents, only: sflxnam use cam_history, only: outfld @@ -950,12 +924,8 @@ subroutine chem_emissions( state, cam_in, pbuf ) ! fire surface emissions if not elevated forcing call fire_emissions_srf( lchnk, ncol, cam_in%fireflx, cam_in%cflx ) -#ifndef OSLO_AERO - ! TODO oslo_aero: should this be added to OSLO_AERO - there was - ! not a pre-existing ocean salinity file capability air-sea - ! exchange of trace gases + ! air-sea exchange of trace gases call ocean_emis_getflux(lchnk, ncol, state, cam_in%u10, cam_in%sst, cam_in%ocnfrac, cam_in%icefrac, cam_in%cflx) -#endif end subroutine chem_emissions diff --git a/src/chemistry/mozart/mo_chm_diags.F90 b/src/chemistry/mozart/mo_chm_diags.F90 index a1c4108c51..5650403fee 100644 --- a/src/chemistry/mozart/mo_chm_diags.F90 +++ b/src/chemistry/mozart/mo_chm_diags.F90 @@ -11,14 +11,6 @@ module mo_chm_diags use mo_jeuv, only : neuv use gas_wetdep_opts,only : gas_wetdep_method use mo_drydep, only : has_drydep - ! - use ppgrid, only : pcols ! OSLO_AERO - use physics_buffer, only : pbuf_get_field, pbuf_get_index, physics_buffer_desc ! OSLO_AERO - use constituents, only : cnst_get_ind ! OSLO_AERO -#ifdef OSLO_AERO - use oslo_aero_share, only : getCloudTracerIndexDirect, getCloudTracerName, aerosolType, isAerosol - use oslo_aero_params -#endif implicit none private @@ -59,7 +51,7 @@ module mo_chm_diags character(len=fieldname_len) :: depflx_name(gas_pcnst) character(len=fieldname_len) :: wetdep_name(gas_pcnst) character(len=fieldname_len) :: wtrate_name(gas_pcnst) - character(len=fieldname_len) :: wetdep_name_area(gas_pcnst) ! OSLO_AERO + real(r8), parameter :: N_molwgt = 14.00674_r8 real(r8), parameter :: S_molwgt = 32.066_r8 @@ -112,8 +104,7 @@ subroutine chm_diags_inti logical :: history_chemspecies_srf ! output the chemistry constituents species in the surface layer logical :: history_dust integer :: bulkaero_species(20) - integer :: cloudTracerIndex ! OSLO_AERO - character(len=20) :: cloudTracerName ! OSLO_AERO + !----------------------------------------------------------------------- call phys_getopts( history_aerosol_out = history_aerosol, & @@ -432,40 +423,12 @@ subroutine chm_diags_inti call addfld( wtrate_name(m), (/ 'lev' /), 'A', '/s', spc_name//' wet deposition rate' ) endif -#ifdef OSLO_AERO - wetdep_name_area(m)='WD_A_'//trim(spc_name) - call addfld( wetdep_name_area(m), horiz_only, 'A', 'kg/m2/s ', spc_name//' wet deposition' ) - - !Needed for budget term of gases! Aerosols have their own budget terms - if(n.gt.0) then - if(.NOT. isAerosol(n))then - if(history_chemistry)then - call add_default( wetdep_name_area(m), 1, ' ') - end if - endif - end if -#endif - if (spc_name(1:3) == 'num') then unit_basename = ' 1' else unit_basename = 'kg' endif -#ifdef OSLO_AERO - if (n.gt.0) then - if ( any( aer_species == m ) .or. isAerosol(n) ) then - call addfld( spc_name, (/ 'lev' /), 'A', unit_basename//'/kg ', trim(attr)//' concentration') - call addfld( trim(spc_name)//'_SRF', horiz_only, 'A', unit_basename//'/kg', trim(attr)//" in bottom layer") - else - call addfld( spc_name, (/ 'lev' /), 'A', 'mol/mol', trim(attr)//' concentration') - call addfld( trim(spc_name)//'_SRF', horiz_only, 'A', 'mol/mol', trim(attr)//" in bottom layer") - endif - else - call addfld( spc_name, (/ 'lev' /), 'A', 'mol/mol', trim(attr)//' concentration') - call addfld( trim(spc_name)//'_SRF', horiz_only, 'A', 'mol/mol', trim(attr)//" in bottom layer") - endif -#else if ( any( aer_species == m ) ) then call addfld( spc_name, (/ 'lev' /), 'A', unit_basename//'/kg ', trim(attr)//' concentration') call addfld( trim(spc_name)//'_SRF', horiz_only, 'A', unit_basename//'/kg', trim(attr)//" in bottom layer") @@ -473,7 +436,7 @@ subroutine chm_diags_inti call addfld( spc_name, (/ 'lev' /), 'A', 'mol/mol', trim(attr)//' concentration') call addfld( trim(spc_name)//'_SRF', horiz_only, 'A', 'mol/mol', trim(attr)//" in bottom layer") endif -#endif + if ((m /= id_cly) .and. (m /= id_bry)) then if (history_aerosol.or.history_chemistry) then call add_default( spc_name, 1, ' ' ) @@ -514,63 +477,13 @@ subroutine chm_diags_inti if (m==id_cfc12 ) call add_default( spc_name, 1, ' ') endif -#ifdef OSLO_AERO - call add_default( spc_name, 1, ' ' ) - - ! output 3d-field of aersol tracer in cloud water - if (n > 0) then - cloudTracerIndex = getCloudTracerIndexDirect(n) - if(cloudTracerIndex > 0)then - cloudTracerName(1:len(CloudTracerName))=" " - cloudTracerName = getCloudTracerName(n) - call addfld( trim(cloudTracerName), (/'lev'/), 'A','kg/kg', & - trim(cloudTracerName)//' in cloud water') - call add_default( trim(cloudTracerName), 1, ' ' ) - - !Add column burden of cloud tracers - call addfld('cb_'//trim(cloudTracerName),horiz_only, 'A', 'kg/m2', & - 'cb_'//trim(cloudTracerName)//' column in cloud water') - call add_default('cb_'//trim(cloudTracerName),1,' ') - endif - !..and column burden in clean air - call addfld('cb_'//trim(spc_name),horiz_only, 'A', 'kg/m2', & - 'cb_'//trim(spc_name)//' in column') - call add_default('cb_'//trim(spc_name),1,' ' ) - - if (history_aerosol) then - if (cloudTracerIndex > 0) then - !Output budget-terms for cloud borne aerosols - call add_default (trim(cloudTracerName)//'GVF' , 1, ' ') - call add_default (trim(cloudTracerName)//'SFWET' , 1, ' ') - call add_default (trim(cloudTracerName)//'TBF' , 1, ' ') - call add_default (trim(cloudTracerName)//'DDF' , 1, ' ') - call add_default (trim(cloudTracerName)//'SFSBS' , 1, ' ') - call add_default (trim(cloudTracerName)//'SFSIC' , 1, ' ') - call add_default (trim(cloudTracerName)//'SFSBC' , 1, ' ') - call add_default (trim(cloudTracerName)//'SFSIS' , 1, ' ') - endif - endif - end if -#else - if (history_dust .and. (index(spc_name,'dst_') > 0)) call add_default( spc_name, 1, ' ') -#endif enddo call addfld( 'MASS', (/ 'lev' /), 'A', 'kg', 'mass of grid box' ) call addfld( 'AREA', horiz_only, 'A', 'm2', 'area of grid box' ) -#ifdef OSLO_AERO - do n=1,N_AEROSOL_TYPES - call addfld('cb_'//trim(aerosol_type_name(n)),horiz_only, 'A', 'kg/m2',& - 'cb_'//trim(aerosol_type_name(n))//' column of aerosol type') - call add_default('cb_'//trim(aerosol_type_name(n)), 1, ' ') - - call addfld('mmr_'//trim(aerosol_type_name(n)),(/'lev'/),'A','kg/kg' ,& - 'mmr_'//trim(aerosol_type_name(n))//' mmr of aerosol type') - call add_default('mmr_'//trim(aerosol_type_name(n)), 1, ' ') - end do -#endif + call addfld( 'dry_deposition_NOy_as_N', horiz_only, 'I', 'kg/m2/s', 'NOy dry deposition flux ' ) call addfld( 'DF_SOX', horiz_only, 'I', 'kg/m2/s', 'SOx dry deposition flux ' ) call addfld( 'dry_deposition_NHx_as_N', horiz_only, 'I', 'kg/m2/s', 'NHx dry deposition flux ' ) @@ -593,13 +506,8 @@ subroutine chm_diags_inti end subroutine chm_diags_inti -#ifdef OSLO_AERO - subroutine chm_diags( lchnk, ncol, vmr, mmr, rxt_rates, invariants, depvel, depflx, mmr_tend, pdel, pmid, ltrop, & - wetdepflx, nhx_nitrogen_flx, noy_nitrogen_flx, pbuf) -#else subroutine chm_diags( lchnk, ncol, vmr, mmr, rxt_rates, invariants, depvel, depflx, mmr_tend, pdel, pmid, ltrop, & wetdepflx, nhx_nitrogen_flx, noy_nitrogen_flx ) -#endif !-------------------------------------------------------------------- ! ... utility routine to output chemistry diagnostic variables !-------------------------------------------------------------------- @@ -630,24 +538,11 @@ subroutine chm_diags( lchnk, ncol, vmr, mmr, rxt_rates, invariants, depvel, depf real(r8), intent(in) :: wetdepflx(ncol, gas_pcnst) real(r8), intent(out) :: nhx_nitrogen_flx(ncol) ! kgN/m2/sec real(r8), intent(out) :: noy_nitrogen_flx(ncol) ! kgN/m2/sec -#ifdef OSLO_AERO - type(physics_buffer_desc), pointer :: pbuf(:) -#endif !-------------------------------------------------------------------- ! ... local variables !-------------------------------------------------------------------- -#ifdef OSLO_AERO - real(r8), pointer :: cloudTracerField(:,:) - integer :: cloudTracerIndex - character(len=20) :: cloudTracerName - real(r8) :: mass_tmp(pcols,pver) - real(r8) :: cb(pcols) - real(r8) :: cb_aerosol_type(pcols,N_AEROSOL_TYPES) !column burden aerosol types - real(r8) :: mmr_aerosol_type(pcols,pver,N_AEROSOL_TYPES) !concentration aerosol types - character(len=16) :: spc_name -#endif - integer :: i, k, m, n + integer :: i, k, m real(r8) :: wrk(ncol,pver) ! real(r8) :: tmp(ncol,pver) ! real(r8) :: m(ncol,pver) @@ -698,11 +593,6 @@ subroutine chm_diags( lchnk, ncol, vmr, mmr, rxt_rates, invariants, depvel, depf call outfld( 'AREA', area(:ncol), ncol, lchnk ) call outfld( 'MASS', mass(:ncol,:), ncol, lchnk ) -#ifdef OSLO_AERO - cb_aerosol_type(:,:) = 0.0_r8 - mmr_aerosol_type(:,:,:) = 0.0_r8 -#endif - do m = 1,gas_pcnst !...FOY (counting Fluorines, not chlorines or bromines) @@ -785,49 +675,6 @@ subroutine chm_diags( lchnk, ncol, vmr, mmr, rxt_rates, invariants, depvel, depf vmr_hox(:ncol,:) = vmr_hox(:ncol,:) + wgt * vmr(:ncol,:,m) endif -#ifdef OSLO_AERO - spc_name = trim(solsym(m)) - call cnst_get_ind(spc_name, n, abort=.false.) - - if (n.gt.0) then - if ( any( aer_species == m ) .or. isAerosol(n) ) then - call outfld( solsym(m), mmr(:ncol,:,m), ncol ,lchnk ) - call outfld( trim(solsym(m))//'_SRF', mmr(:ncol,pver,m), ncol ,lchnk ) - else - call outfld( solsym(m), vmr(:ncol,:,m), ncol ,lchnk ) - call outfld( trim(solsym(m))//'_SRF', vmr(:ncol,pver,m), ncol ,lchnk ) - endif - else - call outfld( solsym(m), vmr(:ncol,:,m), ncol ,lchnk ) - call outfld( trim(solsym(m))//'_SRF', vmr(:ncol,pver,m), ncol ,lchnk ) - end if - - if (n > 0) then - cloudTracerIndex = getCloudTracerIndexDirect(n) - if(cloudTracerIndex > 0)then - cloudTracerName = getCloudTracerName(n) - call pbuf_get_field(pbuf, cloudTracerIndex, cloudTracerField ) - call outfld ( trim(cloudTracerName), cloudTracerField, pcols, lchnk) - - ! Treat column burden (cloud tracer) - mass_tmp(:ncol,:) = cloudTracerField(:ncol,:) *pdel(:ncol,:) * rgrav - cb(:ncol) = sum(mass_tmp(:ncol,:),2) - call outfld(trim('cb_'//trim(cloudTracerName)), cb, pcols, lchnk) - endif - - ! Treat column burden (normal tracer) - mass_tmp(:ncol,:) = mmr(:ncol,:,m) * pdel(:ncol,:) * rgrav - cb(:ncol) = sum(mass_tmp(:ncol,:),2) - call outfld(trim('cb_'//trim(spc_name)), cb, pcols, lchnk) - - !Sum column burden per aerosol type - if (aerosolType(n) > 0) then - cb_aerosol_type(:ncol,aerosolType(n)) = cb_aerosol_type(:ncol,aerosolType(n)) + cb(:ncol) - !Total mass mixing ratio of aerosol type - mmr_aerosol_type(:ncol,:,aerosolType(n)) = mmr_aerosol_type(:ncol,:,aerosolType(n)) + mmr(:ncol,:,m) - endif - end if !Check if this is a chemistry tracer -#else if ( any( aer_species == m ) ) then call outfld( solsym(m), mmr(:ncol,:,m), ncol ,lchnk ) call outfld( trim(solsym(m))//'_SRF', mmr(:ncol,pver,m), ncol ,lchnk ) @@ -835,7 +682,6 @@ subroutine chm_diags( lchnk, ncol, vmr, mmr, rxt_rates, invariants, depvel, depf call outfld( solsym(m), vmr(:ncol,:,m), ncol ,lchnk ) call outfld( trim(solsym(m))//'_SRF', vmr(:ncol,pver,m), ncol ,lchnk ) endif -#endif if (has_drydep(solsym(m))) then call outfld( depvel_name(m), depvel(:ncol,m), ncol ,lchnk ) @@ -903,12 +749,8 @@ subroutine chm_diags( lchnk, ncol, vmr, mmr, rxt_rates, invariants, depvel, depf end if ! enddo -#ifdef OSLO_AERO - do n=1,N_AEROSOL_TYPES - call outfld("mmr_"//trim(aerosol_type_name(n)), mmr_aerosol_type(:ncol,:,n), ncol,lchnk) - call outfld("cb_"//trim(aerosol_type_name(n)) , cb_aerosol_type(:ncol,n) , ncol,lchnk) - enddo -#endif + + call outfld( 'NOX', vmr_nox (:ncol,:), ncol, lchnk ) call outfld( 'NOY', vmr_noy (:ncol,:), ncol, lchnk ) call outfld( 'HOX', vmr_hox (:ncol,:), ncol, lchnk ) @@ -1038,11 +880,7 @@ end subroutine chm_diags subroutine het_diags( het_rates, mmr, pdel, lchnk, ncol ) use cam_history, only : outfld -#ifdef OSLO_AERO - use phys_grid, only : get_wght_all_p, get_area_all_p -#else use phys_grid, only : get_wght_all_p -#endif integer, intent(in) :: lchnk integer, intent(in) :: ncol @@ -1051,9 +889,6 @@ subroutine het_diags( het_rates, mmr, pdel, lchnk, ncol ) real(r8), intent(in) :: pdel(ncol,pver) real(r8), dimension(ncol) :: noy_wk, sox_wk, nhx_wk, wrk_wd -#ifdef OSLO_AERO - real(r8), dimension(ncol) :: area -#endif integer :: m, k real(r8) :: wght(ncol) ! @@ -1063,10 +898,6 @@ subroutine het_diags( het_rates, mmr, pdel, lchnk, ncol ) sox_wk(:) = 0._r8 nhx_wk(:) = 0._r8 -#ifdef OSLO_AERO - call get_area_all_p(lchnk, ncol, area) - area = area * rearth**2 -#endif call get_wght_all_p(lchnk, ncol, wght) do m = 1,gas_pcnst @@ -1081,10 +912,7 @@ subroutine het_diags( het_rates, mmr, pdel, lchnk, ncol ) wrk_wd(:ncol) = wrk_wd(:ncol) * rgrav * wght(:ncol) * rearth**2 ! if (gas_wetdep_method=='MOZ') then - call outfld( wetdep_name(m), wrk_wd(:ncol), ncol, lchnk ) -#ifdef OSLO_AERO - call outfld( wetdep_name_area(m), wrk_wd(:ncol)/area(:ncol) ,ncol, lchnk ) -#endif + call outfld( wetdep_name(m), wrk_wd(:ncol), ncol, lchnk ) call outfld( wtrate_name(m), het_rates(:ncol,:,m), ncol, lchnk ) if ( any(noy_species == m ) ) then diff --git a/src/chemistry/mozart/mo_drydep.F90 b/src/chemistry/mozart/mo_drydep.F90 index 68a7e6ec07..a44db8416e 100644 --- a/src/chemistry/mozart/mo_drydep.F90 +++ b/src/chemistry/mozart/mo_drydep.F90 @@ -322,11 +322,8 @@ subroutine dvel_inti_xactive( depvel_lnd_file ) logical :: prog_modal_aero ! determine if modal aerosols are active so that fraction_landuse array is initialized for modal aerosal dry dep -#ifdef OSLO_AERO - prog_modal_aero = .true. -#else call phys_getopts(prog_modal_aero_out=prog_modal_aero) -#endif + call dvel_inti_fromlnd() if( masterproc ) then diff --git a/src/chemistry/mozart/mo_gas_phase_chemdr.F90 b/src/chemistry/mozart/mo_gas_phase_chemdr.F90 index 76c864d542..68657d0739 100644 --- a/src/chemistry/mozart/mo_gas_phase_chemdr.F90 +++ b/src/chemistry/mozart/mo_gas_phase_chemdr.F90 @@ -25,10 +25,6 @@ module mo_gas_phase_chemdr integer :: het1_ndx integer :: ndx_cldfr, ndx_cmfdqr, ndx_nevapr, ndx_cldtop, ndx_prain integer :: ndx_h2so4 -#ifdef OSLO_AERO - logical :: inv_o3, inv_oh, inv_no3, inv_ho2 - integer :: id_o3, id_oh, id_no3, id_ho2 -#endif ! ! CCMI ! @@ -60,11 +56,7 @@ module mo_gas_phase_chemdr subroutine gas_phase_chemdr_inti() -#ifdef OSLO_AERO - use mo_chem_utls, only : get_spc_ndx, get_extfrc_ndx, get_rxt_ndx, get_inv_ndx -#else use mo_chem_utls, only : get_spc_ndx, get_extfrc_ndx, get_rxt_ndx, get_inv_ndx -#endif use cam_history, only : addfld,add_default,horiz_only use mo_chm_diags, only : chm_diags_inti use constituents, only : cnst_get_ind @@ -83,16 +75,6 @@ subroutine gas_phase_chemdr_inti() call phys_getopts( convproc_do_aer_out = convproc_do_aer, history_cesm_forcing_out=history_cesm_forcing ) -#ifdef OSLO_AERO - inv_o3 = get_inv_ndx('O3') > 0 - inv_oh = get_inv_ndx('OH') > 0 - inv_no3 = get_inv_ndx('NO3') > 0 - inv_ho2 = get_inv_ndx('HO2') > 0 - if (inv_o3) id_o3 = get_inv_ndx('O3') - if (inv_oh) id_oh = get_inv_ndx('OH') - if (inv_no3) id_no3 = get_inv_ndx('NO3') - if (inv_ho2) id_ho2 = get_inv_ndx('HO2') -#endif ndx_h2so4 = get_spc_ndx('H2SO4') ! ! CCMI @@ -211,26 +193,11 @@ subroutine gas_phase_chemdr_inti() call addfld( 'HCL_GAS', (/ 'lev' /), 'I', 'mol/mol', 'gas-phase hcl' ) call addfld( 'HCL_STS', (/ 'lev' /), 'I', 'mol/mol', 'STS condensed HCL' ) -#ifdef OSLO_AERO - ! Adding extra fields for oxi-output (before and after diurnal variations.) - call addfld ('OH_bef ', (/ 'lev' /), 'A','unit', 'OH invariants before adding diurnal variations' ) - call addfld ('HO2_bef ', (/ 'lev' /), 'A','unit', 'HO2 invariants before adding diurnal variations' ) - call addfld ('NO3_bef ', (/ 'lev' /), 'A','unit', 'NO3 invariants before adding diurnal variations' ) - call addfld ('OH_aft ', (/ 'lev' /), 'A','unit', 'OH invariants after adding diurnal variations' ) - call addfld ('HO2_aft ', (/ 'lev' /), 'A','unit', 'HO2 invariants after adding diurnal variations' ) - call addfld ('NO3_aft ', (/ 'lev' /), 'A','unit', 'NO3 invariants after adding diurnal variations' ) - - call add_default ('OH_bef ', 1, ' ') - call add_default ('HO2_bef ', 1, ' ') - call add_default ('NO3_bef ', 1, ' ') - call add_default ('OH_aft ', 1, ' ') - call add_default ('HO2_aft ', 1, ' ') - call add_default ('NO3_aft ', 1, ' ') -#endif if (het1_ndx>0) then call addfld( 'het1_total', (/ 'lev' /), 'I', '/s', 'total N2O5 + H2O het rate constant' ) endif call addfld( 'SZA', horiz_only, 'I', 'degrees', 'solar zenith angle' ) + call chm_diags_inti() call rate_diags_init() @@ -342,17 +309,14 @@ subroutine gas_phase_chemdr(lchnk, ncol, imozart, q, & use rate_diags, only : rate_diags_calc, rate_diags_o3s_loss use mo_mass_xforms, only : mmr2vmr, vmr2mmr, h2o_to_vmr, mmr2vmri use orbit, only : zenith + ! ! for aqueous chemistry and aerosol growth ! -#ifdef OSLO_AERO - use oslo_aero_diurnal_var, only : set_diurnal_invariants - use oslo_aero_model, only : aero_model_gasaerexch - use oslo_aero_model, only : aero_model_strat_surfarea -#else - use aero_model, only : aero_model_gasaerexch - use aero_model, only : aero_model_strat_surfarea -#endif + use aero_model, only : aero_model_gasaerexch + + use aero_model, only : aero_model_strat_surfarea + !----------------------------------------------------------------------- ! ... Dummy arguments !----------------------------------------------------------------------- @@ -656,21 +620,6 @@ subroutine gas_phase_chemdr(lchnk, ncol, imozart, q, & !----------------------------------------------------------------------- call setinv( invariants, tfld, h2ovmr, vmr, pmid, ncol, lchnk, pbuf ) -#ifdef OSLO_AERO - !----------------------------------------------------------------------- - ! ... Set the "day/night cycle for prescribed oxidants" - !----------------------------------------------------------------------- - call outfld('OH_bef', invariants(:,:,id_oh), ncol, lchnk) - call outfld('HO2_bef', invariants(:,:,id_ho2), ncol, lchnk) - call outfld('NO3_bef', invariants(:,:,id_no3), ncol, lchnk) - if (inv_oh.or.inv_ho2.or.inv_no3) then - call set_diurnal_invariants(invariants,delt,ncol,lchnk,inv_oh,inv_ho2,id_oh,id_ho2,inv_no3,id_no3) - end if - call outfld('OH_aft', invariants(:,:,id_oh), ncol, lchnk) - call outfld('HO2_aft', invariants(:,:,id_ho2), ncol, lchnk) - call outfld('NO3_aft', invariants(:,:,id_no3), ncol, lchnk) -#endif - !----------------------------------------------------------------------- ! ... stratosphere aerosol surface area !----------------------------------------------------------------------- @@ -1148,17 +1097,10 @@ subroutine gas_phase_chemdr(lchnk, ncol, imozart, q, & endif endif -#ifdef OSLO_AERO - call chm_diags( lchnk, ncol, vmr(:ncol,:,:), mmr_new(:ncol,:,:), & - reaction_rates(:ncol,:,:), invariants(:ncol,:,:), depvel(:ncol,:), sflx(:ncol,:), & - mmr_tend(:ncol,:,:), pdel(:ncol,:), pmid(:ncol,:), troplev(:ncol), wetdepflx_diag(:ncol,:), & - nhx_nitrogen_flx(:ncol), noy_nitrogen_flx(:ncol), pbuf ) -#else call chm_diags( lchnk, ncol, vmr(:ncol,:,:), mmr_new(:ncol,:,:), & reaction_rates(:ncol,:,:), invariants(:ncol,:,:), depvel(:ncol,:), sflx(:ncol,:), & mmr_tend(:ncol,:,:), pdel(:ncol,:), pmid(:ncol,:), troplev(:ncol), wetdepflx_diag(:ncol,:), & nhx_nitrogen_flx(:ncol), noy_nitrogen_flx(:ncol) ) -#endif call rate_diags_calc( reaction_rates(:,:,:), vmr(:,:,:), invariants(:,:,indexm), ncol, lchnk ) ! diff --git a/src/chemistry/mozart/mo_neu_wetdep.F90 b/src/chemistry/mozart/mo_neu_wetdep.F90 index df8ff28483..c3974b7e37 100644 --- a/src/chemistry/mozart/mo_neu_wetdep.F90 +++ b/src/chemistry/mozart/mo_neu_wetdep.F90 @@ -14,8 +14,6 @@ module mo_neu_wetdep use cam_abortutils, only : endrun use shr_drydep_mod, only : n_species_table, species_name_table, dheff use gas_wetdep_opts, only : gas_wetdep_method, gas_wetdep_list, gas_wetdep_cnt - use phys_control, only: phys_getopts ! OSLO_AERO - use mo_constants, only: rgrav ! OSLO_AERO ! implicit none ! @@ -262,9 +260,9 @@ subroutine neu_wetdep_tend(lchnk,ncol,mmr,pmid,pdel,zint,tfld,delt, & real(r8) :: e298, dhr real(r8), dimension(ncol) :: dk1s,dk2s,wrk real(r8) :: lats(pcols) - real(r8) :: wrk_wd(pcols) ! OSLO_AERO - logical :: history_aerosol ! OSLO_AERO + real(r8), parameter :: rad2deg = 180._r8/pi + ! ! from cam/src/physics/cam/stratiform.F90 ! @@ -460,21 +458,6 @@ subroutine neu_wetdep_tend(lchnk,ncol,mmr,pmid,pdel,zint,tfld,delt, & ! end do ! -#ifdef OSLO_AERO - !This is output normally in mo_chm_diags, but if neu wetdep, we have to output it here! - call phys_getopts( history_aerosol_out = history_aerosol) - if (history_aerosol) then - do m=1,gas_wetdep_cnt - wrk_wd(:ncol) = 0.0_r8 - do k=1,pver - !Note sign: tendency is negative, so this becomes a positive flux! - wrk_wd(:ncol) = wrk_wd(:ncol) - wd_tend(1:ncol,k,mapping_to_mmr(m))*pdel(:ncol,k)*rgrav !kg/m2/sec - end do - call outfld('WD_A_'//trim(gas_wetdep_list(m)),wrk_wd(:ncol),ncol,lchnk) - end do - end if -#endif - if ( do_diag ) then call outfld('QT_RAIN_HNO3', qt_rain, ncol, lchnk ) call outfld('QT_RIME_HNO3', qt_rime, ncol, lchnk ) diff --git a/src/chemistry/mozart/mo_setaer.F90 b/src/chemistry/mozart/mo_setaer.F90 index bb23050be4..34442f5ae5 100644 --- a/src/chemistry/mozart/mo_setaer.F90 +++ b/src/chemistry/mozart/mo_setaer.F90 @@ -655,13 +655,9 @@ subroutine setaer( z, airden, rh, aocs1, aocs2, acbs1, acbs2,& use chem_mods, only : adv_mass use mo_constants, only : avogadro use mo_chem_utls, only : get_spc_ndx -#ifdef OSLO_AERO - use oslo_aero_dust, only : dust_names - use oslo_aero_seasalt,only : sslt_names=>seasalt_names -#else use dust_model, only : dust_names use seasalt_model, only : sslt_names=>seasalt_names -#endif + implicit none !----------------------------------------------------------------------------- diff --git a/src/chemistry/mozart/mo_srf_emissions.F90 b/src/chemistry/mozart/mo_srf_emissions.F90 index e44393bcc1..80afe7f474 100644 --- a/src/chemistry/mozart/mo_srf_emissions.F90 +++ b/src/chemistry/mozart/mo_srf_emissions.F90 @@ -10,9 +10,6 @@ module mo_srf_emissions use ioFileMod, only : getfil use cam_logfile, only : iulog use tracer_data, only : trfld,trfile -#ifdef OSLO_AERO - use oslo_aero_ocean, only: oslo_aero_dms_inq -#endif implicit none @@ -39,9 +36,6 @@ module mo_srf_emissions type(emission), allocatable :: emissions(:) integer :: n_emis_files integer :: c10h16_ndx, isop_ndx -#ifdef OSLO_AERO - integer :: dms_ndx -#endif contains @@ -291,9 +285,7 @@ subroutine srf_emissions_inti( srf_emis_specifier, emis_type_in, emis_cycle_yr, c10h16_ndx = get_spc_ndx('C10H16') isop_ndx = get_spc_ndx('ISOP') -#ifdef OSLO_AERO - dms_ndx = get_spc_ndx('DMS') -#endif + end subroutine srf_emissions_inti subroutine set_srf_emissions_time( pbuf2d, state ) @@ -410,16 +402,6 @@ subroutine set_srf_emissions( lchnk, ncol, sflx ) declination = dec_max * cos((doy_loc - 172._r8)*twopi/dayspy) tod = (calday - doy_loc) + .5_r8 -#ifdef OSLO_AERO - ! Zero DMS emissions if option is not "from file" - ! oslo_aero_dms_inq() Returns "true" if "emissions from file" - if (.not. oslo_aero_dms_inq()) then - if (dms_ndx > 0) then - sflx(:ncol,dms_ndx) = 0.0_r8 - end if - end if -#endif - do i = 1,ncol ! polar_day = .false. diff --git a/src/chemistry/mozart/mo_usrrxt.F90 b/src/chemistry/mozart/mo_usrrxt.F90 index 9d61bdbd06..6c6edddaad 100644 --- a/src/chemistry/mozart/mo_usrrxt.F90 +++ b/src/chemistry/mozart/mo_usrrxt.F90 @@ -3,9 +3,6 @@ module mo_usrrxt use shr_kind_mod, only : r8 => shr_kind_r8 use cam_logfile, only : iulog use ppgrid, only : pver, pcols -#ifdef OSLO_AERO - use oslo_aero_params, only: nmodes_oslo=> nmodes -#endif implicit none @@ -609,11 +606,7 @@ subroutine usrrxt( rxt, temp, tempi, tempe, invariants, h2ovmr, & use mo_setinv, only : inv_o2_ndx=>o2_ndx, inv_h2o_ndx=>h2o_ndx use physics_buffer,only : physics_buffer_desc use carma_flags_mod, only : carma_hetchem_feedback -#ifdef OSLO_AERO - use oslo_aero_model, only : aero_model_surfarea -#else use aero_model, only : aero_model_surfarea -#endif use rad_constituents,only : rad_cnst_get_info implicit none @@ -777,11 +770,8 @@ subroutine usrrxt( rxt, temp, tempi, tempe, invariants, h2ovmr, & ! get info about the modal aerosols ! get ntot_amode -#ifdef OSLO_AERO - ntot_amode = nmodes_oslo -#else call rad_cnst_get_info(0, nmodes=ntot_amode) -#endif + if (ntot_amode>0) then allocate(sfc_array(pcols,pver,ntot_amode), dm_array(pcols,pver,ntot_amode) ) else diff --git a/src/physics/cam/vertical_diffusion.F90 b/src/physics/cam/vertical_diffusion.F90 index c3bb24c4ee..dd2cc721f3 100644 --- a/src/physics/cam/vertical_diffusion.F90 +++ b/src/physics/cam/vertical_diffusion.F90 @@ -72,9 +72,6 @@ module vertical_diffusion use ref_pres, only : do_molec_diff, nbot_molec use phys_control, only : phys_getopts use time_manager, only : is_first_step -#ifdef OSLO_AERO -use oslo_aero_share, only: getNumberOfAerosolTracers, fillAerosolTracerList -#endif implicit none private @@ -319,19 +316,17 @@ subroutine vertical_diffusion_init(pbuf2d) call cnst_get_ind( 'NUMLIQ', ixnumliq, abort=.false. ) call cnst_get_ind( 'NUMICE', ixnumice, abort=.false. ) - ! Set prog_modal_aero determines whether prognostic modal aerosols are present in the run. - ! Get the constituent indices of the number and mass mixing ratios of the modal - ! aerosols. - ! N.B. - This implementation assumes that the prognostic modal aerosols are - ! impacting the climate calculation (i.e., can get info from list 0). -#ifdef OSLO_AERO - prog_modal_aero = .true. - pmam_ncnst = getNumberOfAerosolTracers() - allocate(pmam_cnst_idx(pmam_ncnst)) - call fillAerosolTracerList(pmam_cnst_idx) -#else + ! prog_modal_aero determines whether prognostic modal aerosols are present in the run. call phys_getopts(prog_modal_aero_out=prog_modal_aero) if (prog_modal_aero) then + + ! Get the constituent indices of the number and mass mixing ratios of the modal + ! aerosols. + ! + ! N.B. - This implementation assumes that the prognostic modal aerosols are + ! impacting the climate calculation (i.e., can get info from list 0). + ! + ! First need total number of mam constituents call rad_cnst_get_info(0, nmodes=nmodes) do m = 1, nmodes @@ -353,7 +348,6 @@ subroutine vertical_diffusion_init(pbuf2d) end do end do end if -#endif ! Initialize upper boundary condition module @@ -577,15 +571,12 @@ subroutine vertical_diffusion_init(pbuf2d) if( history_budget ) then call add_default( vdiffnam(ixcldliq), history_budget_histfile_num, ' ' ) call add_default( vdiffnam(ixcldice), history_budget_histfile_num, ' ' ) -#ifdef OSLO_AERO - call add_default( vdiffnam(ixnumliq), history_budget_histfile_num, ' ' ) - call add_default( vdiffnam(ixnumice), history_budget_histfile_num, ' ' ) -#endif if( history_budget_histfile_num > 1 ) then call add_default( vdiffnam(1), history_budget_histfile_num, ' ' ) call add_default( 'DTV' , history_budget_histfile_num, ' ' ) end if end if + if ( history_waccm ) then if (do_molec_diff) then call add_default ( 'TTPXMLC', 1, ' ' ) @@ -1181,22 +1172,17 @@ subroutine vertical_diffusion_tend( & end if -#ifdef OSLO_AERO - ! Do nothing if OSLO_AERO - ! Oslo aero adds emissions together with dry deposition - so do not add the explicit - ! surface fluxes to the lowest layer -#else if (prog_modal_aero) then + ! Modal aerosol species not diffused, so just add the explicit surface fluxes to the ! lowest layer. **NOTE** This code assumes wet mmr. - + tmp1(:ncol) = ztodt * gravit * state%rpdel(:ncol,pver) do m = 1, pmam_ncnst l = pmam_cnst_idx(m) q_tmp(:ncol,pver,l) = q_tmp(:ncol,pver,l) + tmp1(:ncol) * cflux(:ncol,l) enddo end if -#endif ! -------------------------------------------------------- ! ! Diagnostics and output writing after applying PBL scheme ! diff --git a/src/physics/cam/zm_microphysics.F90 b/src/physics/cam/zm_microphysics.F90 index 18f9ab5204..b54e1e684e 100644 --- a/src/physics/cam/zm_microphysics.F90 +++ b/src/physics/cam/zm_microphysics.F90 @@ -1475,13 +1475,11 @@ subroutine zm_mphy(su, qu, mu, du, eu, cmel, cmei, zf, pm, te, end if -#ifndef OSLO_AERO call activate_aerosol( & wu(i,k), wmix, wdiab, wmin, wmax, & t(i,k), rho(i,k), naermod, aero%nmodes, vaerosol, & hygro, aero_props_obj, fn, fm, & fluxn, fluxm, flux_fullact, in_cloud_in=in_cloud, smax_f=smax_f) -#endif do m = 1, aero%nmodes nlsrc = nlsrc + fn(m)*naermod(m) ! number nucleated diff --git a/src/physics/rrtmg/radiation.F90 b/src/physics/rrtmg/radiation.F90 index d7d90350a5..31e33b183d 100644 --- a/src/physics/rrtmg/radiation.F90 +++ b/src/physics/rrtmg/radiation.F90 @@ -42,13 +42,6 @@ module radiation use error_messages, only: handle_err use perf_mod, only: t_startf, t_stopf use cam_logfile, only: iulog -use prescribed_volcaero, only: has_prescribed_volcaero -#ifdef OSLO_AERO -use oslo_aero_optical_params, only: oslo_aero_optical_params_calc -#ifdef AEROCOM -use oslo_aero_aerocom, only: dod440, dod550, dod870, abs550, abs550alt -#endif -#endif implicit none private @@ -162,7 +155,6 @@ module radiation ! PIO descriptors (for restarts) type(var_desc_t) :: cospcnt_desc type(var_desc_t) :: nextsw_cday_desc - !=============================================================================== contains !=============================================================================== @@ -549,11 +541,6 @@ subroutine radiation_init(pbuf2d) end if end do -#ifdef OSLO_AERO - call addfld('FDSCDRF', (/ 'ilev' /), 'A', 'W/m2', 'Shortwave clear-sky downward flux') - call addfld('FUSCDRF', (/ 'ilev' /), 'A', 'W/m2', 'Shortwave clear-sky upward flux') -#endif - if (scm_crm_mode) then call add_default('FUS ', 1, ' ') call add_default('FUSC ', 1, ' ') @@ -777,7 +764,6 @@ subroutine radiation_tend( & ! Local variables - logical :: idrf type(rad_out_t), pointer :: rd ! allow rd_out to be optional by allocating a local object ! if the argument is not present logical :: write_output @@ -879,33 +865,10 @@ subroutine radiation_tend( & real(r8) :: aer_tau_w_f(pcols,0:pver,nswbands) ! aerosol forward scattered fraction * w * tau real(r8) :: aer_lw_abs (pcols,pver,nlwbands) ! aerosol absorption optics depth (LW) -#ifdef OSLO_AERO - ! Local variables used for calculating aerosol optics and direct and indirect forcings. - ! aodvis and absvis are AOD and absorptive AOD for visible wavelength close to 0.55 um (0.35-0.64) - ! Note that aodvis and absvis output should be devided by dayfoc to give physical (A)AOD values - real(r8) :: per_tau (pcols,0:pver,nswbands) ! aerosol extinction optical depth - real(r8) :: per_tau_w (pcols,0:pver,nswbands) ! aerosol single scattering albedo * tau - real(r8) :: per_tau_w_g(pcols,0:pver,nswbands) ! aerosol assymetry parameter * w * tau - real(r8) :: per_tau_w_f(pcols,0:pver,nswbands) ! aerosol forward scattered fraction * w * tau - real(r8) :: per_lw_abs (pcols,pver,nlwbands) ! aerosol absorption optics depth (LW) - real(r8) :: aodvis(pcols) ! AOD vis - real(r8) :: absvis(pcols) ! absorptive AOD vis - real(r8) :: clearodvis(pcols) - real(r8) :: clearabsvis(pcols) - real(r8) :: cloudfree(pcols) - real(r8) :: cloudfreemax(pcols) - real(r8) :: clearod440(pcols) ! AERCOM - real(r8) :: clearod550(pcols) ! AERCOM - real(r8) :: clearod870(pcols) ! AERCOM - real(r8) :: clearabs550(pcols) ! AERCOM - real(r8) :: clearabs550alt(pcols) ! AERCOM - real(r8) :: ftem_1d(pcols) ! work-array to avoid NAN and pcols/ncol confusion -#endif - - real(r8) :: fns(pcols,pverp) ! net shortwave flux - real(r8) :: fcns(pcols,pverp) ! net clear-sky shortwave flux - real(r8) :: fnl(pcols,pverp) ! net longwave flux - real(r8) :: fcnl(pcols,pverp) ! net clear-sky longwave flux + real(r8) :: fns(pcols,pverp) ! net shortwave flux + real(r8) :: fcns(pcols,pverp) ! net clear-sky shortwave flux + real(r8) :: fnl(pcols,pverp) ! net longwave flux + real(r8) :: fcnl(pcols,pverp) ! net clear-sky longwave flux ! for COSP real(r8) :: emis(pcols,pver) ! Cloud longwave emissivity @@ -1227,149 +1190,10 @@ subroutine radiation_tend( & call t_stopf('cldoptics') - ! ------------------------------------------ ! Solar radiation computation - ! ------------------------------------------ - ! OSLO_AERO aerosol - -#ifdef OSLO_AERO if (dosw) then - per_lw_abs(:,:,:) = 0._r8 - per_tau(:,:,:) = 0._r8 - per_tau_w(:,:,:) = 0._r8 - per_tau_w_g(:,:,:) = 0._r8 - per_tau_w_f(:,:,:) = 0._r8 - - call oslo_aero_optical_params_calc(lchnk, ncol, 10.0_r8*state%pint, state%pmid, & - coszrs, pbuf, state, state%t, cld, & - per_tau, per_tau_w, per_tau_w_g, per_tau_w_f, per_lw_abs, aodvis, absvis) - - call get_variability(sfac) - - ! Get the active climate/diagnostic shortwave calculations - call rad_cnst_get_call_list(active_calls) - - ! The climate (icall==0) calculation must occur last. - do icall = N_DIAG, 0, -1 - - if (active_calls(icall)) then - - ! update the concentrations in the RRTMG state object - call rrtmg_state_update(state, pbuf, icall, r_state) - - ! A first call with Oslo aerosols set to zero for radiative forcing diagnostics - ! follwoing the Ghan (2013) method: - ! for calculation of direct radiative forcing, not necessarily "offline" as such anymore - ! (just nudged), but with an extra call with 0 aerosol extiction. - ! - idrf = .true. - call rad_rrtmg_sw( & - lchnk, ncol, num_rrtmg_levs, r_state, state%pmid, & - cldfprime, per_tau*0.0_r8, per_tau_w, per_tau_w_g, per_tau_w_f, & - eccf, coszrs, rd%solin, sfac, cam_in%asdir, & - cam_in%asdif, cam_in%aldir, cam_in%aldif, qrs, rd%qrsc, & - fsnt, rd%fsntc, rd%fsntoa, rd%fsutoa, rd%fsntoac, & - rd%fsnirt, rd%fsnrtc, rd%fsnirtsq, fsns, rd%fsnsc, & - rd%fsdsc, fsds, cam_out%sols, cam_out%soll, cam_out%solsd, & - cam_out%solld, fns, fcns, Nday, Nnite, & - IdxDay, IdxNite, su, sd, E_cld_tau=c_cld_tau, & - E_cld_tau_w=c_cld_tau_w, E_cld_tau_w_g=c_cld_tau_w_g, & - E_cld_tau_w_f=c_cld_tau_w_f, old_convert=.false., idrf=idrf) - - ftem(:ncol,:pver) = qrs(:ncol,:pver)/cpair - ! - ! Dump shortwave radiation information to history tape buffer (diagnostics) - ! - ! Note that DRF fields are now from the per_tau=0 call (clean), no longer with per_tau from pmxsub - call outfld('QRS_DRF ',ftem ,pcols,lchnk) - ftem(:ncol,:pver) = rd%qrsc(:ncol,:pver)/cpair - call outfld('QRSC_DRF',ftem ,pcols,lchnk) - call outfld('FSNT_DRF',fsnt(:) ,pcols,lchnk) - call outfld('FSNS_DRF',fsns(:) ,pcols,lchnk) - call outfld('FSNTCDRF',rd%fsntc(:) ,pcols,lchnk) - call outfld('FSNSCDRF',rd%fsnsc(:) ,pcols,lchnk) -#ifdef AEROCOM - call outfld('FSUTADRF',rd%fsutoa(:),pcols,lchnk) - call outfld('FSDS_DRF',fsds(:) ,pcols,lchnk) - ftem_1d(1:ncol) = fsds(1:ncol)-fsns(1:ncol) - call outfld('FSUS_DRF',ftem_1d,pcols,lchnk) - call outfld('FSDSCDRF',rd%fsdsc(:) ,pcols,lchnk) -#endif - idrf = .false. - call rad_rrtmg_sw( & - lchnk, ncol, num_rrtmg_levs, r_state, state%pmid, & - cldfprime, per_tau, per_tau_w, per_tau_w_g, per_tau_w_f, & - eccf, coszrs, rd%solin, sfac, cam_in%asdir, & - cam_in%asdif, cam_in%aldir, cam_in%aldif, qrs, rd%qrsc, & - fsnt, rd%fsntc, rd%fsntoa, rd%fsutoa, rd%fsntoac, & - rd%fsnirt, rd%fsnrtc, rd%fsnirtsq, fsns, rd%fsnsc, & - rd%fsdsc, fsds, cam_out%sols, cam_out%soll, cam_out%solsd, & - cam_out%solld, fns, fcns, Nday, Nnite, & - IdxDay, IdxNite, su, sd, E_cld_tau=c_cld_tau, & - E_cld_tau_w=c_cld_tau_w, E_cld_tau_w_g=c_cld_tau_w_g, & - E_cld_tau_w_f=c_cld_tau_w_f, old_convert=.false., idrf=idrf) - - ! Output net fluxes at 200 mb - call vertinterp(ncol, pcols, pverp, state%pint, 20000._r8, fcns, rd%fsn200c) - call vertinterp(ncol, pcols, pverp, state%pint, 20000._r8, fns, rd%fsn200) - if (hist_fld_active('FSNR')) then - do i = 1,ncol - call vertinterp(1, 1, pverp, state%pint(i,:), p_trop(i), fns(i,:), rd%fsnr(i)) - end do - end if - - if (write_output) call radiation_output_sw(lchnk, ncol, icall, rd, pbuf, cam_out) - - end if - end do - end if - - ! Calculate cloud-free fraction assuming random overlap - ! (kind of duplicated from cloud_cover_diags::cldsav) - cloudfree(1:ncol) = 1.0_r8 - cloudfreemax(1:ncol) = 1.0_r8 - !Find cloud-free fraction (note this duplicated code and may not be consistent with cldtot calculated elsewhere) - do k = 1, pver - do i=1,ncol - cloudfree(i) = cloudfree(i) * cloudfreemax(i) - cloudfreemax(i) = min(cloudfreemax(i),1.0_r8-cld(i,k)) - end do - end do - - ! Calculate AOD (visible) for cloud free - do i = 1, ncol - clearodvis(i)=cloudfree(i)*aodvis(i) - clearabsvis(i)=cloudfree(i)*absvis(i) - end do - - ! clear-sky AOD and absorptive AOD for visible wavelength close to 0.55 um (0.35-0.64) - ! Note that caodvis and cabsvis output should be devided by dayfoc*cloudfree to give physical (A)AOD values - call outfld('CAODVIS ',clearodvis ,pcols,lchnk) - call outfld('CABSVIS ',clearabsvis ,pcols,lchnk) - call outfld('CLDFREE ',cloudfree ,pcols,lchnk) -#ifdef AEROCOM - do i = 1, ncol - clearod440(i) = cloudfree(i)*dod440(i) - clearod550(i) = cloudfree(i)*dod550(i) - clearod870(i) = cloudfree(i)*dod870(i) - clearabs550(i) = cloudfree(i)*abs550(i) - clearabs550alt(i) = cloudfree(i)*abs550alt(i) - end do - call outfld('CDOD440 ',clearod440 ,pcols,lchnk) - call outfld('CDOD550 ',clearod550 ,pcols,lchnk) - call outfld('CDOD870 ',clearod870 ,pcols,lchnk) - call outfld('CABS550 ',clearabs550 ,pcols,lchnk) - call outfld('CABS550A',clearabs550alt,pcols,lchnk) -#endif -#endif - - ! CAM Aerosol - -#ifndef OSLO_AERO - if (dosw) then - call get_variability(sfac) ! Get the active climate/diagnostic shortwave calculations @@ -1417,75 +1241,14 @@ subroutine radiation_tend( & end if end do - end if ! end of (if do_sw) -#endif + + end if ! Output aerosol mmr call rad_cnst_out(0, state, pbuf) - ! ------------------------------------------ ! Longwave radiation computation - ! ------------------------------------------ -#ifdef OSLO_AERO - if (dolw) then - - call rad_cnst_get_call_list(active_calls) - - ! The climate (icall==0) calculation must occur last. - do icall = N_DIAG, 0, -1 - - if (active_calls(icall)) then - - ! update the conctrations in the RRTMG state object - call rrtmg_state_update( state, pbuf, icall, r_state) - - call rad_rrtmg_lw( & - lchnk, ncol, num_rrtmg_levs, r_state, state%pmid, & - per_lw_abs*0.0_r8, cldfprime, c_cld_lw_abs, qrl, rd%qrlc, & - flns, flnt, rd%flnsc, rd%flntc, cam_out%flwds, & - rd%flut, rd%flutc, fnl, fcnl, rd%fldsc, & - lu, ld) - - call outfld('FLNT_DRF',flnt(:) ,pcols,lchnk) - call outfld('FLNTCDRF',rd%flntc(:) ,pcols,lchnk) - - call rad_rrtmg_lw( & - lchnk, ncol, num_rrtmg_levs, r_state, state%pmid, & - per_lw_abs, cldfprime, c_cld_lw_abs, qrl, rd%qrlc, & - flns, flnt, rd%flnsc, rd%flntc, cam_out%flwds, & - rd%flut, rd%flutc, fnl, fcnl, rd%fldsc, & - lu, ld) - - ! FLNT_ORG is just for temporary testing vs. FLNT - ftem_1d(1:ncol) = cam_out%flwds(1:ncol) - flns(1:ncol) - call outfld('FLUS ',ftem_1d ,pcols,lchnk) - - ! Output fluxes at 200 mb - call vertinterp(ncol, pcols, pverp, state%pint, 20000._r8, fnl, rd%fln200) - call vertinterp(ncol, pcols, pverp, state%pint, 20000._r8, fcnl, rd%fln200c) - if (hist_fld_active('FLNR')) then - do i = 1,ncol - call vertinterp(1, 1, pverp, state%pint(i,:), p_trop(i), fnl(i,:), rd%flnr(i)) - end do - end if - - flntclr(:) = 0._r8 - freqclr(:) = 0._r8 - do i = 1, ncol - if (maxval(cldfprime(i,:)) <= 0.1_r8) then - freqclr(i) = 1._r8 - flntclr(i) = rd%flntc(i) - end if - end do - - if (write_output) call radiation_output_lw(lchnk, ncol, icall, rd, pbuf, cam_out, freqclr, flntclr) - end if - end do - end if -#endif - -#ifndef OSLO_AERO if (dolw) then call rad_cnst_get_call_list(active_calls) @@ -1529,8 +1292,8 @@ subroutine radiation_tend( & end if end do + end if -#endif ! deconstruct the RRTMG state object call rrtmg_state_destroy(r_state) @@ -1578,7 +1341,7 @@ subroutine radiation_tend( & snow_tau_in=gb_snow_tau, snow_emis_in=gb_snow_lw) cosp_cnt(lchnk) = 0 end if - end if ! end of if (docosp) + end if else ! if (dosw .or. dolw) then @@ -1801,3 +1564,4 @@ end subroutine calc_col_mean !=============================================================================== end module radiation + diff --git a/src/physics/rrtmg/radlw.F90 b/src/physics/rrtmg/radlw.F90 index 7e2d80de68..b2b56a751c 100644 --- a/src/physics/rrtmg/radlw.F90 +++ b/src/physics/rrtmg/radlw.F90 @@ -227,16 +227,12 @@ subroutine rad_rrtmg_lw(lchnk ,ncol ,rrtmg_levs,r_state, & fsul(:ncol,pverp-rrtmg_levs+1:pverp)=uflxc(:ncol,rrtmg_levs:1:-1) fsdl(:ncol,pverp-rrtmg_levs+1:pverp)=dflxc(:ncol,rrtmg_levs:1:-1) -#ifndef OSLO_AERO if (single_column.and.scm_crm_mode) then -#endif call outfld('FUL ',ful,pcols,lchnk) call outfld('FDL ',fdl,pcols,lchnk) call outfld('FULC ',fsul,pcols,lchnk) call outfld('FDLC ',fsdl,pcols,lchnk) -#ifndef OSLO_AERO endif -#endif fnl(:ncol,:) = ful(:ncol,:) - fdl(:ncol,:) ! mji/ cam excluded this? diff --git a/src/physics/rrtmg/radsw.F90 b/src/physics/rrtmg/radsw.F90 index 5df39fdbda..df222557dd 100644 --- a/src/physics/rrtmg/radsw.F90 +++ b/src/physics/rrtmg/radsw.F90 @@ -53,7 +53,7 @@ subroutine rad_rrtmg_sw(lchnk,ncol ,rrtmg_levs ,r_state , & Nday ,Nnite ,IdxDay ,IdxNite , & su ,sd , & E_cld_tau, E_cld_tau_w, E_cld_tau_w_g, E_cld_tau_w_f, & - old_convert, idrf) + old_convert) !----------------------------------------------------------------------- @@ -132,8 +132,7 @@ subroutine rad_rrtmg_sw(lchnk,ncol ,rrtmg_levs ,r_state , & real(r8), optional, intent(in) :: E_cld_tau_w (nbndsw, pcols, pver) ! cloud optical real(r8), optional, intent(in) :: E_cld_tau_w_g(nbndsw, pcols, pver) ! cloud optical real(r8), optional, intent(in) :: E_cld_tau_w_f(nbndsw, pcols, pver) ! cloud optical - logical , optional, intent(in) :: old_convert - logical , optional, intent(in) :: idrf + logical, optional, intent(in) :: old_convert ! Output arguments @@ -305,16 +304,12 @@ subroutine rad_rrtmg_sw(lchnk,ncol ,rrtmg_levs ,r_state , & qrsc(1:ncol,1:pver) = 0.0_r8 fns(1:ncol,1:pverp) = 0.0_r8 fcns(1:ncol,1:pverp) = 0.0_r8 -#ifndef OSLO_AERO if (single_column.and.scm_crm_mode) then -#endif fus(1:ncol,1:pverp) = 0.0_r8 fds(1:ncol,1:pverp) = 0.0_r8 fusc(:ncol,:pverp) = 0.0_r8 fdsc(:ncol,:pverp) = 0.0_r8 -#ifndef OSLO_AERO endif -#endif if (associated(su)) su(1:ncol,:,:) = 0.0_r8 if (associated(sd)) sd(1:ncol,:,:) = 0.0_r8 @@ -627,9 +622,7 @@ subroutine rad_rrtmg_sw(lchnk,ncol ,rrtmg_levs ,r_state , & end if ! these outfld calls don't work for spmd only outfield in scm mode (nonspmd) -#ifndef OSLO_AERO if (single_column .and. scm_crm_mode) then -#endif ! Following outputs added for CRM call ExpDayNite(fus,Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pverp) call ExpDayNite(fds,Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pverp) @@ -639,15 +632,7 @@ subroutine rad_rrtmg_sw(lchnk,ncol ,rrtmg_levs ,r_state , & call outfld('FDS ', fds, pcols, lchnk) call outfld('FUSC ', fusc, pcols, lchnk) call outfld('FDSC ', fdsc, pcols, lchnk) -#ifndef OSLO_AERO - end if -#endif - if (present(idrf)) then - if (idrf) then - call outfld('FUSCDRF ', fusc, pcols, lchnk) - call outfld('FDSCDRF ', fdsc, pcols, lchnk) - endif - end if + endif end subroutine rad_rrtmg_sw From 6c63a65bf47f261e63163b26c5e683bdef0acc65 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Wed, 11 Oct 2023 11:11:00 +0200 Subject: [PATCH 20/24] use cases updated --- cime_config/config_component.xml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml index 2834e39509..b734c60298 100644 --- a/cime_config/config_component.xml +++ b/cime_config/config_component.xml @@ -239,8 +239,11 @@ 2000_trop_strat_vbs_cam6 waccmx_ma_2000_cam6 - 2000_cam6_noresm - 2000_cam6 + 2000_cam6 + 2000_cam6 + + 2000_cam6_noresm + 2000_cam6_noresm aquaplanet_cam3 aquaplanet_cam4 From 5f8a7b8ae104d31bf9fc1de31543a28e8b5d3e55 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Thu, 12 Oct 2023 10:59:09 +0200 Subject: [PATCH 21/24] updates to get failed tests working --- .../use_cases/hist_cam6_noresm.xml | 191 ++++++++++++++++++ cime_config/config_component.xml | 3 + cime_config/testdefs/testlist_cam.xml | 12 +- 3 files changed, 204 insertions(+), 2 deletions(-) create mode 100644 bld/namelist_files/use_cases/hist_cam6_noresm.xml diff --git a/bld/namelist_files/use_cases/hist_cam6_noresm.xml b/bld/namelist_files/use_cases/hist_cam6_noresm.xml new file mode 100644 index 0000000000..0e11f22992 --- /dev/null +++ b/bld/namelist_files/use_cases/hist_cam6_noresm.xml @@ -0,0 +1,191 @@ + + + + + + + + + + + 'atm/cam/solar/SolarForcingCMIP6_18491230-22991231_c171031.nc' + + + 'CHEM_LBC_FILE' + +atm/waccm/lb/LBC_1750-2015_CMIP6_GlobAnnAvg_c180926.nc +'SERIAL' +'CO2','CH4','N2O','CFC11eq','CFC12' + + + + + 'atm/cam/ozone_strataero' + 'ozone_strataero_WACCM_L70_zm5day_18500101-20150103_CMIP6ensAvg_c180923.nc' + 'O3' + 'SERIAL' + + + 'atm/cam/tracer_cnst' + 'tracer_cnst_halons_3D_L70_1849-2015_CMIP6ensAvg_c180927.nc' + 'O3','OH','NO3','HO2' + 'INTERP_MISSING_MONTHS' + '' + + + INTERP_MISSING_MONTHS + + + INTERP_MISSING_MONTHS + + + + 'BC_AX -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_AX_anthrosurfALL_surface_1849-2015_1.9x2.5_version20180512.nc', + 'BC_N -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_N_anthrosurfALL_surface_1849-2015_1.9x2.5_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_anthrosurfALL_surface_1849-2015_1.9x2.5_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_anthrosurfALL_surface_1849-2015_1.9x2.5_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_anthrosurfALL_surface_1849-2015_1.9x2.5_version20180512.nc' + + + 'BC_AX -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_AX_anthrosurfALL_surface_1849-2015_1.9x2.5_version20180512.nc', + 'BC_N -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_N_anthrosurfALL_surface_1849-2015_1.9x2.5_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_anthrosurfALL_surface_1849-2015_1.9x2.5_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_anthrosurfALL_surface_1849-2015_1.9x2.5_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_anthrosurfALL_surface_1849-2015_1.9x2.5_version20180512.nc' + + + 'BC_AX -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_AX_anthrosurfALL_surface_1849-2015_0.9x1.25_version20180512.nc', + 'BC_N -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_N_anthrosurfALL_surface_1849-2015_0.9x1.25_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_anthrosurfALL_surface_1849-2015_0.9x1.25_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_anthrosurfALL_surface_1849-2015_0.9x1.25_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_anthrosurfALL_surface_1849-2015_0.9x1.25_version20180512.nc' + + + + + 'H2O -> $INPUTDATA_ROOT/atm/cam/chem/emis/elev/H2OemissionCH4oxidationx2_3D_L70_1849-2015_CMIP6ensAvg_c180927.nc', + 'BC_AX -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_AX_airALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'BC_AX -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_AX_anthroprofALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'BC_N -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_N_airALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'BC_N -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_N_anthroprofALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'BC_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_NI_bbALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_airALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_anthroprofALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_bbALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_airALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_anthroprofALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_bbALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_volcALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_airALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_anthroprofALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_bbALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_volcALL_vertical_1849-2015_1.9x2.5_version20180512.nc' + + + 'H2O -> $INPUTDATA_ROOT/atm/cam/chem/emis/elev/H2OemissionCH4oxidationx2_3D_L70_1849-2015_CMIP6ensAvg_c180927.nc', + 'BC_AX -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_AX_airALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'BC_AX -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_AX_anthroprofALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'BC_N -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_N_airALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'BC_N -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_N_anthroprofALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'BC_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_NI_bbALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_airALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_anthroprofALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_bbALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_airALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_anthroprofALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_bbALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_volcALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_airALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_anthroprofALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_bbALL_vertical_1849-2015_1.9x2.5_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_volcALL_vertical_1849-2015_1.9x2.5_version20180512.nc' + + + 'H2O -> $INPUTDATA_ROOT/atm/cam/chem/emis/elev/H2OemissionCH4oxidationx2_3D_L70_1849-2015_CMIP6ensAvg_c180927.nc', + 'BC_AX -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_AX_airALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'BC_AX -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_AX_anthroprofALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'BC_N -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_N_airALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'BC_N -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_N_anthroprofALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'BC_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_BC_NI_bbALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_airALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_anthroprofALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'OM_NI -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_OM_NI_bbALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_airALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_anthroprofALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_bbALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO2_volcALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_airALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_anthroprofALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_bbALL_vertical_1849-2015_0.9x1.25_version20180512.nc', + 'SO4_PR -> $INPUTDATA_ROOT/atm/cam/chem/emis/cmip6_emissions_version20180512/emissions_cmip6_noresm2_SO4_PR_volcALL_vertical_1849-2015_0.9x1.25_version20180512.nc' + + + + + + + + + INTERP_MISSING_MONTHS + INTERP_MISSING_MONTHS + +0.286 +0.264 + + + .false. + .true. + .true. + .true. + .true. + .true. + + + .true. + + + .true. + + + 0.0200D0 + 0.0200D0 + + 8.0E-6 + 8.0E-6 + + + +5.5e-4 +5.0e-4 + + + .true. + + + 4 + + +0.90D0 + + +'isoprene = isoprene','monoterp = myrcene + sabinene + limonene+ carene_3 + ocimene_t_b + pinene_b + pinene_a' + + +noresm-only/atm/cam/chem/trop_mozart_aero/emis/soanucl/bvocgcmFV19_isopr_1850_2000_zero.nc +noresm-only/atm/cam/chem/trop_mozart_aero/emis/soanucl/bvocgcmFV19_monoterp_1850_2000_zero.nc + + +1850 + + + + + + + + + + +'A:Q:H2O','N:O2:O2','N:CO2:CO2','N:ozone:O3','N:N2O:N2O','N:CH4:CH4','N:CFC11:CFC11','N:CFC12:CFC12' + + diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml index b734c60298..246c81ce11 100644 --- a/cime_config/config_component.xml +++ b/cime_config/config_component.xml @@ -270,6 +270,9 @@ hist_cam6 hist_cam_lt hist_cam_mt + + hist_cam6_noresm + waccm_tsmlt_hist_cam6 waccm_sc_hist_cam6 waccm_ma_hist_cam6 diff --git a/cime_config/testdefs/testlist_cam.xml b/cime_config/testdefs/testlist_cam.xml index eae2c6a75c..e2d52f3c29 100644 --- a/cime_config/testdefs/testlist_cam.xml +++ b/cime_config/testdefs/testlist_cam.xml @@ -18,7 +18,15 @@ - + + + + + + + + + @@ -35,7 +43,7 @@ - + From 99b34053a37f23301d00ab3ad1ca5122a1315624 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Tue, 24 Oct 2023 14:52:33 +0200 Subject: [PATCH 22/24] removed hardwiring of use_hetfrz_classnuc --- bld/build-namelist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bld/build-namelist b/bld/build-namelist index 1ddc31a2fa..90d185013c 100755 --- a/bld/build-namelist +++ b/bld/build-namelist @@ -3043,7 +3043,7 @@ unless (defined $nl->get_value('dms_source_type')) { } #add_default($nl, 'opom_source_type'); #add_default($nl, 'opom_cycle_year'); -if ($chem =~ /_mam_oslo/) {$nl->set_variable_value('phys_ctl_nl','use_hetfrz_classnuc','.true.');} +#if ($chem =~ /_mam_oslo/) {$nl->set_variable_value('phys_ctl_nl','use_hetfrz_classnuc','.true.');} # WACCM-X runtime options add_default($nl, 'waccmx_opt'); From 740f7591ab9809cbc492658c794e4035ecbf2d7e Mon Sep 17 00:00:00 2001 From: Steve Goldhaber Date: Mon, 23 Oct 2023 21:01:38 +0200 Subject: [PATCH 23/24] Add new script to check for differences in the energy diagnostics of two log files. Move hard-coded use_hetfrz_classnuc to namelist_defaults Replace ERS test with PEM test --- bld/build-namelist | 1 - bld/namelist_files/namelist_defaults_cam.xml | 7 +- cime_config/SystemTests/check_energy_log.py | 233 +++++++++++++++++++ cime_config/testdefs/testlist_cam.xml | 3 +- 4 files changed, 239 insertions(+), 5 deletions(-) create mode 100755 cime_config/SystemTests/check_energy_log.py diff --git a/bld/build-namelist b/bld/build-namelist index 1ddc31a2fa..94007da750 100755 --- a/bld/build-namelist +++ b/bld/build-namelist @@ -3043,7 +3043,6 @@ unless (defined $nl->get_value('dms_source_type')) { } #add_default($nl, 'opom_source_type'); #add_default($nl, 'opom_cycle_year'); -if ($chem =~ /_mam_oslo/) {$nl->set_variable_value('phys_ctl_nl','use_hetfrz_classnuc','.true.');} # WACCM-X runtime options add_default($nl, 'waccmx_opt'); diff --git a/bld/namelist_files/namelist_defaults_cam.xml b/bld/namelist_files/namelist_defaults_cam.xml index 776eda9aca..24171d3f1f 100644 --- a/bld/namelist_files/namelist_defaults_cam.xml +++ b/bld/namelist_files/namelist_defaults_cam.xml @@ -2278,9 +2278,10 @@ 1.2D0 1.2D0 -.false. -.true. -.true. +.false. +.true. +.true. +.true. 0.01D0 0.05D0 diff --git a/cime_config/SystemTests/check_energy_log.py b/cime_config/SystemTests/check_energy_log.py new file mode 100755 index 0000000000..c11bfaf139 --- /dev/null +++ b/cime_config/SystemTests/check_energy_log.py @@ -0,0 +1,233 @@ +#!/usr/bin/env python3 + +""" +Given two log files, compare the diagnostics from check_energy. +Report any differences. +Treat the first file as the 'standard' for reporting of relative differences. +""" + +import argparse +import gzip +import os +import re +import sys + +_DEFAULT_EPS = 1.0e-14 + +class LogEntry: + """Class to hold the data from a single energy diagnostic entry from a + CAM log file.""" + + __entry_re = re.compile(r"nstep, te") + __nstep_diff_msg = "nstep differs" + __table_spc = 24 + __log_entries = {"nstep" : "nstep", + "te_input" : "TE input", "te_output" : "TE output", + "heat" : "Heat", "p_surf" : "Surf. Pres.", "p_top" : "Pres. top"} + + def __init__(self, input_line, linenum=None, eps=_DEFAULT_EPS): + """Initialize the log entry directly from a line of a CAM log file. + If not None, is the input line number.""" + if self.is_log_entry(input_line): + tokens = [x for x in input_line.strip().split(" ") if x] + if len(tokens) != len(self.__log_entries) + 2: + raise ValueError(f"Bad atm log input line, '{input_line.strip()}'") + # end if + self.__linenum = linenum + self.__nstep = int(tokens[2]) + self.__te_input = float(tokens[3]) + self.__te_output = float(tokens[4]) + self.__heat = float(tokens[5]) + self.__p_surf = float(tokens[6]) + self.__p_top = float(tokens[7]) + self.__eps = eps + else: + raise ValueError(f"Input line ({input_line}) is not a valid entry") + # end if + + def compare(self, log_entry): + """Compare against . + If the entries are equivalent, return an empty list + If the entries differ, return a list of difference messages.""" + errs = [] + if self.__nstep != log_entry.nstep: + errs.append(self.__nstep_diff_msg) + errs.append(f"File 1: nstep = {self.__nstep}") + errs.append(f"File 2: nstep = {log_entry.__nstep}") + else: + diff = self._find_val_diffs(self.__te_input, + log_entry.__te_input, "te_input") + if diff: + errs.append(diff) + # end if + diff = self._find_val_diffs(self.__te_output, + log_entry.__te_output, "te_output") + if diff: + errs.append(diff) + # end if + diff = self._find_val_diffs(self.__heat, + log_entry.__heat, "heat") + if diff: + errs.append(diff) + # end if + diff = self._find_val_diffs(self.__p_surf, + log_entry.__p_surf, "p_surf") + if diff: + errs.append(diff) + # end if + diff = self._find_val_diffs(self.__p_top, + log_entry.__p_top, "p_top") + if diff: + errs.append(diff) + # end if + # end if + + return errs + + def _find_val_diffs(self, val1, val2, key): + """Compare two real values. If they are equal, return None. + If the two values differ, return a list: + Value Header + File 1 value + File 2 value + relative difference + is the type of value being compared + """ + err = None + if val1 == val2: + return err + # end if + if val1 > self.__eps: + diff = abs(val2 - val1) / val1 + else: + diff = abs(val2 - val1) + # end if + f1val = f"{val1:18.16e}" + f2val = f"{val1:18.16e}" + diffval = f"{diff:5.3e}" + err = [' '*6+f"{self.__log_entries[key]}"+' '*(self.__table_spc-len(self.__log_entries[key])-6), + f1val+' '*(self.__table_spc-len(f1val)), f2val+' '*(self.__table_spc-len(f2val)), + diffval+' '*(self.__table_spc-len(diffval))] + return err + + @property + def nstep(self): + """Return the step number of this log entry""" + return self.__nstep + + @property + def linenum(self): + """Return the source line number of this log entry""" + return self.__linenum + + @classmethod + def is_log_entry(cls, input_line): + """Return True iff is a CAM log file energy diagnostic""" + return cls.__entry_re.search(input_line.strip()) is not None + + @classmethod + def nstep_diff_msg(cls): + """Return the special nstep difference error message string""" + return cls.__nstep_diff_msg + +############################################################################### + +def gather_energy_diags_from_log(pathname): + """Gather the energy logs from .""" + if not os.path.exists(pathname): + raise ValueError(f"input file, '{pathname}', does not exist") + # end if + log_entries = {} + linenum = 0 + try: + infile = gzip.open(pathname, "rt") + except gzip.BadGzipFile as exc: + infile = open(pathname, "rt") + # end try + + for line in infile: + linenum += 1 + if LogEntry.is_log_entry(line): + new_entry = LogEntry(line, linenum=linenum) + if new_entry.nstep in log_entries: + emsg = f"Duplicate nstep {new_entry.nstep} on line {linenum}." + emsg += f"\nOriginal entry on line {log_entries[new_entry.nstep].linenum}." + raise ValueError(emsg) + # end if + log_entries[new_entry.nstep] = new_entry + # end if (no else, just ignore other lines) + # end for + + # Don't leave without this + infile.close() + + return log_entries + +############################################################################### + +def compare_log_files(logfile1, logfile2): + """Compare the diagnostics from check_energy of vs. + Report any differences. + Treat as the 'standard' for reporting of relative differences. + Return True iff the files are considered equivalent + """ + + errs = [] + if not os.path.exists(logfile1): + raise ValueError(f"logfile1, '{logfile1}', does not exist") + # end if + if not os.path.exists(logfile2): + raise ValueError(f"logfile2, '{logfile2}', does not exist") + # end if + + log_entries1 = gather_energy_diags_from_log(logfile1) + log_entries2 = gather_energy_diags_from_log(logfile2) + + # We go through the entries from logile2 since it should have a subset + # of the entries from logfile1. + # It is an error for an entry in logfile2 to not be represented on logfile1 + for nstep in log_entries2: + if nstep in log_entries1: + diffs = log_entries1[nstep].compare(log_entries2[nstep]) + if diffs: + if diffs[0] == LogEntry.nstep_diff_msg: + errs.extend(diffs) + else: + errs.append(f"\nnstep {nstep}:") + errs.append(' '*7+f"{''.join([x[0] for x in diffs])}") + errs.append(f"File 1: {''.join([x[1] for x in diffs])}") + errs.append(f"File 2: {''.join([x[2] for x in diffs])}") + errs.append(f"RelDiff: {''.join([x[3] for x in diffs])}") + # end if + # end if + else: + errs.append(f"Log entry for nstep = {nstep} missing on File 2") + # end if + # end for + if errs: + print(f"Energy diagnostics differ:") + print(f"File 1: {logfile1}\nFile 2: {logfile2}:") + print("\n".join(errs)) + else: + print(f"{logfile1} and {logfile2} have equivalent energy diagnostics:") + # end if + +############################################################################### + +def _main_func(): + """Parse the two files to check from the command line + and call the main compare function. + Raise an exception if the input line does not contain two items. + The return value is True if the files are equivalent""" + if len(sys.argv) != 3: + raise ValueError(f"Usage: {sys.argv[0]} ") + # end if + logfile1 = sys.argv[1] + logfile2 = sys.argv[2] + compOK = compare_log_files(logfile1, logfile2) + return compOK + +############################################################################### + +if __name__ == "__main__": + _main_func() diff --git a/cime_config/testdefs/testlist_cam.xml b/cime_config/testdefs/testlist_cam.xml index e2d52f3c29..6990266fe4 100644 --- a/cime_config/testdefs/testlist_cam.xml +++ b/cime_config/testdefs/testlist_cam.xml @@ -26,9 +26,10 @@ - + + From 932ad3cd055749bef937bbf47cca4fa0b5c349eb Mon Sep 17 00:00:00 2001 From: Steve Goldhaber Date: Tue, 24 Oct 2023 21:13:40 +0200 Subject: [PATCH 24/24] Update externals to match new tags for CIME, CAM-Nor phys, and Oslo Aero --- Externals.cfg | 2 +- Externals_CAM.cfg | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/Externals.cfg b/Externals.cfg index 45d8422403..d4f373565e 100644 --- a/Externals.cfg +++ b/Externals.cfg @@ -29,7 +29,7 @@ required = True [cime] protocol = git -tag = cime6.0.105_noresm_v4 +tag = cime6.0.173_noresm_v0 repo_url = https://github.com/NorESMhub/cime.git local_path = cime required = True diff --git a/Externals_CAM.cfg b/Externals_CAM.cfg index 17b5cbfc2d..463f3541e7 100644 --- a/Externals_CAM.cfg +++ b/Externals_CAM.cfg @@ -63,19 +63,15 @@ required = True [camnor_phys] protocol = git -#tag = camnor_noresm_v0.0.3 -branch = feature/oslo_aero_integrate -#repo_url = https://github.com/NorESMhub/CAM-Nor-physics -repo_url = https://github.com/mvertens/CAM-Nor-physics +tag = camnor_noresm_v0.0.5 +repo_url = https://github.com/NorESMhub/CAM-Nor-physics local_path = src/physics/camnor_phys required = True [oslo_aero] protocol = git -#branch = noresm_develop -branch = feature/oslo_aero_integrate -#repo_url = https://github.com/NorESMhub/OSLO_AERO -repo_url = https://github.com/mvertens/OSLO_AERO +tag = noresm_oslo_aero_v0 +repo_url = https://github.com/NorESMhub/OSLO_AERO local_path = src/chemistry/oslo_aero required = True