diff --git a/Externals.cfg b/Externals.cfg
index 1e96526479..dc66b3c485 100644
--- a/Externals.cfg
+++ b/Externals.cfg
@@ -1,5 +1,5 @@
[ccs_config]
-tag = ccs_config_cesm0.0.49
+tag = ccs_config_cesm0.0.59
protocol = git
repo_url = https://github.com/ESMCI/ccs_config_cesm
local_path = ccs_config
@@ -13,7 +13,7 @@ local_path = components/cice5
required = True
[cice6]
-tag = cesm_cice6_2_0_35
+tag = cesm_cice6_4_1_3
protocol = git
repo_url = https://github.com/ESCOMP/CESM_CICE
local_path = components/cice
@@ -21,14 +21,14 @@ externals = Externals.cfg
required = True
[cmeps]
-tag = cmeps0.14.12
+tag = cmeps0.14.24
protocol = git
repo_url = https://github.com/ESCOMP/CMEPS.git
local_path = components/cmeps
required = True
[cdeps]
-tag = cdeps0.12.67
+tag = cdeps1.0.8
protocol = git
repo_url = https://github.com/ESCOMP/CDEPS.git
local_path = components/cdeps
@@ -57,14 +57,14 @@ local_path = libraries/mct
required = True
[parallelio]
-tag = pio2_5_9
+tag = pio2_5_10
protocol = git
repo_url = https://github.com/NCAR/ParallelIO
local_path = libraries/parallelio
required = True
[cime]
-tag = cime6.0.82
+tag = cime6.0.94
protocol = git
repo_url = https://github.com/ESMCI/cime
local_path = cime
@@ -79,7 +79,7 @@ externals = Externals_CISM.cfg
required = True
[clm]
-tag = ctsm5.1.dev114
+tag = ctsm5.1.dev120
protocol = git
repo_url = https://github.com/ESCOMP/CTSM
local_path = components/clm
@@ -96,7 +96,7 @@ externals = Externals_FMS.cfg
required = True
[mosart]
-tag = mosart1_0_47
+tag = mosart1_0_48
protocol = git
repo_url = https://github.com/ESCOMP/MOSART
local_path = components/mosart
diff --git a/Externals_CAM.cfg b/Externals_CAM.cfg
index 15aa548487..7bb8130432 100644
--- a/Externals_CAM.cfg
+++ b/Externals_CAM.cfg
@@ -23,21 +23,21 @@ required = True
local_path = src/physics/clubb
protocol = svn
repo_url = https://github.com/larson-group/clubb_release/tags/
-tag = clubb_4ncar_20221129_59cb19f/src/CLUBB_core
+tag = clubb_4ncar_20221129_59cb19f_20230330_branchtag/src/CLUBB_core
required = True
[silhs]
local_path = src/physics/silhs
protocol = svn
repo_url = https://github.com/larson-group/clubb_release/tags/
-tag = clubb_4ncar_20221129_59cb19f/src/SILHS
+tag = clubb_4ncar_20221129_59cb19f_20230330_branchtag/src/SILHS
required = True
[pumas]
local_path = src/physics/pumas
protocol = git
repo_url = https://github.com/ESCOMP/PUMAS
-tag = pumas_cam-release_v1.28
+tag = pumas_cam-release_v1.29
required = True
[pumas-frozen]
diff --git a/bld/build-namelist b/bld/build-namelist
index 1e6f51d274..2664e46c5a 100755
--- a/bld/build-namelist
+++ b/bld/build-namelist
@@ -851,7 +851,7 @@ if (($chem =~ /waccm_ma/ or $chem =~ /waccm_tsmlt/) and !$chem_rad_passive) {
elsif (($chem =~ /trop_strat/ or $chem =~ /geoschem/) and !$chem_rad_passive) {
$radval .= ",'N:O2:O2','A:CO2:CO2'";
}
-elsif ($co2_cycle and !$co2_cycle_rad_passive) {
+elsif (($co2_cycle and !$co2_cycle_rad_passive) or ($chem =~ /ghg_mam4/)) {
$radval .= ",'N:O2:O2','A:CO2:CO2'";
}
else {
@@ -877,7 +877,7 @@ if ($rad_prog_ozone) {
die "ERROR: can not set ozone rad_climate specification\n";
}
-if ((($chem =~ /waccm_ma/) or ($chem =~ /waccm_sc_mam/) or ($chem =~ /waccm_tsmlt/) or ($chem =~ /trop_strat/)) and !$chem_rad_passive ) {
+if ((($chem =~ /ghg_mam4/) or ($chem =~ /waccm_ma/) or ($chem =~ /waccm_sc_mam/) or ($chem =~ /waccm_tsmlt/) or ($chem =~ /trop_strat/)) and !$chem_rad_passive ) {
$radval .= ",'A:N2O:N2O','A:CH4:CH4','N:CFC11STAR:CFC11','A:CFC12:CFC12'";
} elsif ($prog_ghg1 and $prog_ghg2 and !$chem_rad_passive ) {
$radval .= ",'A:N2O:N2O','A:CH4:CH4','A:CFC11:CFC11','A:CFC12:CFC12'";
@@ -1662,7 +1662,16 @@ if ($chem =~ /waccm_sc/) {
add_default($nl, 'h2orates');
add_default($nl, 'solar_parms_data_file');
}
-
+if ($chem =~ /ghg_mam4/) {
+ add_default($nl, 'h2orates');
+ my $flbc_list = "'CH4','N2O','CO2','CFC11','CFC12'";
+ add_default($nl, 'flbc_list', 'val'=>$flbc_list);
+ unless (defined $nl->get_value('flbc_type')) {
+ add_default($nl, 'flbc_type', 'val'=>'CYCLICAL');
+ add_default($nl, 'flbc_cycle_yr', 'val'=>'2000');
+ }
+ add_default($nl, 'flbc_file');
+}
if ( $prog_species ) {
my $ddval;
my $emisval;
@@ -2350,7 +2359,7 @@ if (($chem =~ /_mam4/ or $chem =~ /_mam5/) and ($phys =~ /cam6/ or $phys =~ /cam
$first = 0;
}
}
- if ($chem eq 'trop_mam4' or $chem eq 'waccm_sc_mam4') {
+ if ($chem eq 'trop_mam4' or $chem eq 'waccm_sc_mam4'or $chem eq 'ghg_mam4') {
# SOA yields (used for the interactive emissions) have been calculated based on the VBS yields in CAM-chem.
# Duseong S. Jo, et al. to be submitted to GMD, 2023 -- see https://github.com/ESCOMP/CAM/pull/727 discussion for additional detail.
my %soae_fctrs = ('BENZENE_an_srf_file' => '3.4192D0',
@@ -2393,8 +2402,8 @@ if (($chem =~ /_mam4/ or $chem =~ /_mam5/) and ($phys =~ /cam6/ or $phys =~ /cam
'num_a2_cv_ext_file' => 'num_a2',
);
- # aircraft emissions
- if ($chem !~ /trop_mam/ and $chem !~ /waccm_sc/) {
+ # air craft emissions
+ if ($chem !~ /trop_mam/ and $chem !~ /ghg_mam/ and $chem !~ /waccm_sc/) {
%species = (%species,
'bc_a4_ar_ext_file' => 'bc_a4',
'num_a4_ar_ext_file' => 'num_a4',
@@ -2450,7 +2459,7 @@ if (($chem =~ /_mam4/ or $chem =~ /_mam5/) and ($phys =~ /cam6/ or $phys =~ /cam
}
# MEGAN emissions
- if (($chem eq 'trop_mam4' or $chem eq 'waccm_sc_mam4') and !$aqua_mode and !$scam){
+ if (($chem eq 'trop_mam4' or $chem eq 'waccm_sc_mam4' or $chem eq 'ghg_mam4') and !$aqua_mode and !$scam){
my $val = "'SOAE = 0.9058*isoprene + 5.8638*(carene_3 + pinene_a + thujene_a + bornene +',"
. "' terpineol_4 + terpineol_a + terpinyl_ACT_a + myrtenal + sabinene + pinene_b + camphene +',"
. "' fenchene_a + limonene + phellandrene_a + terpinene_a + terpinene_g + terpinolene +',"
@@ -2601,10 +2610,10 @@ if (($chem =~ /_mam4/ or $chem =~ /_mam5/) and ($phys =~ /cam6/ or $phys =~ /cam
}
}
-if ($chem eq 'trop_mam4' or $chem eq 'waccm_sc_mam4') {
+if (($chem eq 'trop_mam4') or ($chem eq 'waccm_sc_mam4') or ($chem eq 'ghg_mam4')) {
# Prescribed species
- if ($chem eq 'waccm_sc_mam4') {
+ if (($chem eq 'waccm_sc_mam4')or($chem eq 'ghg_mam4')) {
add_default($nl, 'tracer_cnst_specifier', 'val'=>"'O3','OH','NO3','HO2','HALONS'");
add_default($nl, 'tracer_cnst_file');
add_default($nl, 'tracer_cnst_datapath');
@@ -2731,7 +2740,7 @@ if ($waccmx){
$maxzen = 116.;
} elsif ($chem =~ "trop_strat" or $chem =~ "waccm_") {
$maxzen = 97.01;
-} elsif ($chem =~ "trop_mam" or $chem =~ "trop_mozart") {
+} elsif ($chem =~ "trop_mam" or $chem =~ "trop_mozart" or $chem =~ "ghg_mam") {
$maxzen = 88.85;
}
if ($maxzen>0.0) {
@@ -3145,6 +3154,11 @@ if (!$simple_phys) {
} else {
add_default($nl, 'use_hetfrz_classnuc', 'val'=>'.false.');
}
+ if ($nl->get_value('use_hetfrz_classnuc') =~ m/$TRUE/io) {
+ # set default scaling factors if het frz is turned on
+ add_default($nl, 'hetfrz_bc_scalfac');
+ add_default($nl, 'hetfrz_dust_scalfac');
+ }
add_default($nl, 'use_preexisting_ice');
if ($chem =~ /_mam7/) {
if ($nl->get_value('use_preexisting_ice') =~ m/$TRUE/io) {
@@ -3541,14 +3555,16 @@ if ( length($nl->get_value('soil_erod_file'))>0 ) {
else {
if ($chem =~ /trop_strat/ or $chem =~ /geoschem/ or $chem =~ /waccm_ma/ or $chem =~ /waccm_tsmlt/ or $chem =~ /trop_mozart/) {
add_default($nl, 'dust_emis_fact', 'ver'=>'chem');
- # set scaling of lightning NOx production
- add_default($nl, 'lght_no_prd_factor' );
}
else {
add_default($nl, 'dust_emis_fact');
}
}
}
+if (chem_has_species($cfg, 'NO')) {
+ # set scaling of lightning NOx production
+ add_default($nl, 'lght_no_prd_factor' );
+}
# Seasalt emissions tuning factor
if ($chem =~ /_mam(\d)/) {
@@ -3924,7 +3940,6 @@ if ($dyn =~ /se/) {
my @vars = qw(
se_ftype
se_horz_num_threads
- se_lcp_moist
se_large_Courant_incr
se_hypervis_subcycle
se_hypervis_subcycle_sponge
@@ -3952,7 +3967,6 @@ if ($dyn =~ /se/) {
se_fvm_supercycling_jet
se_kmin_jet
se_kmax_jet
- se_phys_dyn_cp
se_molecular_diff
);
@@ -4177,6 +4191,21 @@ add_default($nl, 'cam_snapshot_before_num');
add_default($nl, 'cam_snapshot_after_num');
check_snapshot_settings();
+if ($opts{'cmeps'}) {
+ # advertise the nature of ozone data passed to surface models
+ if ($rad_prog_ozone) {
+ add_default($nl, 'atm_ozone_frequency', 'val'=>'subdaily');
+ } else {
+ add_default($nl, 'atm_ozone_frequency', 'val'=>'multiday_average');
+ }
+ # for lightning flash freq to CTSM
+ if ($simple_phys or $aqua_mode) {
+ add_default($nl, 'atm_provides_lightning', 'val'=>'.false.');
+ } else {
+ add_default($nl, 'atm_provides_lightning', 'val'=>'.true.');
+ }
+}
+
#-----------------------------------------------------------------------------------------------
# Write output files
@@ -4193,16 +4222,8 @@ my %nl_group = ();
foreach my $name (@nl_groups) { $nl_group{$name} = ''; }
# Dry deposition, MEGAN VOC emis and ozone namelists
-@comp_groups = qw(drydep_inparm megan_emis_nl fire_emis_nl carma_inparm ndep_inparm ozone_coupling_nl);
+@comp_groups = qw(drydep_inparm megan_emis_nl fire_emis_nl carma_inparm ndep_inparm ozone_coupling_nl lightning_coupling_nl);
-# nature of ozone data passed to surface models -- only if cmeps (nuopc) coupling is used
-if ($opts{'cmeps'}) {
- if ($rad_prog_ozone) {
- add_default($nl, 'atm_ozone_frequency', 'val'=>'subdaily');
- } else {
- add_default($nl, 'atm_ozone_frequency', 'val'=>'multiday_average');
- }
-}
$outfile = "$opts{'dir'}/drv_flds_in";
$nl->write($outfile, 'groups'=>\@comp_groups);
if ($print>=1) {
diff --git a/bld/config_files/definition.xml b/bld/config_files/definition.xml
index e198e1bd65..8e14d94c51 100644
--- a/bld/config_files/definition.xml
+++ b/bld/config_files/definition.xml
@@ -98,8 +98,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,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,geoschem_mam4
+
+ 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,geoschem_mam4
Prognostic mozart species packages: list of any subset of the following: DST,SSLT,SO4,GHG,OC,BC,CARBON16
diff --git a/bld/configure b/bld/configure
index 05509afaec..9036a2c10e 100755
--- a/bld/configure
+++ b/bld/configure
@@ -63,7 +63,7 @@ OPTIONS
test_tracers, test_tracers2].
Default: none.
-chem Build CAM with specified prognostic chemistry package
- [ none | terminator | trop_mam3 | trop_mam4 | trop_mam7 | trop_mozart | trop_strat_mam4_ts2 |
+ [ 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 |
@@ -140,10 +140,6 @@ OPTIONS
-verbose [or -v] Turn on verbose echoing of settings made by configure.
-version Echo the CVS tag name used to check out this CAM distribution.
- Options for surface components used in standalone CAM mode:
-
- -ocn Build CAM with ocean model [docn | dom | som | socn | aquaplanet | pop]. Default: aquaplanet
-
Options for building CAM via standalone scripts:
-cam_bld Directory where CAM will be built. This is where configure will write the
diff --git a/bld/namelist_files/namelist_defaults_cam.xml b/bld/namelist_files/namelist_defaults_cam.xml
index 957077df4f..f02a957d53 100644
--- a/bld/namelist_files/namelist_defaults_cam.xml
+++ b/bld/namelist_files/namelist_defaults_cam.xml
@@ -125,6 +125,9 @@
atm/cam/inic/se/FCMTHIST_ne30pg3_1980-01-01_c221214.nc
atm/cam/inic/fv/FC2000mam5_f10_0002-01-01_c221214.nc
+atm/cam/inic/se/FWsc_ne30pg3_58L_GRID_48_taperstart10km_lowtop_BL10_v3_beta1p75_Top_43km.nc
+atm/cam/inic/se/L93_ne30pg3_ne30pg3_mg17_450_short.cam.i.1979-01-07-00000.nc
+
atm/cam/chem/trop_mozart/ic/cami_0000-09-01_4x5_L26_c060217.nc
atm/cam/chem/trop_mozart/ic/cami_0000-09-01_10x15_L26_c060216.nc
@@ -302,7 +305,7 @@
atm/cam/topo/se/ne5pg3_nc3000_Co360_Fi001_MulG_PF_nullRR_Nsw064_20170516.nc
atm/cam/topo/se/ne16pg3_nc3000_Co120_Fi001_PF_nullRR_Nsw084_20171012.nc
-atm/cam/topo/se/ne30pg3_nc3000_Co060_Fi001_PF_nullRR_Nsw042_20171014.nc
+atm/cam/topo/se/ne30pg3_gmted2010_modis_bedmachine_nc3000_Laplace0100_20230105.nc
atm/cam/topo/se/ne60pg3_nc3000_Co030_Fi001_PF_nullRR_Nsw021_20171012.nc
atm/cam/topo/se/ne120pg3_nc3000_Co015_Fi001_PF_nullRR_Nsw010_20171014.nc
atm/cam/topo/se/ne240pg3_nc3000_Co008_Fi001_PF_nullRR_Nsw005_20171015.nc
@@ -572,6 +575,7 @@
atm/cam/ggas/ghg_hist_1765-2005_c091218.nc
atm/waccm/lb/LBC_1765-2100_1.9x2.5_CCMI_RCP60_za_RNOCStrend_c141002.nc
+atm/waccm/lb/LBC_17500116-20150116_CMIP6_0p5degLat_c180905.nc
atm/cam/ggas/emissions-cmip6_CO2_anthro_surface_175001-201512_fv_0.9x1.25_c20181011.nc
@@ -624,6 +628,7 @@
atm/waccm/phot/xh2o_c080826.nc
atm/waccm/phot/xh2o_c080826.nc
+atm/waccm/phot/xh2o_c080826.nc
atm/waccm/ub
@@ -741,8 +746,10 @@
.true.
.true.
.true.
-.false.
.false.
+.false.
+.false.
+.false.
.false.
.false.
.false.
@@ -1819,6 +1826,8 @@
halons_oxid_1.9x2.5zm_L66_1849-2099_c160714.nc
atm/waccm/halons
+halons_oxid_1.9x2.5zm_L66_1849-2099_c160714.nc
+atm/waccm/halons
CYCLICAL
2000
@@ -2243,6 +2252,8 @@
.false.
.true.
.true.
+0.01D0
+0.05D0
.false.
.true.
@@ -2864,14 +2875,16 @@
''
'O', 'O2', 'H', 'N2'
-'Q'
-'Q','CLDLIQ','RAINQM'
-'Q','CLDLIQ','CLDICE'
-'Q','CLDLIQ','CLDICE'
-'Q','CLDLIQ','CLDICE'
-'Q','CLDLIQ','CLDICE'
-'Q','CLDLIQ','CLDICE','RAINQM','SNOWQM'
-'Q','CLDLIQ','CLDICE','RAINQM','SNOWQM'
+'Q'
+'Q'
+'Q'
+'Q','CLDLIQ','RAINQM'
+'Q','CLDLIQ','CLDICE'
+'Q','CLDLIQ','CLDICE'
+'Q','CLDLIQ','CLDICE'
+'Q','CLDLIQ','CLDICE'
+'Q','CLDLIQ','CLDICE','RAINQM','SNOWQM'
+'Q','CLDLIQ','CLDICE','RAINQM','SNOWQM','GRAUQM'
@@ -2969,8 +2982,6 @@
2
- .true.
-
.true.
3.22D0
@@ -2978,6 +2989,7 @@
3
2
4
+ 4
3
1
@@ -2998,8 +3010,6 @@
1.0e99
1.9
-1
-
-1
5.e15
@@ -3287,99 +3297,6 @@
' C3H6_O3 + ISOP_O3 + MVK_O3 + MACR_O3 + MTERP_O3 + BCARY_O3 + S_O3 + SO_O3'
-
-
-
-
-
-
-atm/cam/sst/sst_HadOIBl_bc_0.23x0.31_clim_c061106.nc
-atm/cam/sst/sst_HadOIBl_bc_0.47x0.63_clim_c061106.nc
-atm/cam/sst/sst_HadOIBl_bc_0.9x1.25_clim_c040926a.nc
-atm/cam/sst/sst_HadOIBl_bc_1.9x2.5_clim_c061031.nc
-atm/cam/sst/sst_HadOIBl_bc_2.5x3.33_clim_c091210.nc
-atm/cam/sst/sst_HadOIBl_bc_4x5_clim_c061031.nc
-atm/cam/sst/sst_HadOIBl_bc_10x15_clim_c050526.nc
-
-atm/cam/sst/sst_HadOIBl_bc_256x512_clim_c031031.nc
-atm/cam/sst/sst_HadOIBl_bc_128x256_clim_c050526.nc
-atm/cam/sst/sst_HadOIBl_bc_64x128_clim_c050526.nc
-atm/cam/sst/sst_HadOIBl_bc_48x96_clim_c050526.nc
-atm/cam/sst/sst_HadOIBl_bc_32x64_clim_c050526.nc
-atm/cam/sst/sst_HadOIBl_bc_8x16_clim_c050526.nc
-
-atm/cam/sst/sst_HadOIBl_bc_1x1_clim_c101029.nc
-atm/cam/sst/sst_HadOIBl_bc_1x1_clim_c101029.nc
-
-
-atm/cam/sst/sst_HadOIBl_bc_0.23x0.31_clim_pi_c091020.nc
-atm/cam/sst/sst_HadOIBl_bc_0.47x0.63_clim_pi_c100128.nc
-atm/cam/sst/sst_HadOIBl_bc_0.9x1.25_clim_pi_c100127.nc
-atm/cam/sst/sst_HadOIBl_bc_1.9x2.5_clim_pi_c100127.nc
-atm/cam/sst/sst_HadOIBl_bc_4x5_clim_pi_c100127.nc
-atm/cam/sst/sst_HadOIBl_bc_10x15_clim_pi_c100127.nc
-
-atm/cam/sst/sst_HadOIBl_bc_128x256_clim_pi_c100128.nc
-atm/cam/sst/sst_HadOIBl_bc_64x128_clim_pi_c100128.nc
-atm/cam/sst/sst_HadOIBl_bc_48x96_clim_pi_c100128.nc
-atm/cam/sst/sst_HadOIBl_bc_32x64_clim_pi_c100128.nc
-atm/cam/sst/sst_HadOIBl_bc_8x16_clim_pi_c100128.nc
-
-atm/cam/sst/sst_HadOIBl_bc_1x1_clim_pi_c100129.nc
-atm/cam/sst/sst_HadOIBl_bc_1x1_clim_pi_c100129.nc
-
-
-atm/cam/sst/sst_HadOIBl_bc_0.23x0.31_clim_pi_c091020.nc
-atm/cam/sst/sst_HadOIBl_bc_0.47x0.63_1850_2012_c130411.nc
-atm/cam/sst/sst_HadOIBl_bc_0.9x1.25_1850_2012_c130411.nc
-atm/cam/sst/sst_HadOIBl_bc_1.9x2.5_1850_2012_c130411.nc
-atm/cam/sst/sst_HadOIBl_bc_4x5_1850_2012_c130411.nc
-atm/cam/sst/sst_HadOIBl_bc_10x15_1850_2012_c130411.nc
-
-atm/cam/sst/sst_HadOIBl_bc_128x256_1850_2012_c130411.nc
-atm/cam/sst/sst_HadOIBl_bc_64x128_1850_2012_c130411.nc
-atm/cam/sst/sst_HadOIBl_bc_48x96_1850_2008_c100128.nc
-atm/cam/sst/sst_HadOIBl_bc_32x64_1850_2012_c130411.nc
-atm/cam/sst/sst_HadOIBl_bc_8x16_1850_2012_c130411.nc
-
-atm/cam/sst/sst_HadOIBl_bc_1x1_1850_2012_c130411.nc
-atm/cam/sst/sst_HadOIBl_bc_1x1_1850_2012_c130411.nc
-
-atm/cam/som/cam4.som.forcing.aquaplanet.QzaFix_h50Fix_TspunFix.fv19.nc
-
-
-ocn/docn7/domain.ocn.1x1.111007.nc
-ocn/docn7/domain.ocn.1x1.111007.nc
-
-
-atm/cam/ocnfrac/domain.camocn.128x256_USGS_070807.nc
-share/domains/domain.ocn.T42_gx1v7.180727.nc
-share/domains/domain.ocn.48x96_gx3v7_100114.nc
-atm/cam/ocnfrac/domain.camocn.32x64_USGS_070807.nc
-atm/cam/ocnfrac/domain.camocn.8x16_USGS_070807.nc
-
-atm/cam/ocnfrac/domain.camocn.0.23x0.31_gx1v6_101108.nc
-atm/cam/ocnfrac/domain.camocn.0.47x0.63_gx1v6_090408.nc
-share/domains/domain.ocn.fv0.9x1.25_gx1v7.151020.nc
-share/domains/domain.ocn.fv1.9x2.5_gx1v7.170518.nc
-share/domains/domain.ocn.4x5_gx3v7_100120.nc
-atm/cam/ocnfrac/domain.camocn.10x15_USGS_070807.nc
-
-share/domains/domain.ocn.C24_gx1v7_c200625.nc
-share/domains/domain.ocn.C48_gx1v7_c200625.nc
-share/domains/domain.ocn.C96_gx1v7_c200625.nc
-share/domains/domain.ocn.C192_gx1v7_c200625.nc
-share/domains/domain.ocn.C384_gx1v7_c200625.nc
-
-share/domains/domain.ocn.ne5np4_gx3v7.140810.nc
-share/domains/domain.ocn.ne16np4_gx1v7.171018.nc
-share/domains/domain.ocn.ne30_gx1v7.171003.nc
-share/domains/domain.ocn.ne60np4_gx1v6.121113.nc
-share/domains/domain.ocn.ne120np4_gx1v6.121113.nc
-share/domains/domain.ocn.ne240np4_gx1v6.111226.nc
-
-atm/cam/ocnfrac/domain.aqua.fv1.9x2.5.nc
-
HEMCO_Config.rc
diff --git a/bld/namelist_files/namelist_definition.xml b/bld/namelist_files/namelist_definition.xml
index b7c8d46f50..05fafa608d 100644
--- a/bld/namelist_files/namelist_definition.xml
+++ b/bld/namelist_files/namelist_definition.xml
@@ -1733,7 +1733,7 @@ Default: none
+ group="cam_history_nl" valid_values="A,B,I,X,M,N,L,S" >
Sets the averaging flag for all variables on a particular history file
series. Valid values are:
@@ -1741,6 +1741,7 @@ series. Valid values are:
B ==> GMT 00:00:00 average
I ==> Instantaneous
M ==> Minimum
+ N ==> average over nsteps
X ==> Maximum
L ==> Local-time
S ==> Standard deviation
@@ -1832,6 +1833,7 @@ are:
B ==> GMT 00:00:00 average
I ==> Instantaneous
M ==> Minimum
+ N ==> average over nsteps
X ==> Maximum
L ==> Local-time
S ==> Standard deviation
@@ -1906,27 +1908,27 @@ if .true. then output CLUBBs radiative history statistics
Default: false
-
Same as {{ hilight }}fincl1{{ closehilight }}, but for CLUBB statistics on zt grid.
-
Same as {{ hilight }}fincl1{{ closehilight }}, but for CLUBB statistics on zm grid.
-
Same as {{ hilight }}fincl1{{ closehilight }}, but for CLUBB statistics on radiation zt grid.
-
Same as {{ hilight }}fincl1{{ closehilight }}, but for CLUBB statistics on radiation zm grid.
-
Same as {{ hilight }}fincl1{{ closehilight }}, but for CLUBB statistics on surface.
@@ -2825,6 +2827,18 @@ Add diagnostic output for heterogeneous freezing code.
Default: .false.
+
+Heterogeneous freezing scaling factor for black carbon aerosols.
+Default: 0.01
+
+
+
+Heterogeneous freezing scaling factor for dust aerosols.
+Default: 0.05
+
+
Switch to turn on treatment of pre-existing ice in the ice nucleation code.
@@ -3545,7 +3559,7 @@ Include effects of precip evaporation on turbulent moments
Switch for CLUBB_ADV parameter that turns on advection of CLUBB pdf moments by
-the dynamics core. Very experimental.
+the dynamics core. Very experimental.
@@ -3894,7 +3908,7 @@ xpyp only.
-Flag to apply a locally calculated ustar to momentum surface fluxes in the
+Flag to apply a locally calculated ustar to momentum surface fluxes in the
clubb interface.
@@ -3960,8 +3974,8 @@ Flag to turn on the clubb monotonic flux limiter for vm (meridional momemtum).
-Flag to use an "upwind" discretization rather than a centered discretization
-for the portion of the wp3 turbulent advection term for ADG1 that is linearized
+Flag to use an "upwind" discretization rather than a centered discretization
+for the portion of the wp3 turbulent advection term for ADG1 that is linearized
in terms of wp3(t+1). (Requires ADG1 PDF and l_standard_term_ta=true).
@@ -3988,7 +4002,7 @@ Flag to use smooth Heaviside 'Peskin' in computation of invrs_tau.
-Use the standard discretization for the turbulent advection terms. Setting to
+Use the standard discretization for the turbulent advection terms. Setting to
.false. means that a_1 and a_3 are pulled outside of the derivative in
advance_wp2_wp3_module.F90 and in advance_xp2_xpyp_module.F90.
@@ -4070,7 +4084,7 @@ production) term.
-Flag used to calculate convective velocity using a variable estimate of layer
+Flag used to calculate convective velocity using a variable estimate of layer
depth based on the depth over which wpthlp is positive near the ground when true
@@ -4764,7 +4778,7 @@ Default: set by build-namelist
+
+History tape number thermo budget output is written to.
+Default: 1
+
+
+
+Produce output for the energy budget diagnostic package.
+Default: .false.
+
@@ -6211,14 +6236,8 @@ List of species that are constrained in the stratosphere.
Default: set by build-namelist.
-
-Full pathname of dataset for land mask applied to the lighting NOx production
-Default: set by build-namelist.
-
-
+ group="lightning_nl" valid_values="" >
Multiplication factor applied to the lighting NOx production
Default: 1.0.
@@ -7260,6 +7279,36 @@ List of nitrogen deposition fluxes to be sent from CAM to surface models.
Default: set by build-namelist.
+
+Year first to use in nitrogen deposition stream data. Set by case xml variable
+CAM_STREAM_NDEP_YEAR_FIRST
+
+
+
+Year last to use in nitrogen deposition stream data.
+Set by case xml variable CAM_STREAM_NDEP_YEAR_LAST
+
+
+
+Model year to align with CAM_STREAM_NDEP_YEAR_FIRST.
+Set by case xml variable CAM_STREAM_NDEP_YEAR_ALIGN
+
+
+
+NDEP stream data filename.
+Set by case xml variable CAM_STREAM_NDEP_DATA_FILENAME.
+
+
+
+NDEP mesh file corresponding to sream_ndep_data_filename.
+Set by case xml variable CAM_STREAM_NDEP_MESH_FILENAME.
+
+
File containing MEGAN emissions factors.
@@ -7296,6 +7345,12 @@ coarser temporal resolution.
Default: set by build-namelist.
+
+If TRUE atmosphere model will provide prognosed lightning flash frequency.
+Default: FALSE
+
+
-
-Scaling of temperature increment for different levels of
-thermal energy consistency.
-0: no scaling
-1: scale increment for cp consistency between dynamics and physics
-2: do 1 as well as take into account condensate effect on thermal energy
-Default: Set by build-namelist.
-
-
Hyperviscosity coefficient for u,v, T [m^4/s].
@@ -7730,17 +7775,6 @@ If < 0, se_sponge_del4_lev is automatically set based on model top location.
Default: Set by build-namelist.
-
-If TRUE the continous equations the dynamical core is based on will conserve a
-comprehensive moist total energy
-If FALSE the continous equations the dynamical core is based on will conserve
-a total energy based on cp for dry air and no condensates (same total energy as
-CAM physics uses).
-For more details see Lauritzen et al., (2018;DOI:10.1029/2017MS001257)
-Default: TRUE
-
-
If TRUE the CSLAM algorithm will work for Courant number larger than 1 with
@@ -8285,30 +8319,6 @@ us_standard_atmosphere: static atmospheric state (u,v)=0, standard lapse rate fo
Default: 'none'
-
-
-
-
-
-Full pathname of time-variant sea-surface temperature and sea-ice
-concentration boundary dataset.
-Default: set by build-namelist.
-
-
-
-Full pathname of
-Default: set by build-namelist.
-
-
-
-Full pathname of grid file for time-variant sea-surface temperature and sea-ice
-concentration boundary dataset.
-Default: set by build-namelist.
-
-
+
+
+
+
+
+
+
+Stream filename(s) for Nitrogen Deposition data
+
+
+
+Stream meshfile for Nitrogen Deposition data
+
+
+
+First year to loop over for Nitrogen Deposition data
+
+
+
+Last year to loop over for Nitrogen Deposition data
+
+
+
+Simulation year that aligns with stream_year_first_ndep value
+
+
diff --git a/bld/namelist_files/use_cases/1850-2005_cam5.xml b/bld/namelist_files/use_cases/1850-2005_cam5.xml
index 8a6c2a7f0c..5d4a572be0 100644
--- a/bld/namelist_files/use_cases/1850-2005_cam5.xml
+++ b/bld/namelist_files/use_cases/1850-2005_cam5.xml
@@ -56,35 +56,11 @@
INTERP_MISSING_MONTHS
- atm/cam/chem/trop_mozart_aero/oxid
- oxid_1.9x2.5_L26_1850-2005_c091123.nc
- INTERP_MISSING_MONTHS
+ atm/cam/chem/trop_mozart_aero/oxid
+ oxid_1.9x2.5_L26_1850-2005_c091123.nc
+ INTERP_MISSING_MONTHS
1850-2000
-
-.false.
-1850
-2012
-2008
-
-atm/cam/sst/sst_HadOIBl_bc_0.47x0.63_1850_2012_c130411.nc
-atm/cam/sst/sst_HadOIBl_bc_0.9x1.25_1850_2012_c130411.nc
-atm/cam/sst/sst_HadOIBl_bc_1.9x2.5_1850_2012_c130411.nc
-atm/cam/sst/sst_HadOIBl_bc_4x5_1850_2012_c130411.nc
-atm/cam/sst/sst_HadOIBl_bc_10x15_1850_2012_c130411.nc
-
-atm/cam/sst/sst_HadOIBl_bc_128x256_1850_2012_c130411.nc
-atm/cam/sst/sst_HadOIBl_bc_64x128_1850_2012_c130411.nc
-atm/cam/sst/sst_HadOIBl_bc_48x96_1850_2008_c100128.nc
-atm/cam/sst/sst_HadOIBl_bc_32x64_1850_2012_c130411.nc
-atm/cam/sst/sst_HadOIBl_bc_8x16_1850_2012_c130411.nc
-
-
-.true.
-0
-0
-atm/cam/sst/sst_HadOIBl_bc_0.23x0.31_clim_pi_c091020.nc
-
diff --git a/bld/namelist_files/use_cases/1850_cam_lt.xml b/bld/namelist_files/use_cases/1850_cam_lt.xml
new file mode 100644
index 0000000000..f3c043d55b
--- /dev/null
+++ b/bld/namelist_files/use_cases/1850_cam_lt.xml
@@ -0,0 +1,67 @@
+
+
+
+
+atm/cam/solar/SolarForcingCMIP6piControl_c160921.nc
+ 18500101
+ FIXED
+
+
+atm/cam/inic/se/FWsc_ne30pg3_58L_GRID_48_taperstart10km_lowtop_BL10_v3_beta1p75_Top_43km.nc
+
+
+atm/waccm/lb/LBC_17500116-20150116_CMIP6_0p5degLat_c180905.nc
+1850
+'CYCLICAL'
+'CO2','CH4','N2O','CFC11','CFC12','CFC11eq'
+
+
+'Q:H2O->UBC_FILE'
+atm/cam/chem/ubc/b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensAvg123.cam.h0zm.H2O.185001-201412_c230509cdf5.nc
+CYCLICAL
+1850
+
+
+ 'atm/cam/ozone_strataero'
+ 'ozone_strataero_cyclical_WACCM6_L70_CMIP6-piControl.001_y21-50avg_zm_5day_c180802.nc'
+ 'O3'
+ CYCLICAL
+ 1850
+
+
+ 1850
+ 'atm/cam/ozone_strataero'
+ 'ozone_strataero_cyclical_WACCM6_L70_CMIP6-piControl.001_y21-50avg_zm_5day_c180802.nc'
+ .true.
+ 'CYCLICAL'
+
+
+
+ 1850
+ 'atm/cam/tracer_cnst'
+ 'tracer_cnst_WACCM6_halons_3DmonthlyL70_1850climoCMIP6piControl001_y21-50avg_c180802.nc'
+ 'O3','OH','NO3','HO2','HALONS'
+ 'CYCLICAL'
+ ''
+
+
+ CYCLICAL
+ 1850
+
+ 'num_a1 -> $INPUTDATA_ROOT/atm/cam/chem/emis/historical_ne30pg3/emissions-cmip6_num_so4_a1_anthro-ene_vertical_mol_175001-201412_ne30pg3_c20200103.nc',
+ 'num_a1 -> $INPUTDATA_ROOT/atm/cam/chem/emis/historical_ne30pg3/emissions-cmip6_num_a1_so4_contvolcano_vertical_850-5000_ne30pg3_c20200125.nc',
+ 'num_a2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/historical_ne30pg3/emissions-cmip6_num_a2_so4_contvolcano_vertical_850-5000_ne30pg3_c20200125.nc',
+ 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/historical_ne30pg3/emissions-cmip6_SO2_contvolcano_vertical_850-5000_ne30pg3_c20200125.nc',
+ 'so4_a1 -> $INPUTDATA_ROOT/atm/cam/chem/emis/historical_ne30pg3/emissions-cmip6_so4_a1_anthro-ene_vertical_mol_175001-201412_ne30pg3_c20200103.nc',
+ 'so4_a1 -> $INPUTDATA_ROOT/atm/cam/chem/emis/historical_ne30pg3/emissions-cmip6_so4_a1_contvolcano_vertical_850-5000_ne30pg3_c20200125.nc',
+ 'so4_a2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/historical_ne30pg3/emissions-cmip6_so4_a2_contvolcano_vertical_850-5000_ne30pg3_c20200125.nc'
+
+
+
+ CYCLICAL
+ 1850
+
+CYCLICAL
+1850
+
+
diff --git a/bld/namelist_files/use_cases/1850_cam_mt.xml b/bld/namelist_files/use_cases/1850_cam_mt.xml
new file mode 100644
index 0000000000..67049703f3
--- /dev/null
+++ b/bld/namelist_files/use_cases/1850_cam_mt.xml
@@ -0,0 +1,62 @@
+
+
+
+
+atm/cam/solar/SolarForcingCMIP6piControl_c160921.nc
+ 18500101
+ FIXED
+
+
+atm/cam/inic/se/L93_ne30pg3_ne30pg3_mg17_450_short.cam.i.1979-01-07-00000.nc
+
+
+atm/waccm/lb/LBC_17500116-20150116_CMIP6_0p5degLat_c180905.nc
+1850
+'CYCLICAL'
+'CO2','CH4','N2O','CFC11','CFC12','CFC11eq'
+
+
+
+ 'atm/cam/ozone_strataero'
+ 'ozone_strataero_cyclical_WACCM6_L70_CMIP6-piControl.001_y21-50avg_zm_5day_c180802.nc'
+ 'O3'
+ CYCLICAL
+ 1850
+
+
+ 1850
+ 'atm/cam/ozone_strataero'
+ 'ozone_strataero_cyclical_WACCM6_L70_CMIP6-piControl.001_y21-50avg_zm_5day_c180802.nc'
+ .true.
+ 'CYCLICAL'
+
+
+
+ 1850
+ 'atm/cam/tracer_cnst'
+ 'tracer_cnst_WACCM6_halons_3DmonthlyL70_1850climoCMIP6piControl001_y21-50avg_c180802.nc'
+ 'O3','OH','NO3','HO2','HALONS'
+ 'CYCLICAL'
+ ''
+
+
+ CYCLICAL
+ 1850
+
+ 'num_a1 -> $INPUTDATA_ROOT/atm/cam/chem/emis/historical_ne30pg3/emissions-cmip6_num_so4_a1_anthro-ene_vertical_mol_175001-201412_ne30pg3_c20200103.nc',
+ 'num_a1 -> $INPUTDATA_ROOT/atm/cam/chem/emis/historical_ne30pg3/emissions-cmip6_num_a1_so4_contvolcano_vertical_850-5000_ne30pg3_c20200125.nc',
+ 'num_a2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/historical_ne30pg3/emissions-cmip6_num_a2_so4_contvolcano_vertical_850-5000_ne30pg3_c20200125.nc',
+ 'SO2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/historical_ne30pg3/emissions-cmip6_SO2_contvolcano_vertical_850-5000_ne30pg3_c20200125.nc',
+ 'so4_a1 -> $INPUTDATA_ROOT/atm/cam/chem/emis/historical_ne30pg3/emissions-cmip6_so4_a1_anthro-ene_vertical_mol_175001-201412_ne30pg3_c20200103.nc',
+ 'so4_a1 -> $INPUTDATA_ROOT/atm/cam/chem/emis/historical_ne30pg3/emissions-cmip6_so4_a1_contvolcano_vertical_850-5000_ne30pg3_c20200125.nc',
+ 'so4_a2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/historical_ne30pg3/emissions-cmip6_so4_a2_contvolcano_vertical_850-5000_ne30pg3_c20200125.nc'
+
+
+
+ CYCLICAL
+ 1850
+
+CYCLICAL
+1850
+
+
diff --git a/bld/namelist_files/use_cases/2000_cam6.xml b/bld/namelist_files/use_cases/2000_cam6.xml
index 56195092cd..fef59dc7d3 100644
--- a/bld/namelist_files/use_cases/2000_cam6.xml
+++ b/bld/namelist_files/use_cases/2000_cam6.xml
@@ -2,13 +2,15 @@
-
- 2000
- atm/cam/ozone
- tracer_cnst_CAM6chem_2000climo_3D_monthly_c171004.nc
- ''
- 'O3','OH','NO3','HO2'
- 'CYCLICAL'
+atm/cam/ozone
+tracer_cnst_CAM6chem_2000climo_3D_monthly_c171004.nc
+'O3','OH','NO3','HO2'
+atm/cam/tracer_cnst
+tracer_cnst_halons_3D_L70_1849-2015_CMIP6ensAvg_c180927.nc
+'O3','OH','NO3','HO2','HALONS'
+2000
+CYCLICAL
+''
2000
atm/cam/ozone
diff --git a/bld/namelist_files/use_cases/aquaplanet_cam3.xml b/bld/namelist_files/use_cases/aquaplanet_cam3.xml
index 3fd3d876cb..373b2ad18d 100644
--- a/bld/namelist_files/use_cases/aquaplanet_cam3.xml
+++ b/bld/namelist_files/use_cases/aquaplanet_cam3.xml
@@ -57,9 +57,6 @@
-
-.true.
-
86164.10063718943
6.37100e6
@@ -78,4 +75,3 @@
0
-
diff --git a/bld/namelist_files/use_cases/aquaplanet_cam4.xml b/bld/namelist_files/use_cases/aquaplanet_cam4.xml
index a18f4cfcd0..67d32c9f9f 100644
--- a/bld/namelist_files/use_cases/aquaplanet_cam4.xml
+++ b/bld/namelist_files/use_cases/aquaplanet_cam4.xml
@@ -31,8 +31,6 @@
-
-.true.
86164.10063718943
6.37100e6
@@ -45,4 +43,3 @@
.false.
-
diff --git a/bld/namelist_files/use_cases/aquaplanet_cam5.xml b/bld/namelist_files/use_cases/aquaplanet_cam5.xml
index afc820ecef..814eecd98f 100644
--- a/bld/namelist_files/use_cases/aquaplanet_cam5.xml
+++ b/bld/namelist_files/use_cases/aquaplanet_cam5.xml
@@ -29,10 +29,6 @@
CYCLICAL
1990
-
-.true.
-
-
86164.10063718943
6.37100e6
@@ -50,4 +46,3 @@
""
-
diff --git a/bld/namelist_files/use_cases/aquaplanet_cam6.xml b/bld/namelist_files/use_cases/aquaplanet_cam6.xml
index cbe41e8cee..814eecd98f 100644
--- a/bld/namelist_files/use_cases/aquaplanet_cam6.xml
+++ b/bld/namelist_files/use_cases/aquaplanet_cam6.xml
@@ -29,9 +29,6 @@
CYCLICAL
1990
-
-.true.
-
86164.10063718943
6.37100e6
@@ -49,4 +46,3 @@
""
-
diff --git a/bld/namelist_files/use_cases/aquaplanet_rce_cam6.xml b/bld/namelist_files/use_cases/aquaplanet_rce_cam6.xml
index 01d810b08d..f03c4294b2 100644
--- a/bld/namelist_files/use_cases/aquaplanet_rce_cam6.xml
+++ b/bld/namelist_files/use_cases/aquaplanet_rce_cam6.xml
@@ -44,9 +44,6 @@
CYCLICAL
1990
-
-.true.
-
.true.
0.73391095
@@ -71,4 +68,3 @@
0.0
-
diff --git a/bld/namelist_files/use_cases/hist_cam_lt.xml b/bld/namelist_files/use_cases/hist_cam_lt.xml
new file mode 100644
index 0000000000..577610275c
--- /dev/null
+++ b/bld/namelist_files/use_cases/hist_cam_lt.xml
@@ -0,0 +1,48 @@
+
+
+
+19790101
+
+
+atm/cam/solar/SolarForcingCMIP6_18491230-23000102_c20200615.nc
+
+
+atm/cam/inic/se/FWsc_ne30pg3_58L_GRID_48_taperstart10km_lowtop_BL10_v3_beta1p75_Top_43km.nc
+
+
+atm/waccm/lb/LBC_17500116-20150116_CMIP6_0p5degLat_c180905.nc
+'SERIAL'
+'CO2','CH4','N2O','CFC11','CFC12','CFC11eq'
+
+
+'Q:H2O->UBC_FILE'
+atm/cam/chem/ubc/f.e21.FWHISTBgcCrop.f09_f09_mg17.CMIP6-AMIP-WACCM.ensAvg123.cam.h0zm.UBC.195001-201412_c220322.nc
+'SERIAL'
+
+
+ 'atm/cam/ozone_strataero'
+ 'ozone_strataero_WACCM_L70_zm5day_18500101-20150103_CMIP6ensAvg_c180923.nc'
+ 'O3'
+ SERIAL
+
+
+ .true.
+ 'atm/cam/ozone_strataero'
+ 'ozone_strataero_WACCM_L70_zm5day_18500101-20150103_CMIP6ensAvg_c180923.nc'
+ SERIAL
+
+
+ 'atm/cam/tracer_cnst'
+ 'tracer_cnst_halons_3D_L70_1849-2015_CMIP6ensAvg_c180927.nc'
+ 'O3','OH','NO3','HO2','HALONS'
+ INTERP_MISSING_MONTHS
+ ''
+
+
+INTERP_MISSING_MONTHS
+
+
+INTERP_MISSING_MONTHS
+SERIAL
+
+
diff --git a/bld/namelist_files/use_cases/hist_cam_mt.xml b/bld/namelist_files/use_cases/hist_cam_mt.xml
new file mode 100644
index 0000000000..08c53aa595
--- /dev/null
+++ b/bld/namelist_files/use_cases/hist_cam_mt.xml
@@ -0,0 +1,43 @@
+
+
+
+19790101
+
+
+atm/cam/solar/SolarForcingCMIP6_18491230-23000102_c20200615.nc
+
+
+atm/cam/inic/se/L93_ne30pg3_ne30pg3_mg17_450_short.cam.i.1979-01-07-00000.nc
+
+
+atm/waccm/lb/LBC_17500116-20150116_CMIP6_0p5degLat_c180905.nc
+'SERIAL'
+'CO2','CH4','N2O','CFC11','CFC12','CFC11eq'
+
+
+ 'atm/cam/ozone_strataero'
+ 'ozone_strataero_WACCM_L70_zm5day_18500101-20150103_CMIP6ensAvg_c180923.nc'
+ 'O3'
+ SERIAL
+
+
+ .true.
+ 'atm/cam/ozone_strataero'
+ 'ozone_strataero_WACCM_L70_zm5day_18500101-20150103_CMIP6ensAvg_c180923.nc'
+ SERIAL
+
+
+ 'atm/cam/tracer_cnst'
+ 'tracer_cnst_halons_3D_L70_1849-2015_CMIP6ensAvg_c180927.nc'
+ 'O3','OH','NO3','HO2','HALONS'
+ INTERP_MISSING_MONTHS
+ ''
+
+
+INTERP_MISSING_MONTHS
+
+
+INTERP_MISSING_MONTHS
+SERIAL
+
+
diff --git a/bld/namelist_files/use_cases/sd_waccm_sulfur.xml b/bld/namelist_files/use_cases/sd_waccm_sulfur.xml
index f45159054a..25c4d622de 100644
--- a/bld/namelist_files/use_cases/sd_waccm_sulfur.xml
+++ b/bld/namelist_files/use_cases/sd_waccm_sulfur.xml
@@ -139,27 +139,4 @@
1850-2000
-
-.false.
-1850
-2008
-
-atm/cam/sst/sst_HadOIBl_bc_0.47x0.63_1850_2008_c100128.nc
-atm/cam/sst/sst_HadOIBl_bc_0.9x1.25_1850_2008_c100127.nc
-atm/cam/sst/sst_HadOIBl_bc_1.9x2.5_1850_2008_c100127.nc
-atm/cam/sst/sst_HadOIBl_bc_4x5_1850_2008_c100127.nc
-atm/cam/sst/sst_HadOIBl_bc_10x15_1850_2008_c100127.nc
-
-atm/cam/sst/sst_HadOIBl_bc_128x256_1850_2008_c100128.nc
-atm/cam/sst/sst_HadOIBl_bc_64x128_1850_2008_c100128.nc
-atm/cam/sst/sst_HadOIBl_bc_48x96_1850_2008_c100128.nc
-atm/cam/sst/sst_HadOIBl_bc_32x64_1850_2008_c100128.nc
-atm/cam/sst/sst_HadOIBl_bc_8x16_1850_2008_c100128.nc
-
-
-.true.
-0
-0
-atm/cam/sst/sst_HadOIBl_bc_0.23x0.31_clim_pi_c091020.nc
-
diff --git a/bld/namelist_files/use_cases/waccm_carma_bc_2013_cam4.xml b/bld/namelist_files/use_cases/waccm_carma_bc_2013_cam4.xml
index ff2a72cbcc..a6e5287553 100644
--- a/bld/namelist_files/use_cases/waccm_carma_bc_2013_cam4.xml
+++ b/bld/namelist_files/use_cases/waccm_carma_bc_2013_cam4.xml
@@ -46,12 +46,12 @@
atm/waccm/sulf/SAD_SULF_1849-2100_1.9x2.5_c090817.nc
'SERIAL'
-
+
.false.
atm/waccm/qbo/qbocoefficients_c091230.nc'
-.true.
+.true.
@@ -75,42 +75,42 @@
0, -240, -240, -24, -24
'A', 'I', 'I', 'A', 'A'
-
+
- 'AOA1', 'AOA2', 'BR', 'BRCL', 'BRO', 'BRONO2', 'CCL4', 'CF2CLBR', 'CF3BR',
- 'CFC11', 'CFC113', 'CFC12', 'CH2O', 'CH3BR', 'CH3CCL3', 'CH3CL', 'CH3O2', 'CH3OOH',
- 'CH4', 'CL', 'CL2', 'CL2O2', 'CLDHGH', 'CLDLOW', 'CLDMED', 'CLDTOT', 'CLO', 'CLONO2',
- 'CLOUD', 'CO', 'CO2', 'DTCOND', 'DTV', 'DUV', 'DVV', 'EKGW', 'FLNS', 'FLNSC', 'FLNT',
+ 'AOA1', 'AOA2', 'BR', 'BRCL', 'BRO', 'BRONO2', 'CCL4', 'CF2CLBR', 'CF3BR',
+ 'CFC11', 'CFC113', 'CFC12', 'CH2O', 'CH3BR', 'CH3CCL3', 'CH3CL', 'CH3O2', 'CH3OOH',
+ 'CH4', 'CL', 'CL2', 'CL2O2', 'CLDHGH', 'CLDLOW', 'CLDMED', 'CLDTOT', 'CLO', 'CLONO2',
+ 'CLOUD', 'CO', 'CO2', 'DTCOND', 'DTV', 'DUV', 'DVV', 'EKGW', 'FLNS', 'FLNSC', 'FLNT',
'FLNTC', 'FSDS', 'FSNS', 'FSNSC', 'FSNT', 'FSNTC', 'H', 'H2', 'H2O', 'H2O2', 'HBR',
'HCFC22', 'HCL', 'HNO3', 'HO2', 'HO2NO2', 'HOBR', 'HOCL', 'HORZ', 'LANDFRAC', 'LHFLX',
'N', 'N2O', 'N2O5', 'NO', 'NO2', 'NO3', 'O', 'O1D', 'O2', 'O3',
'OCLO', 'OCNFRAC', 'OH', 'OMEGA', 'PHIS', 'PRECC', 'PRECL', 'PS', 'Q', 'QFLX',
'QPERT', 'QRL', 'QRLNLTE', 'QRS', 'RELHUM', 'SHFLX', 'SOLIN', 'SWCF', 'QCP',
- 'QTHERMAL', 'QRL_TOT', 'QRS_TOT', 'QJOULE', 'PSL', 'HNO3_STS', 'HNO3_NAT',
- 'HNO3_GAS', 'NO_Aircraft', 'NO_Lightning', 'QNO', 'QRS_AUR', 'QRS_CO2NIR', 'QRS_EUV',
- 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'T', 'TREFHT',
- 'TTGW', 'U', 'UTGWORO', 'UTGWSPEC', 'V', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'O2_1S',
- 'O2_1D', 'NOX', 'NOY', 'CLOX', 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'QJOULE', 'UI',
+ 'QTHERMAL', 'QRL_TOT', 'QRS_TOT', 'QJOULE', 'PSL', 'HNO3_STS', 'HNO3_NAT',
+ 'HNO3_GAS', 'NO_Aircraft', 'NO_Lightning', 'QNO', 'QRS_AUR', 'QRS_CO2NIR', 'QRS_EUV',
+ 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'T', 'TREFHT',
+ 'TTGW', 'U', 'UTGWORO', 'UTGWSPEC', 'V', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'O2_1S',
+ 'O2_1D', 'NOX', 'NOY', 'CLOX', 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'QJOULE', 'UI',
'VI', 'UIONTEND', 'VIONTEND', 'DTCORE', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN',
'OMEGA_24_COS', 'OMEGA_24_SIN', 'OMEGA_12_COS', 'OMEGA_12_SIN',
- 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS',
+ 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS',
'V_12_SIN', 'PS_24_COS', 'PS_24_SIN', 'PS_12_COS', 'PS_12_SIN', 'CLDLIQ','CLDICE','CONCLD',
'FRONTGF:I', 'BUTGWSPEC', 'BTAUE', 'BTAUW', 'BTAUN', 'BTAUS','TAUE','TAUW','TAUN','TAUS',
'TAUGWX', 'TAUGWY', 'TAUX','TAUY','SNOWHLND','SNOWHICE','ICEFRAC','FSDSC','SFNO', 'SFCO',
'SFCH2O','CFC11STAR','TROPP_FD'
-
+
- 'PS', 'Z3', 'T', 'U', 'V', 'FLNT','PSL',
+ 'PS', 'Z3', 'T', 'U', 'V', 'FLNT','PSL',
'OMEGA','FSDS','FSDSC','CLOUD','CONCLD','SNOWHLND','SNOWHICE',
- 'CH3CL', 'CFC11', 'CFC12', 'CFC113', 'HCFC22', 'CCL4', 'CH3CCL3',
+ 'CH3CL', 'CFC11', 'CFC12', 'CFC113', 'HCFC22', 'CCL4', 'CH3CCL3',
'CH3BR', 'CF3BR', 'CF2CLBR',
'CO', 'CO2', 'CH2O', 'CH3OOH', 'CH4',
'O3', 'O', 'O1D',
'N', 'NO', 'NO2', 'NO3', 'N2O5', 'HNO3', 'HO2NO2', 'NOX', 'NOY', 'N2O',
'H', 'H2', 'OH', 'HO2', 'H2O2', 'H2O',
- 'CL','CL2', 'CLO', 'OCLO', 'CL2O2', 'CLONO2', 'HOCL', 'HCL', 'CLOX', 'CLOY',
+ 'CL','CL2', 'CLO', 'OCLO', 'CL2O2', 'CLONO2', 'HOCL', 'HCL', 'CLOX', 'CLOY',
'BR', 'BRO', 'HOBR', 'HBR', 'BRCL', 'BRONO2', 'BROX', 'BROY', 'TCLY',
'jo2_a', 'jo2_b', 'jo3_a', 'jo3_b', 'jhocl', 'jno3_b', 'jcl2o2',
'SAD_SULFC', 'SAD_LNAT', 'SAD_ICE','AOA1','AOA2',
@@ -118,7 +118,7 @@
'VTHzm', 'WTHzm', 'UVzm', 'UWzm', 'TH', 'MSKtem'
-
+
'PS:B', 'T:B', 'Z3:B', 'U:B', 'V:B', 'CO:B', 'CO2:B',
'H2:B', 'O:B', 'O2:B', 'O3:B', 'H:B', 'OH:B', 'HO2:B', 'H2O:B',
@@ -126,11 +126,11 @@
'Np:B', 'N2p:B', 'Op:B', 'O2p:B', 'NOp:B', 'e:B', 'QRL_TOT:B',
'QRS_TOT:B', 'QJOULE:B', 'jno3_a:B', 'jno3_b:B', 'jcl2o2:B', 'CL2O2:B', 'CLO:B',
'BRO:B', 'NO3:B', 'DTCORE:B', 'DTV:B', 'TTGW:B','OMEGA:B'
-
+
- 'PS', 'PSL', 'U', 'V', 'T', 'Z3', 'PHIS','FRONTGF:I', 'OMEGA'
+ 'PS', 'PSL', 'U', 'V', 'T', 'Z3', 'PHIS','FRONTGF:I', 'OMEGA'
-
+
'MSKtem', 'PS', 'PSL', 'VTHzm', 'UVzm', 'UWzm', 'Uzm', 'Vzm', 'THzm','Wzm', 'PHIS'
@@ -138,27 +138,4 @@
1850-2000
-
-.false.
-1850
-2008
-
-atm/cam/sst/sst_HadOIBl_bc_0.47x0.63_1850_2008_c100128.nc
-atm/cam/sst/sst_HadOIBl_bc_0.9x1.25_1850_2008_c100127.nc
-atm/cam/sst/sst_HadOIBl_bc_1.9x2.5_1850_2008_c100127.nc
-atm/cam/sst/sst_HadOIBl_bc_4x5_1850_2008_c100127.nc
-atm/cam/sst/sst_HadOIBl_bc_10x15_1850_2008_c100127.nc
-
-atm/cam/sst/sst_HadOIBl_bc_128x256_1850_2008_c100128.nc
-atm/cam/sst/sst_HadOIBl_bc_64x128_1850_2008_c100128.nc
-atm/cam/sst/sst_HadOIBl_bc_48x96_1850_2008_c100128.nc
-atm/cam/sst/sst_HadOIBl_bc_32x64_1850_2008_c100128.nc
-atm/cam/sst/sst_HadOIBl_bc_8x16_1850_2008_c100128.nc
-
-
-.true.
-0
-0
-atm/cam/sst/sst_HadOIBl_bc_0.23x0.31_clim_pi_c091020.nc
-
diff --git a/cime_config/buildnml b/cime_config/buildnml
index ca44b885d5..c35f7c6243 100755
--- a/cime_config/buildnml
+++ b/cime_config/buildnml
@@ -48,6 +48,12 @@ def buildnml(case, caseroot, compname):
RUN_REFTOD = case.get_value("RUN_REFTOD")
COMP_INTERFACE = case.get_value("COMP_INTERFACE")
+ stream_ndep_year_first = case.get_value("CAM_STREAM_NDEP_YEAR_FIRST")
+ stream_ndep_year_last = case.get_value("CAM_STREAM_NDEP_YEAR_LAST")
+ stream_ndep_year_align = case.get_value("CAM_STREAM_NDEP_YEAR_ALIGN")
+ stream_ndep_data_filename = case.get_value("CAM_STREAM_NDEP_DATA_FILENAME")
+ stream_ndep_mesh_filename = case.get_value("CAM_STREAM_NDEP_MESH_FILENAME")
+
testsrc = os.path.join(srcroot, "components", "cam")
if os.path.exists(testsrc):
srcroot = testsrc
@@ -167,6 +173,12 @@ def buildnml(case, caseroot, compname):
buildnl_opts += ["-inputdata", input_data_list]
+ CAM_NAMELIST_OPTS += " stream_ndep_year_first=" + stream_ndep_year_first
+ CAM_NAMELIST_OPTS += " stream_ndep_year_last=" + stream_ndep_year_last
+ CAM_NAMELIST_OPTS += " stream_ndep_year_align=" + stream_ndep_year_align
+ CAM_NAMELIST_OPTS += " stream_ndep_data_filename='" + stream_ndep_data_filename.strip() + "'"
+ CAM_NAMELIST_OPTS += " stream_ndep_mesh_filename='" + stream_ndep_mesh_filename.strip() + "'"
+
buildnl_opts += ["-namelist",
'" &atmexp ' + CAM_NAMELIST_OPTS + '/" ']
diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml
index b09dd13d17..a31f354dc5 100644
--- a/cime_config/config_component.xml
+++ b/cime_config/config_component.xml
@@ -13,7 +13,7 @@
CAM cam4 physics:
CAM cam3 physics:
CAM simplified and non-versioned physics :
- CAM7 development physics:
+ CAM7 development physics:
- 58 vertical layers:
- 93 vertical layers:
CAM-Chem troposphere/stratosphere chemistry with simplified VBS-SOA:
CAM-Chem troposphere/stratosphere chemistry with simplified VBS-SOA and expanded isoprene and terpene oxidation:
GEOS-Chem troposphere/stratosphere chemistry :
CAM-Chem troposphere/stratosphere chem with simplified volatility basis set SOA scheme and fire emissons :
CAM CLUBB - turned on by default in CAM60:
- CAM-Chem troposphere/stratosphere chem with extended volatility basis set SOA scheme and modal aerosols :
+ CAM-Chem troposphere/stratosphere chem with extended volatility basis set SOA scheme and modal aersols :
+ CAM low top model
+ Prognostic GHG chemistry mechanism for CAM7:
Modal Aerosol Model composed of 7 modes:
+ CAM mid top model
CAM CO2 ramp:
CAM super-parameterized CAM one moment SAM microphysics
CAM super-parameterized CAM one moment SAM microphysics using CLUBB
@@ -130,6 +131,7 @@
-phys cam_dev
+ -chem ghg_mam4
-chem trop_strat_mam5_vbs
-chem geoschem_mam4 -hemco
@@ -163,13 +165,14 @@
-chem waccm_mad_mam5
-offline_dyn
+
-nlev 56
-nlev 56
-nlev 56
-nlev 88
-nlev 145
- -nlev 58
- -nlev 93
+ -nlev 58
+ -nlev 93
-phys adiabatic
@@ -210,6 +213,8 @@
waccm_tsmlt_1850_cam6
waccm_ma_1850_cam6
waccm_sc_1850_cam6
+ 1850_cam_lt
+ 1850_cam_mt
2000_cam4_trop_chem
waccmxie_ma_2000_cam4
@@ -253,6 +258,8 @@
1950-2010_ccmi_refc1_waccmx_ma
1850-2005_cam5
hist_cam6
+ hist_cam_lt
+ hist_cam_mt
waccm_tsmlt_hist_cam6
waccm_sc_hist_cam6
waccm_ma_hist_cam6
@@ -361,6 +368,79 @@
User mods to apply to specific compset matches.
+
+
+
+ char
+ 2000
+
+ 1850
+ 2010
+ 1850
+ 2015
+
+ run_component_cam
+ env_run.xml
+ Nitrogen deposition data year first
+
+
+
+ char
+ 2000
+
+ 2010
+ 1850
+ 2015
+ 2101
+
+ run_component_cam
+ env_run.xml
+ Nitrogen deposition data year last
+
+
+
+ char
+ 1
+
+ 1850
+ 2015
+
+ run_component_cam
+ env_run.xml
+ Nitrogen deposition align CAM_STREAM_NDEP_YEAR_FIRST with this model year
+
+
+
+
+ char
+ UNSET
+
+ $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP5-8.5-WACCM_1849-2101_monthly_c191007.nc
+ $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP1-2.6-WACCM_1849-2101_monthly_c191007.nc
+ $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP2-4.5-WACCM_1849-2101_monthly_c191007.nc
+ $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_SSP370_b.e21.BWSSP370cmip6.f09_g17.CMIP6-SSP3-7.0-WACCM.002_1849-2101_monthly_0.9x1.25_c211216.nc
+ $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc
+ $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc
+ $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc
+ $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_WACCM6_CMIP6piControl001_y21-50avg_1850monthly_0.95x1.25_c180802.nc
+
+ run_component_cam
+ env_run.xml
+ Nitrogen deposition data filename
+
+
+
+ char
+ $DIN_LOC_ROOT/share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc
+ run_component_cam
+ env_run.xml
+ Nitrogen deposition mesh filename (corresponding to the CAM_STREAM_NDEP_DATA_FILENAME)
+
+
=========================================
CAM naming conventions
diff --git a/cime_config/config_compsets.xml b/cime_config/config_compsets.xml
index 65051c66ac..0bd04659ff 100644
--- a/cime_config/config_compsets.xml
+++ b/cime_config/config_compsets.xml
@@ -61,6 +61,26 @@
+
+ FLTHIST_v0c
+ HIST_CAM%DEV%LT%GHGMAM4_CLM51%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV
+
+
+
+ FMTHIST_v0c
+ HIST_CAM%DEV%MT%GHGMAM4_CLM51%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV
+
+
+
+ FLT1850_TESTINGONLY_v0c
+ 1850_CAM%DEV%LT%GHGMAM4_CLM51%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV
+
+
+
+ FMT1850_TESTINGONLY_v0c
+ 1850_CAM%DEV%MT%GHGMAM4_CLM51%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV
+
+
FHIST_BGC
HIST_CAM60_CLM50%BGC-CROP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV
@@ -316,11 +336,11 @@
FCLTHIST
- HIST_CAM%DEV%L58%CCTS1_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV
+ HIST_CAM%DEV%LT%CCTS1_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV
FCMTHIST
- HIST_CAM%DEV%L93%CCTS1_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV
+ HIST_CAM%DEV%MT%CCTS1_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV
FCvbsxHIST
@@ -597,51 +617,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
1
diff --git a/cime_config/testdefs/testlist_cam.xml b/cime_config/testdefs/testlist_cam.xml
index 4806d18d52..a67c77f510 100644
--- a/cime_config/testdefs/testlist_cam.xml
+++ b/cime_config/testdefs/testlist_cam.xml
@@ -1424,7 +1424,15 @@
-
+
+
+
+
+
+
+
+
+
@@ -2506,9 +2514,10 @@
-
+
+
diff --git a/cime_config/testdefs/testmods_dirs/cam/outfrq1d_14dec_L32wsc/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/outfrq1d_14dec_L32wsc/user_nl_cam
deleted file mode 100644
index 53ed11dfc5..0000000000
--- a/cime_config/testdefs/testmods_dirs/cam/outfrq1d_14dec_L32wsc/user_nl_cam
+++ /dev/null
@@ -1,5 +0,0 @@
-mfilt=1,1,1,1,1,1,1,1,1,1
-ndens=1,1,1,1,1,1,1,1,1,1
-nhtfrq=-24,-24,-24,-24,-24,-24,-24,-24,-24,-24
-tracer_cnst_specifier = 'O3','OH','NO3','HO2','HALONS'
-ubc_specifier = 'NOTSET'
diff --git a/cime_config/testdefs/testmods_dirs/cam/outfrq1d_14dec_L32wsc/shell_commands b/cime_config/testdefs/testmods_dirs/cam/outfrq1d_14dec_ghg_cam_dev/shell_commands
similarity index 84%
rename from cime_config/testdefs/testmods_dirs/cam/outfrq1d_14dec_L32wsc/shell_commands
rename to cime_config/testdefs/testmods_dirs/cam/outfrq1d_14dec_ghg_cam_dev/shell_commands
index eca142f772..513b5dbe41 100644
--- a/cime_config/testdefs/testmods_dirs/cam/outfrq1d_14dec_L32wsc/shell_commands
+++ b/cime_config/testdefs/testmods_dirs/cam/outfrq1d_14dec_ghg_cam_dev/shell_commands
@@ -1,3 +1,3 @@
./xmlchange ROF_NCPL=\$ATM_NCPL
./xmlchange RUN_STARTDATE=0001-12-14
-./xmlchange CAM_CONFIG_OPTS="-phys cam_dev -microphys mg2 -chem waccm_sc_mam4 -nlev 32"
+./xmlchange CAM_CONFIG_OPTS="-phys cam_dev -microphys mg2 -chem ghg_mam4 -nlev 32"
diff --git a/cime_config/testdefs/testmods_dirs/cam/outfrq1d_14dec_ghg_cam_dev/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/outfrq1d_14dec_ghg_cam_dev/user_nl_cam
new file mode 100644
index 0000000000..1e5bc2fa49
--- /dev/null
+++ b/cime_config/testdefs/testmods_dirs/cam/outfrq1d_14dec_ghg_cam_dev/user_nl_cam
@@ -0,0 +1,9 @@
+mfilt=1,1,1,1,1,1,1,1,1,1
+ndens=1,1,1,1,1,1,1,1,1,1
+nhtfrq=-24,-24,-24,-24,-24,-24,-24,-24,-24,-24
+tracer_cnst_specifier = 'O3','OH','NO3','HO2','HALONS'
+flbc_cycle_yr=1850
+phys_grid_ctem_nfreq=-6
+phys_grid_ctem_zm_nbas=16
+phys_grid_ctem_za_nlat=15
+fincl2 = 'THphys','VTHzm','WTHzm','UVzm','UWzm','Uzm','Vzm','Wzm','THzm'
diff --git a/cime_config/testdefs/testmods_dirs/cam/outfrq1d_14dec_L32wsc/user_nl_clm b/cime_config/testdefs/testmods_dirs/cam/outfrq1d_14dec_ghg_cam_dev/user_nl_clm
similarity index 100%
rename from cime_config/testdefs/testmods_dirs/cam/outfrq1d_14dec_L32wsc/user_nl_clm
rename to cime_config/testdefs/testmods_dirs/cam/outfrq1d_14dec_ghg_cam_dev/user_nl_clm
diff --git a/cime_config/testdefs/testmods_dirs/cam/outfrq1d_physgrid_tem_mpasa120_wcmsc/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/outfrq1d_physgrid_tem_mpasa120_wcmsc/user_nl_cam
index 1212d35edd..1769cf51c8 100644
--- a/cime_config/testdefs/testmods_dirs/cam/outfrq1d_physgrid_tem_mpasa120_wcmsc/user_nl_cam
+++ b/cime_config/testdefs/testmods_dirs/cam/outfrq1d_physgrid_tem_mpasa120_wcmsc/user_nl_cam
@@ -17,7 +17,7 @@ phys_grid_ctem_za_nlat = 90
fincl1 = ' '
fexcl1 = ' '
-fincl2 = 'VTHzaphys','WTHzaphys','UVzaphys','UWzaphys'
+fincl2 = 'Uzm','Vzm','Wzm','THzm', 'VTHzm','WTHzm','UVzm','UWzm'
mfilt=1,1,1,1,1,1,1,1,1,1
ndens=1,1,1,1,1,1,1,1,1,1
diff --git a/cime_config/testdefs/testmods_dirs/cam/outfrq3s_physgrid_tem/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/outfrq3s_physgrid_tem/user_nl_cam
index 55e353983a..dad2b49ac7 100644
--- a/cime_config/testdefs/testmods_dirs/cam/outfrq3s_physgrid_tem/user_nl_cam
+++ b/cime_config/testdefs/testmods_dirs/cam/outfrq3s_physgrid_tem/user_nl_cam
@@ -5,4 +5,4 @@ inithist='ENDOFRUN'
phys_grid_ctem_nfreq=3
phys_grid_ctem_zm_nbas=16
phys_grid_ctem_za_nlat=15
-fincl3 = 'VTHzaphys','WTHzaphys','UVzaphys','UWzaphys'
+fincl3 = 'Uzm','Vzm','Wzm','THzm', 'VTHzm','WTHzm','UVzm','UWzm'
diff --git a/cime_config/testdefs/testmods_dirs/cam/outfrq9s_physgrid_tem_1deg/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/outfrq9s_physgrid_tem_1deg/user_nl_cam
index 9cf4e0a97d..a82b687449 100644
--- a/cime_config/testdefs/testmods_dirs/cam/outfrq9s_physgrid_tem_1deg/user_nl_cam
+++ b/cime_config/testdefs/testmods_dirs/cam/outfrq9s_physgrid_tem_1deg/user_nl_cam
@@ -5,4 +5,4 @@ inithist='ENDOFRUN'
phys_grid_ctem_nfreq=-2
phys_grid_ctem_zm_nbas=120
phys_grid_ctem_za_nlat=90
-fincl3 = 'VTHzaphys','WTHzaphys','UVzaphys','UWzaphys'
+fincl3 = 'Uzm','Vzm','Wzm','THzm', 'VTHzm','WTHzm','UVzm','UWzm'
diff --git a/doc/ChangeLog b/doc/ChangeLog
index d09f63077b..5d77cc2f5a 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,5 +1,2413 @@
===============================================================
+Tag name: cam6_3_111
+Originator(s): cacraig, hannay, fvitt
+Date: May 17, 2023
+One-line Summary: create CAM LT and MT 1850 use_cases
+Github PR URL: https://github.com/ESCOMP/CAM/pull/806
+
+Purpose of changes (include the issue number and title text for each relevant GitHub issue):
+ - Add use_cases for 1850 LT and MT compsets: https://github.com/ESCOMP/CAM/issues/804
+
+ *** IMPORTANT NOTE -- MT compsets do not run successfully for 9 time steps
+
+Describe any changes made to build system: N/A
+
+Describe any changes made to the namelist:
+ - See specific details below in file section:
+ Updated namelist settings based on discussion in: https://github.com/NCAR/amwg_dev/discussions/261
+
+List any changes to the defaults for the boundary datasets: N/A
+
+Describe any substantial timing or memory changes: N/A
+
+Code reviewed by: hannay, nusbaume
+
+List all files eliminated: N/A
+
+List all files added and what they do:
+A bld/namelist_files/use_cases/1850_cam_lt.xml
+A bld/namelist_files/use_cases/1850_cam_mt.xml
+ - Initial use cases - setup for BLT1850 and BMT1850 to use
+
+List all existing files that have been modified, and describe the changes:
+M bld/build-namelist
+ - Remove H2O ext_file from ghg_mam runs
+
+M bld/namelist_files/namelist_defaults_cam.xml
+ - Added gw_apply_tndmz defaults for ghg_mam4 93 and 58 level
+ - Added se_hypervis_subcycle default for ne30np4, npg3, 58 level
+
+M bld/namelist_files/use_cases/hist_cam_lt.xml
+M bld/namelist_files/use_cases/hist_cam_mt.xml
+ - Removed the above settings and others which are set properly via namelist_defaults
+
+M cime_config/config_component.xml
+ - Added hooks for 1850 LT and MT use_cases
+
+M cime_config/config_compsets.xml
+ - Added for Testing purposes ONLY - FLT1850_TESTINGONLY_v0c and FMT1850_TESTINGONLY_v0c
+
+
+If there were any failures reported from running test_driver.sh on any test
+platform, and checkin with these failures has been OK'd by the gatekeeper,
+then copy the lines from the td.*.status files for the failed tests to the
+appropriate machine below. All failed tests must be justified.
+
+cheyenne/intel/aux_cam:
+ FAIL ERP_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.FW2000climo.cheyenne_intel.cam-outfrq9s_wcm_ne30 RUN time=266
+ - preexisting failure
+
+ FAIL ERS_Ln9_P36x1_Vnuopc.mpasa480_mpasa480.F2000climo.cheyenne_intel.cam-outfrq9s_mpasa480 RUN time=357
+ - This test passed for Brian Eaton when he made cam6_3_110. We retested and Francis Vitt had it fail for
+ cam6_3_109. Cheryl Craig tested using cam6_3_110 and cam6_3_108 and it failed in both of these version.
+ Saying this is a preexisting failure and will be researched later
+
+ FAIL ERS_Ld3_Vnuopc.f10_f10_mg37.F1850.cheyenne_intel.cam-outfrq1d_14dec_ghg_cam_dev BASELINE
+ FAIL SMS_D_Ln9_Vnuopc_P720x1.ne30pg3_ne30pg3_mg17.FCLTHIST.cheyenne_intel.cam-outfrq9s BASELINE
+ - expected baselines differences due to namelist changes
+
+
+izumi/nag/aux_cam: all BFB except:
+ FAIL DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae RUN time=10
+
+
+izumi/gnu/aux_cam: all BFB
+
+ADDITIONAL TESTS RUN:
+
+ Cecile ran FLTHIST and FLT1850 tests with restart and they ran properly (with user_nl_cam, user_nl_clm, CLM SourceMods and
+ various XML settings):
+ /glade/scratch/hannay/cases/f.cam6_3_111.FLT1850.001
+ /glade/scratch/hannay/cases/f.cam6_3_111.FLTHIST_v0c.001
+
+
+===============================================================
+===============================================================
+
+Tag name: cam6_3_110
+Originator(s): eaton, bstephens
+Date: Tue May 9 01:46:34 PM EDT 2023
+One-line Summary: Resolve miscellaneous issues.
+Github PR URL: https://github.com/ESCOMP/CAM/pull/797
+
+Purpose of changes (include the issue number and title text for each relevant GitHub issue):
+
+. Issue #371 - Grid matches in refcases will need to change from
+ gland4 to gris4 if they are re-enabled
+ (https://github.com/ESCOMP/CAM/issues/371).
+ - Resolved by removing entries for old refcases.
+
+. Issue #741 - Updates to address CLUBB variable-name length limit.
+ (https://github.com/ESCOMP/CAM/issues/741)
+ - Use cam_history_support::max_fieldname_len to replace hardcoded 16.
+ - PR #743 will be resolved by this PR.
+
+. Issue #608 - Fix path for buildlib/buildnml
+ (https://github.com/ESCOMP/CAM/issues/608)
+ - Fix one wrong occurance of the old path 'cime/scripts/Tools'. Don't
+ see any problem with paths for buildlib/buildnml.
+
+. Issue #749 - Correct description of low-level wind output
+ (https://github.com/ESCOMP/CAM/issues/749)
+ - fix description as suggested
+
+. Issue #803 - Add missing GHGMAM4 to FMTHIST compset
+ (https://github.com/ESCOMP/CAM/issues/803)
+ - add missing %GHGMAM4 to FMTHIST compset
+ - change FLTHIST_v0b to FLTHIST_v0c
+ - change FMTHIST_v0b to FMTHIST_v0c
+
+. resolves #371
+. resolves #741
+. resolves #743
+. resolves #608
+. resolves #749
+. resolves #803
+
+Describe any changes made to build system: none
+
+Describe any changes made to the namelist: none
+
+List any changes to the defaults for the boundary datasets: none
+
+Describe any substantial timing or memory changes: none
+
+Code reviewed by: fvitt, cacraigucar, nusbaume
+
+List all files eliminated: none
+
+List all files added and what they do: none
+
+List all existing files that have been modified, and describe the changes:
+
+bld/namelist_files/namelist_definition.xml
+. change type of clubb_vars_* from char*16 to char*35
+
+cime_config/config_compsets.xml
+. remove commented out lines (575-618) for old refcases
+. add missing %GHGMAM4 to FMTHIST compset
+. change FLTHIST_v0b to FLTHIST_v0c
+. change FMTHIST_v0b to FMTHIST_v0c
+
+src/physics/cam/cam_diagnostics.F90
+. change descriptions of WSPDSRFMX and WSPDSRFAV from 'at the surface' to
+ 'at surface layer midpoint'
+
+src/physics/cam/clubb_intr.F90
+. access max_fieldname_len from cam_history_support
+. replace hardcoded 16 by max_fieldname_len in 8 places that set the name
+ of the variable for an outfld call
+
+test/system/archive_baseline.sh
+. change path of bless_test_results from 'cime/scripts/Tools' to
+ 'cime/CIME/Tools'
+
+If there were any failures reported from running test_driver.sh on any test
+platform, and checkin with these failures has been OK'd by the gatekeeper,
+then copy the lines from the td.*.status files for the failed tests to the
+appropriate machine below. All failed tests must be justified.
+
+cheyenne/intel/aux_cam:
+ ERP_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.FW2000climo.cheyenne_intel.cam-outfrq9s_wcm_ne30 (Overall: FAIL) details:
+ - pre-existing failure
+
+izumi/nag/aux_cam:
+ DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) details:
+ - pre-existing failure
+
+izumi/gnu/aux_cam: All PASS
+
+CAM tag used for the baseline comparison tests if different than previous
+tag:
+
+Summarize any changes to answers: BFB
+
+===============================================================
+===============================================================
+
+Tag name: cam6_3_109
+Originator(s): pel, jet
+Date: 28 April 2023
+One-line Summary: Science and infrastructure updates for inline energy/mass budgets
+Github PR URL: https://github.com/ESCOMP/CAM/pull/761
+
+Purpose of changes (include the issue number and title text for each relevant GitHub issue):
+
+ Add inline energy/mass budgets support. (#519) Science changes are
+ included that help close the mass and energy budgets of physics
+ and the SE/MPAS dycores (#521) as well as adding all water
+ constituents to atmospheric mass (pressure) (#520).
+
+ Extra items also included in this PR:
+ - Bugfix to correctly open an instance version of atm_in (ndep issue #790)
+ - Update FLTHIST compset and finish implementing initial FMTHIST compset (#789)
+
+ As of this commit energy/mass budgets have been roughed in for
+ physics and the SE and MPAS dycores. Similar to amwg_diagnostic
+ functionality, energy/mass budget diagnostic fields will be added
+ to a history file via the thermo_budget_histfile_num namelist
+ parameter. Globally averaged energy budget summaries are also
+ calculated and written to the atm log file every time the budget
+ history tape is written to. The period over which energy and mass
+ budgets are averaged is the same as the averaging period of the
+ history budget file. Thus history budgets can be output/averaged
+ at timestep, hour, or month resolutions using the nhtfrq variable
+ specific to the budget history file identified by
+ thermo_budget_histfile_num. The new namelist logical variable
+ thermo_buget_history is used to turn budgeting on (.true.) or off
+ (.false.) The default is .false. (no budgeting) because of the
+ global gathers needed to create the budgets.
+
+ An energy or mass budget is defined by a mathematical operation
+ (sum/difference) of two energy/mass snapshots. For instance one
+ can talk of the energy lost/gained by the physics
+ parameterizations by comparing snapshots taken before and after
+ running the physics.
+
+ An energy budget is created, logged and written to the budget history tape in four steps
+ 1) call cam_budget_em_snapshot to define multiple energy/mass snapshots
+ 2) call cam_budget_em_budget to define a budget as the difference/sum of two snapshots.
+ 3) call tot_energy_phys (or tot_energy_dyn) for each named snapshot
+ 4) setting namelist variables thermo_budget_history, thermo_budget_histfile_num, nhtfrq
+
+ Energy and mass snapshots are defined and added to the history
+ buffer via the cam_budget_em_snapshot subroutine. The cam_budget_em_snapshot routine
+ creates a set of vertically integrated energy and mass history
+ output fields based on the snapshot name parameter prepended with
+ the types of energy and mass that are carried in cam and defined
+ in cam_thermo.F90 For example calling cam_budget_em_snapshot with a name of
+ 'dAP', perhaps standing for an energy snapshot after physics is
+ called, will create a set of fields that contain kinetic (KE_dAP),
+ sensible (SE_dAP), potential (PO_dAP) and total (TE_dap) energies
+ as well as atmospheric vapor (wv_dAP), liquid (wl_dAP) and ice
+ (wi_dAP) masses. A call to calc_total_energy for the each named
+ snapshot (here placed after after the physics parameterization)
+ will calculate and outfld the 9 or so specific energy and mass
+ snapshots.
+
+ The cam_budget_em_budget routine defines a named budget composed of the
+ difference or sum of two snapshots. As with cam_budget_em_shapshot the
+ budget name is prepended with the same energies identifiers as
+ cam_budget_em_snapshot. All energy/mass snapshots as well as the budgets are
+ saved to the history buffer and written to the budget history
+ file. tot_energy_phys and tot_energy_dyn routines exists for both
+ physics and dynamics to allow snapshots tailored to thermodynamic
+ needs and data structures of those packages.
+
+
+Describe any changes made to build system:
+
+Describe any changes made to the namelist:
+ New budgeting namelist variables have been added. Interface
+ follows existing functionality to outfld standard diagnostics for
+ budgeting and diagnosis.
+
+ se_lcp_moist
+ se_phys_dyn_cp
+ - removed
+
+ thermo_budget_histfile_num: integer identifing which history file will contain
+ additional budgeting diagnostic fields
+ thermo_budget_history: logical that turns history budgeting on and off.
+ - added
+
+List any changes to the defaults for the boundary datasets: N/A
+
+Describe any substantial timing or memory changes:
+ Global gathers are done each time a thermo budgeting field is
+ written to the history file. The budgeting diagnostics are not
+ meant to be enabled during a production run.
+
+Code reviewed by: cacraigucar nusbaume brian-eaton fvitt pel
+
+List all files eliminated: N/A
+
+List all files added and what they do:
+ A src/cam/control/cam_budget.F90
+ provides support for energy/mass budgeting using cam_history infrastructure.
+
+List all existing files that have been modified, and describe the changes:
+
+ M bld/namelist_files/use_cases/hist_cam_mt.xml
+ - update FLTHIST for coupled runs
+
+ M bld/build_namelist
+ - Remove se_lcp_moist and se_phys_dyn_cp namelist flags
+
+ M namelist_defaults_cam.xml
+ - new mpas initial data default for mpasa120 aquaplanet.
+ - update cam_dev defaults to add Graupel constituent.
+
+ M namelist_definition.xml
+ - new averaging flag option for budget variables 'N' allows normalization by nsteps.
+ - nstep normalization is required to properly budget subcycled fields.
+ - new namelist parameters for budgeting
+
+ M cam_comp.F90
+ - add call to print budgets. The print_budget function needs to be defined for all dycores.
+
+ M cam_history.F90
+ - new functionality for history buffered fields
+ - new area weighted global averaging functionality for history fields.
+ - create new composed hbuf field which is created from a sum/difference operation on
+ two existing fields.
+ - restart information added for budgeting.
+
+ M cam_history_buffers.F90
+ - new subroutine for nstep field averaging
+
+ M cam_history_support.F90
+ - added support for new global average functionality
+
+ M cime_config/config_compsets.xml
+ - update FLTHIST for coupled runs
+
+ M runtime_opts.F90
+ - added budget namelist read
+
+ M atm_comp_nuopc.F90
+ - bug fix, support for E/W formatted initial data longitudes spanning -180:180
+
+ M cpl/nuopc/atm_stream_ndep.F90
+ - bug fix to allow opening instance version of atm_in namelist.
+
+ M eul/dp_coupling.F90
+ - update calling parameters
+
+ M eul/dycore_budget.F90
+ - Dummy routine for printing EUL budget - not fully supported yet.
+
+ M fv/dp_coupling.F90
+ - update calling parameters
+
+ M fv/dycore_budget.F90
+ - Dummy routine for printing FV budget - not fully supported yet.
+
+ M fv/metdata.F90
+ - thermodynamic activespecies variables
+
+ M fv3/dp_coupling.F90
+ - update calling parameters
+
+ M fv3/dycore_budget.F90
+ - Dummy routine for printing FV3 budget - not fully supported yet.
+
+ M mpas/dp_coupling.F90
+ - science updates
+ - all water constitutents added to pressure
+ - mods to further reduce bias in energy budget
+
+ M mpas/dycore_budget.F90
+ - Routine for printing MPAS budget
+
+ M mpas/dyn_comp.F90
+ - Add core budgets for mpas energy and mass - stages
+
+ M mpas/dyn_grid.F90
+ - register area weights for mpas grids
+
+ M se/advect_tend.F90
+ - refactor statements checking for use of cslam
+
+ M se/dp_coupling.F90
+ - science updates
+ - all water constitutents added to pressure
+ - mods to further reduce bias in energy budget
+
+ M se/dycore/control_mod.F90
+ - remove phys_dyn_cp energy scaling flag
+
+ M se/dycore/control_mod.F90
+ - thermal energy scaling of T
+
+ M se/dycore/dimensions_mod.F90
+ - get rid of lcp_moist now namelist variable
+
+ M se/dycore/fvm_mod.F90
+ - add use_cslam logical in place of if ntrac>0
+
+ M se/dycore/global_norms_mod.F90
+ - new interface for calculating both elem and fvm global integrals (fvm added)
+
+ M se/dycore/hybrid_mod.F90
+ - add use_cslam logical in place of if ntrac>0
+
+ M se/dycore/namelist_mod.F90
+ - add use_cslam logical in place of if ntrac>0
+
+ M se/dycore/prim_advance_mod.F90
+ - science updates to close energy budget
+ - refactor energy calc routine.
+ - new hydrostatic energy routine with potential energy now split out from SE
+
+ M se/dycore/prim_advection_mod.F90
+ - refactor for enthalpy ... internal energy to enthalpy
+
+ M se/dycore/prim_driver_mod.F90
+ - rename routine to calculate total energy
+
+ M se/dycore/prim_state_mod.F90
+ - add use_cslam logical in place of if ntrac>0
+
+ M se/dycore/viscosity.F90
+ - add use_cslam logical in place of if ntrac>0
+
+ M se/dycore_budget.F90
+ - Routine for printing SE energy/mass budgets
+
+ M se/dyn_comp.F90
+ - Add core budget variables for se energy and mass - stages
+
+ M se/dyn_grid.F90
+ - register area weights for se grids
+ - call budget_add for all SE energy/mass budget fields.
+
+ M se/dyn_grid.F90
+ - consistent naming of routine that calculates total energy
+
+ M se/restart_dynamics.F90
+ - add use_cslam logical in place of if ntrac>0
+
+ M se/stepon.F90
+ - update name calc_tot_energy_dynamics to tot_energy_dyn
+
+ M se/test_fvm_mapping.F90
+ - add use_cslam logical in place of if ntrac>0
+
+ M infrastructure/phys_grid.F90
+ - register area weights for physic grid
+ - call budget_add for all SE energy/mass budget fields.
+
+ M cam_diagnostics.F90
+ - register physics energy/mass budgets using budget_add calls
+ - physics energy/mass variables (physics budget stages)
+
+ M check_energy.F90
+ - update calls to get hydrostatic energy (include new potential energy input param)
+ - update calc energy/mass routine for potential energy calculation.
+
+ M constituents.F90
+ - clean up unused variables (NAG)
+
+ M geopotential.F90
+ - remove unused routines/variables (NAG)
+ - add computation of generalized virtual temp to geopotential_t
+
+ M phys_control.F90
+ - code cleanup
+
+ M cam/phys_grid.F90
+ - register area weights for global integrals
+
+ M physics_types.F90
+ - science updates for energy/mass budgets
+
+ M cam/physpkg.F90
+ - science updates for energy/mass budgets
+ - science updates for energy/mass budgets
+
+ M cam_dev/physpkg.F90
+ - science updates for energy/mass budgets
+
+ M simple/physpkg.F90
+ - science updates for energy/mass budgets (update dme_adjust)
+
+ M utils/air_composition.F90
+ - refactor/cleanup/rename
+
+ M utils/grid_support.F90
+ - support for global area weighting for budgets
+
+ M utils/cam_thermo.F90
+ - energy and mass budget variables and descriptions.
+
+If there were any failures reported from running test_driver.sh on any test
+platform, and checkin with these failures has been OK'd by the gatekeeper,
+then copy the lines from the td.*.status files for the failed tests to the
+appropriate machine below. All failed tests must be justified.
+
+cheyenne/intel/aux_cam: Expecting namelist and baseline failures (SE,MPAS,FV3 climate changing, others roundoff)
+
+ ERP_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.FW2000climo.cheyenne_intel.cam-outfrq9s_wcm_ne30 (Overall: FAIL)
+ - pre-existing failure
+
+ ERC_D_Ln9_P144x1_Vnuopc.ne16pg3_ne16pg3_mg17.QPC6HIST.cheyenne_intel.cam-outfrq3s_ttrac_usecase (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq3s_cosp (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPMOZ.cheyenne_intel.cam-outfrq3s (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPX2000.cheyenne_intel.cam-outfrq3s (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.FADIAB.cheyenne_intel.cam-terminator (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.QPC5HIST.cheyenne_intel.cam-outfrq3s_usecase (Overall: DIFF)
+ ERI_D_Ln18_Vnuopc.f45_f45_mg37.QPC41850.cheyenne_intel.cam-co2rmp_usecase (Overall: DIFF)
+ ERP_D_Ln9_Vmct.f09_f09_mg17.QSC6.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ ERP_D_Ln9_Vmct.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ ERP_D_Ln9_Vnuopc.f09_f09_mg17.QSC6.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ ERP_D_Ln9_Vnuopc.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ ERP_D_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.F2000dev.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ ERP_Ld3_Vnuopc.f09_f09_mg17.FWHIST.cheyenne_intel.cam-reduced_hist1d (Overall: DIFF)
+ ERP_Ln9_P24x3_Vnuopc.f45_f45_mg37.QPWmaC6.cheyenne_intel.cam-outfrq9s_mee_fluxes (Overall: DIFF)
+ ERP_Ln9_Vmct.f09_f09_mg17.2000_CAM60_CLM50%SP_CICE5%PRES_DOCN%DOM_MOSART_SGLC_SWAV.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ ERP_Ln9_Vnuopc.C96_C96_mg17.F2000climo.cheyenne_intel.cam-outfrq9s_mg3 (Overall: DIFF)
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F1850.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F2000climo.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F2000dev.cheyenne_intel.cam-outfrq9s_mg3 (Overall: DIFF)
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F2010climo.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ ERP_Ln9_Vnuopc.f09_f09_mg17.FHIST_BDRD.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ ERP_Ln9_Vnuopc.f19_f19_mg17.FWsc1850.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ ERP_Ln9_Vnuopc.ne30_ne30_mg17.FCnudged.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ ERS_Ld3_Vnuopc.f10_f10_mg37.F1850.cheyenne_intel.cam-outfrq1d_14dec_ghg_cam_dev (Overall: DIFF)
+ ERS_Ln9_P288x1_Vnuopc.mpasa120_mpasa120.F2000climo.cheyenne_intel.cam-outfrq9s_mpasa120 (Overall: DIFF)
+ ERS_Ln9_P36x1_Vnuopc.mpasa480_mpasa480.F2000climo.cheyenne_intel.cam-outfrq9s_mpasa480 (Overall: DIFF)
+ ERS_Ln9_Vnuopc.f09_f09_mg17.FX2000.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ ERS_Ln9_Vnuopc.f19_f19_mg17.FSPCAMS.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ ERS_Ln9_Vnuopc.f19_f19_mg17.FXSD.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ ERS_Ln9_Vnuopc.ne0TESTONLYne5x4_ne0TESTONLYne5x4_mg37.FADIAB.cheyenne_intel.cam-outfrq3s_refined (Overall: DIFF)
+ SMS_D_Ld2_Vnuopc.f19_f19_mg17.QPC5HIST.cheyenne_intel.cam-volc_usecase (Overall: DIFF)
+ SMS_D_Ln9_Vnuopc.f09_f09_mg17.FCts2nudged.cheyenne_intel.cam-outfrq9s_leapday (Overall: DIFF)
+ SMS_D_Ln9_Vnuopc.f09_f09_mg17.FCvbsxHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.FWma2000climo.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.FWma2000climo.cheyenne_intel.cam-outfrq9s_waccm_ma_mam4 (Overall: DIFF)
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.FXHIST.cheyenne_intel.cam-outfrq9s_amie (Overall: DIFF)
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.QPC2000climo.cheyenne_intel.cam-outfrq3s_usecase (Overall: DIFF)
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.QPC5M7.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ SMS_D_Ln9_Vnuopc.ne16_ne16_mg17.FX2000.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ SMS_D_Ln9_Vnuopc.ne16_ne16_mg17.QPX2000.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ SMS_D_Ln9_Vnuopc_P720x1.ne0ARCTICne30x4_ne0ARCTICne30x4_mt12.FHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ SMS_D_Ln9_Vnuopc_P720x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ SMS_D_Ln9_Vnuopc_P720x1.ne30pg3_ne30pg3_mg17.FCLTHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+ SMS_Ld1_Vnuopc.f09_f09_mg17.FW2000climo.cheyenne_intel.cam-outfrq1d (Overall: DIFF)
+ SMS_Ld1_Vnuopc.f19_f19.F2000dev.cheyenne_intel.cam-outfrq1d (Overall: DIFF)
+ SMS_Ld1_Vnuopc.ne30pg3_ne30pg3_mg17.FC2010climo.cheyenne_intel.cam-outfrq1d (Overall: DIFF)
+ SMS_Lm13_Vnuopc.f10_f10_mg37.F2000climo.cheyenne_intel.cam-outfrq1m (Overall: DIFF)
+ SMS_Ln9_Vnuopc.f09_f09_mg17.F2010climo.cheyenne_intel.cam-nudging (Overall: DIFF)
+ SMS_Ln9_Vnuopc.f09_f09_mg17.FW1850.cheyenne_intel.cam-reduced_hist3s (Overall: DIFF)
+ SMS_Ln9_Vnuopc.f19_f19.F2000climo.cheyenne_intel.cam-silhs (Overall: DIFF)
+ SMS_Ln9_Vnuopc.f19_f19_mg17.FHIST.cheyenne_intel.cam-outfrq9s_nochem (Overall: DIFF)
+ - expecting climate changing differences in SE,MPAS,FV3
+ - verified FV,EUL differences are roundoff
+
+ FAIL ERC_D_Ln9_P144x1_Vnuopc.ne16pg3_ne16pg3_mg17.QPC6HIST.cheyenne_intel.cam-outfrq3s_ttrac_usecase NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.FADIAB.cheyenne_intel.cam-terminator NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.QPC5HIST.cheyenne_intel.cam-outfrq3s_usecase NLCOMP
+ FAIL ERP_D_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.F2000dev.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL ERP_Ln9_Vnuopc.C96_C96_mg17.F2000climo.cheyenne_intel.cam-outfrq9s_mg3 NLCOMP
+ FAIL ERP_Ln9_Vnuopc.f09_f09_mg17.F2000dev.cheyenne_intel.cam-outfrq9s_mg3 NLCOMP
+ FAIL ERP_Ln9_Vnuopc.ne30_ne30_mg17.FCnudged.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL ERP_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.FW2000climo.cheyenne_intel.cam-outfrq9s_wcm_ne30 NLCOMP
+ FAIL ERS_Ln9_Vnuopc.ne0TESTONLYne5x4_ne0TESTONLYne5x4_mg37.FADIAB.cheyenne_intel.cam-outfrq3s_refined NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc.ne16_ne16_mg17.FX2000.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc.ne16_ne16_mg17.QPX2000.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc_P720x1.ne0ARCTICne30x4_ne0ARCTICne30x4_mt12.FHIST.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc_P720x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc_P720x1.ne30pg3_ne30pg3_mg17.FCLTHIST.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL SMS_Ld1_Vnuopc.f19_f19.F2000dev.cheyenne_intel.cam-outfrq1d NLCOMP
+ FAIL SMS_Ld1_Vnuopc.ne30pg3_ne30pg3_mg17.FC2010climo.cheyenne_intel.cam-outfrq1d NLCOMP
+ - expected NLCOMP failures due to removal of se_lcp_moist, se_phys_dyn_cp namelist variables for SE runs
+ - expected NLCOMP failures from addition of GRAUPEL to water species for cam_dev and FV3 runs
+
+izumi/nag/aux_cam: Expecting namelist and baseline failures
+
+ DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL)
+ - pre-existing failure
+
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-carma_sea_salt (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_cosp (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_subcol (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_am (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_convmic (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_cospsathist (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPWmaC6.izumi_nag.cam-outfrq3s (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QSPCAMS.izumi_nag.cam-outfrq3s (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.mpasa480z32_mpasa480.FHS94.izumi_nag.cam-outfrq3s_usecase (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.ne16pg3_ne16pg3_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-outfrq3s_ttrac (Overall: DIFF)
+ ERI_D_Ln18_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_eoyttrac (Overall: DIFF)
+ ERI_D_Ln18_Vnuopc.f19_f19_mg17.QPC6.izumi_nag.cam-ghgrmp_e8 (Overall: DIFF)
+ ERI_D_Ln18_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s_bwic (Overall: DIFF)
+ ERI_D_Ln18_Vnuopc.ne5pg3_ne5pg3_mg37.FADIAB.izumi_nag.cam-outfrq3s_bwic (Overall: DIFF)
+ ERP_Ln9_Vmct.ne5pg3_ne5pg3_mg37.QPC6.izumi_nag.cam-outfrq9s_clubbmf (Overall: DIFF)
+ ERP_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC6.izumi_nag.cam-outfrq9s_clubbmf (Overall: DIFF)
+ ERS_Ln27_Vnuopc.ne5pg3_ne5pg3_mg37.FKESSLER.izumi_nag.cam-outfrq9s (Overall: DIFF)
+ ERS_Ln9_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq9s (Overall: DIFF)
+ PEM_D_Ln9_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s (Overall: DIFF)
+ PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 (Overall: DIFF)
+ PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 (Overall: DIFF)
+ PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 (Overall: DIFF)
+ PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 (Overall: DIFF)
+ PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 (Overall: DIFF)
+ PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 (Overall: DIFF)
+ SMS_D_Ln3_Vnuopc.ne5pg3_ne5pg3_mg37.QPX2000.izumi_nag.cam-outfrq3s (Overall: DIFF)
+ SMS_D_Ln6_Vnuopc.ne5_ne5_mg37.QPWmaC4.izumi_nag.cam-outfrq3s_physgrid_tem (Overall: DIFF)
+ SMS_D_Ln9_P1x1_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s (Overall: DIFF)
+ SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-rad_diag_mam (Overall: DIFF)
+ SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_ba (Overall: DIFF)
+ SMS_P48x1_D_Ln3_Vnuopc.f09_f09_mg17.QPC6HIST.izumi_nag.cam-outfrq3s_co2cycle_usecase (Overall: DIFF)
+ SUB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s (Overall: DIFF)
+ TMC_D_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_eoyttrac (Overall: DIFF)
+ - expecting climate changing differences in SE,MPAS,FV3
+ - verified FV,EUL differences are roundoff
+
+ FAIL ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.ne16pg3_ne16pg3_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-outfrq3s_ttrac NLCOMP
+ FAIL ERI_D_Ln18_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s_bwic NLCOMP
+ FAIL ERI_D_Ln18_Vnuopc.ne5pg3_ne5pg3_mg37.FADIAB.izumi_nag.cam-outfrq3s_bwic NLCOMP
+ FAIL ERP_Ln9_Vmct.ne5pg3_ne5pg3_mg37.QPC6.izumi_nag.cam-outfrq9s_clubbmf NLCOMP
+ FAIL ERP_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC6.izumi_nag.cam-outfrq9s_clubbmf NLCOMP
+ FAIL ERS_Ln27_Vnuopc.ne5pg3_ne5pg3_mg37.FKESSLER.izumi_nag.cam-outfrq9s NLCOMP
+ FAIL ERS_Ln9_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq9s NLCOMP
+ FAIL PEM_D_Ln9_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s NLCOMP
+ FAIL PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 NLCOMP
+ FAIL PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 NLCOMP
+ FAIL PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 NLCOMP
+ FAIL SMS_D_Ln3_Vnuopc.ne5pg3_ne5pg3_mg37.QPX2000.izumi_nag.cam-outfrq3s NLCOMP
+ FAIL SMS_D_Ln6_Vnuopc.ne5_ne5_mg37.QPWmaC4.izumi_nag.cam-outfrq3s_physgrid_tem NLCOMP
+ FAIL SMS_D_Ln9_P1x1_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s NLCOMP
+ - expected NLCOMP failures due to removal of se_lcp_moist, se_phys_dyn_cp namelist variables for SE runs
+
+izumi/gnu/aux_cam: Expecting namelist and baseline failures
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.FADIAB.izumi_gnu.cam-terminator (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC4.izumi_gnu.cam-outfrq3s_diags (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_gnu.cam-outfrq3s_unicon (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_gnu.cam-rad_diag (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPSPCAMM.izumi_gnu.cam-outfrq3s (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC4.izumi_gnu.cam-outfrq3s_nudging_ne5_L26 (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq3s_ba (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.ne5pg2_ne5pg2_mg37.FADIAB.izumi_gnu.cam-outfrq3s (Overall: DIFF)
+ ERC_D_Ln9_Vnuopc.ne5pg4_ne5pg4_mg37.FADIAB.izumi_gnu.cam-outfrq3s (Overall: DIFF)
+ ERP_Ln9_Vnuopc.ne5_ne5_mg37.FHS94.izumi_gnu.cam-outfrq9s (Overall: DIFF)
+ ERP_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq9s (Overall: DIFF)
+ PEM_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.FADIAB.izumi_gnu.cam-outfrq3s (Overall: DIFF)
+ PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal0 (Overall: DIFF)
+ PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal1 (Overall: DIFF)
+ PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal3 (Overall: DIFF)
+ SMS_D_Ln3_Vnuopc.f10_f10_mg37.QPMOZ.izumi_gnu.cam-outfrq3s_chemproc (Overall: DIFF)
+ SMS_D_Ln9.f10_f10_mg37.2000_CAM%DEV%GHGMAM4_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV_SESP.izumi_gnu.cam-outfrq9s (Overall: DIFF)
+ SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPWmaC4.izumi_gnu.cam-outfrq9s_apmee (Overall: DIFF)
+ SMS_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-outfrq3s_ttrac (Overall: DIFF)
+ - expecting climate changing differences in SE,MPAS,FV3
+ - verified FV,EUL differences are roundoff
+
+ FAIL ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC4.izumi_gnu.cam-outfrq3s_nudging_ne5_L26 NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq3s_ba NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.ne5pg2_ne5pg2_mg37.FADIAB.izumi_gnu.cam-outfrq3s NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.ne5pg4_ne5pg4_mg37.FADIAB.izumi_gnu.cam-outfrq3s NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.T5_T5_mg37.QPC3.izumi_gnu.cam-outfrq3s_usecase NLCOMP
+ FAIL ERP_Ln9_Vnuopc.ne5_ne5_mg37.FHS94.izumi_gnu.cam-outfrq9s NLCOMP
+ FAIL ERP_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq9s NLCOMP
+ FAIL PEM_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.FADIAB.izumi_gnu.cam-outfrq3s NLCOMP
+ FAIL PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal0 NLCOMP
+ FAIL PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal1 NLCOMP
+ FAIL PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal3 NLCOMP
+ FAIL SMS_D_Ln9.f10_f10_mg37.2000_CAM%DEV%GHGMAM4_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV_SESP.izumi_gnu.cam-outfrq9s NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-outfrq3s_ttrac NLCOMP
+ - expected NLCOMP failures due to removal of se_lcp_moist, se_phys_dyn_cp namelist variables for SE runs
+ - expected NLCOMP failures from addition of GRAUPEL to water species for cam_dev and FV3 runs
+ - expected NLCOMP failures due to change in format of water_species_in_air for EUL runs
+
+Summarize any changes to answers: climate changing for SE,MPAS due to science updates
+ climate changing for FV3 due to addition of GRAUPEL
+ roundoff for FV and EUL
+
+===============================================================
+===============================================================
+
+Tag name: cam6_3_108
+Originator(s): fvitt
+Date: 27 Apr 2023
+One-line Summary: Ocean emissions bug fix; enable passing lightning flash rates to surface models
+Github PR URLs:
+
+ https://github.com/ESCOMP/CAM/pull/795
+ https://github.com/ESCOMP/CAM/pull/747
+
+Purpose of changes (include the issue number and title text for each relevant GitHub issue):
+
+ Fix issue with ocean emissions in B compsets where SSTs are zero over land. #794
+ In configurations where SSTs are zeros over land (B compsets) divide by zero
+ errors have occurred. The where block used to mask the calculations of fluxes
+ was not preforming as intended to avoid the divide by zero errors. The where
+ block is replaced with a loop over columns and explicitly check columns for
+ ocean fraction. The flux calculations are preformed only in columns not over
+ land.
+
+ Enable passing cloud-to-ground lightning flash rates to surface models. #567
+
+Describe any changes made to build system: N/A
+
+Describe any changes made to the namelist:
+
+ atm_provides_lightning indicator added to drv_flds_in:
+ If TRUE atmosphere model will provide prognosed lightning flash frequency.
+
+List any changes to the defaults for the boundary datasets: N/A
+
+Describe any substantial timing or memory changes: N/A
+
+Code reviewed by: cacraigucar nusbaume jedwards4b jtruesdal brian-eaton
+
+List all files eliminated: N/A
+
+List all files added and what they do: N/A
+
+List all existing files that have been modified, and describe the changes:
+
+M Externals.cfg
+ - update CMEPS for lightning flash freqencies field
+
+M bld/build-namelist
+ - added namelist switch in drv_flds_in for lightning flashes
+ - set lght_no_prd_factor if chemistry includes NO
+
+M bld/namelist_files/namelist_definition.xml
+ - atm_provides lightning switch
+
+M src/chemistry/mozart/mo_chemini.F90
+M src/chemistry/mozart/chemistry.F90
+ - moved reading lightning namelist options to more general location runtime_opts.F90
+
+M src/chemistry/mozart/mo_lightning.F90
+ - add namelist reader
+ - provide cloud-to-ground flash rates
+ - enable use in configurations without chemistry
+ - calculate NOx production rates only if needed by chemistry
+
+M src/chemistry/mozart/ocean_emis.F90
+ - preform calculations on single columns
+ - replace where block with loop over columns -- calc fluxes only in columns over ocean
+
+M src/control/runtime_opts.F90
+ - invoke lightning namelist reader
+
+M src/control/camsrfexch.F90
+M src/cpl/nuopc/atm_import_export.F90
+ - add field for export of lightning flash rates
+
+M src/physics/cam/physpkg.F90
+M src/physics/cam_dev/physpkg.F90
+ - call lightning register and init routines
+
+If there were any failures reported from running test_driver.sh on any test
+platform, and checkin with these failures has been OK'd by the gatekeeper,
+then copy the lines from the td.*.status files for the failed tests to the
+appropriate machine below. All failed tests must be justified.
+
+cheyenne/intel/aux_cam: all bit-for-bit
+ ERP_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.FW2000climo.cheyenne_intel.cam-outfrq9s_wcm_ne30 (Overall: FAIL) details:
+ - pre-existing failure
+
+ ERC_D_Ln9_P144x1_Vnuopc.ne16pg3_ne16pg3_mg17.QPC6HIST.cheyenne_intel.cam-outfrq3s_ttrac_usecase (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq3s_cosp (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPMOZ.cheyenne_intel.cam-outfrq3s (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPX2000.cheyenne_intel.cam-outfrq3s (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.FADIAB.cheyenne_intel.cam-terminator (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.QPC5HIST.cheyenne_intel.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.T42_T42_mg17.FDABIP04.cheyenne_intel.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.T42_T42_mg17.FHS94.cheyenne_intel.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ ERI_D_Ln18_Vnuopc.f45_f45_mg37.QPC41850.cheyenne_intel.cam-co2rmp_usecase (Overall: NLFAIL) details:
+ ERP_D_Ln9_Vnuopc.f09_f09_mg17.QSC6.cheyenne_intel.cam-outfrq9s (Overall: NLFAIL) details:
+ ERP_D_Ln9_Vnuopc.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq9s (Overall: NLFAIL) details:
+ ERP_Ln9_P24x3_Vnuopc.f45_f45_mg37.QPWmaC6.cheyenne_intel.cam-outfrq9s_mee_fluxes (Overall: NLFAIL) details:
+ ERS_Ln9_Vnuopc.ne0TESTONLYne5x4_ne0TESTONLYne5x4_mg37.FADIAB.cheyenne_intel.cam-outfrq3s_refined (Overall: NLFAIL) details:
+ SCT_D_Ln7_Vnuopc.T42_T42_mg17.QPC5.cheyenne_intel.cam-scm_prep (Overall: NLFAIL) details:
+ SMS_D_Ld2_Vnuopc.f19_f19_mg17.QPC5HIST.cheyenne_intel.cam-volc_usecase (Overall: NLFAIL) details:
+ SMS_D_Ld5_Vnuopc.f19_f19_mg17.PC4.cheyenne_intel.cam-cam4_port5d (Overall: NLFAIL) details:
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.QPC2000climo.cheyenne_intel.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.QPC5M7.cheyenne_intel.cam-outfrq9s (Overall: NLFAIL) details:
+ SMS_D_Ln9_Vnuopc.ne16_ne16_mg17.QPX2000.cheyenne_intel.cam-outfrq9s (Overall: NLFAIL) details:
+ SMS_Ld5_Vnuopc.f09_f09_mg17.PC6.cheyenne_intel.cam-cam6_port_f09 (Overall: NLFAIL) details:
+ - NLCOMP failures are due to new lightning_coupling_nl namelist group in drv_flds_in
+
+ ERP_D_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.F2000dev.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ld3_Vnuopc.f09_f09_mg17.FWHIST.cheyenne_intel.cam-reduced_hist1d (Overall: DIFF) details:
+ ERP_Lh12_Vnuopc.f19_f19_mg17.FW4madSD.cheyenne_intel.cam-outfrq3h (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.C96_C96_mg17.F2000climo.cheyenne_intel.cam-outfrq9s_mg3 (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F1850.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F2000climo.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F2000dev.cheyenne_intel.cam-outfrq9s_mg3 (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F2010climo.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.FHIST_BDRD.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f19_f19_mg17.FWsc1850.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.ne30_ne30_mg17.FCnudged.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERS_Ld3_Vnuopc.f10_f10_mg37.F1850.cheyenne_intel.cam-outfrq1d_14dec_ghg_cam_dev (Overall: DIFF) details:
+ ERS_Ln9_P288x1_Vnuopc.mpasa120_mpasa120.F2000climo.cheyenne_intel.cam-outfrq9s_mpasa120 (Overall: DIFF) details:
+ ERS_Ln9_P36x1_Vnuopc.mpasa480_mpasa480.F2000climo.cheyenne_intel.cam-outfrq9s_mpasa480 (Overall: DIFF) details:
+ ERS_Ln9_Vnuopc.f09_f09_mg17.FX2000.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERS_Ln9_Vnuopc.f19_f19_mg17.FSPCAMS.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERS_Ln9_Vnuopc.f19_f19_mg17.FXSD.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f09_f09_mg17.FCts2nudged.cheyenne_intel.cam-outfrq9s_leapday (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f09_f09_mg17.FCvbsxHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f09_f09_mg17.FSD.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.FWma2000climo.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.FWma2000climo.cheyenne_intel.cam-outfrq9s_waccm_ma_mam4 (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.FXHIST.cheyenne_intel.cam-outfrq9s_amie (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.ne16_ne16_mg17.FX2000.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc_P720x1.ne0ARCTICne30x4_ne0ARCTICne30x4_mt12.FHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc_P720x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc_P720x1.ne30pg3_ne30pg3_mg17.FCLTHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.T42_T42.FSCAM.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_Ld1_Vnuopc.f19_f19.F2000dev.cheyenne_intel.cam-outfrq1d (Overall: DIFF) details:
+ SMS_Ld1_Vnuopc.ne30pg3_ne30pg3_mg17.FC2010climo.cheyenne_intel.cam-outfrq1d (Overall: DIFF) details:
+ SMS_Lm13_Vnuopc.f10_f10_mg37.F2000climo.cheyenne_intel.cam-outfrq1m (Overall: DIFF) details:
+ SMS_Ln9_Vnuopc.f09_f09_mg17.F2010climo.cheyenne_intel.cam-nudging (Overall: DIFF) details:
+ SMS_Ln9_Vnuopc.f09_f09_mg17.FW1850.cheyenne_intel.cam-reduced_hist3s (Overall: DIFF) details:
+ SMS_Ln9_Vnuopc.f19_f19.F2000climo.cheyenne_intel.cam-silhs (Overall: DIFF) details:
+ SMS_Ln9_Vnuopc.f19_f19_mg17.FHIST.cheyenne_intel.cam-outfrq9s_nochem (Overall: DIFF) details:
+ - differences are due to new atmImp_Sa_lightning coupler field -- otherwise all bit-for-bit
+ - NLCOMP failures are due to new lightning_coupling_nl namelist group in drv_flds_in
+
+izumi/nag/aux_cam: all bit-for-bit
+
+ DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) details:
+ - pre-existing failure
+
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-carma_sea_salt (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_cosp (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_subcol (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_am (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_convmic (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_cospsathist (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPWmaC6.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QSPCAMS.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.mpasa480z32_mpasa480.FHS94.izumi_nag.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.ne16pg3_ne16pg3_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-outfrq3s_ttrac (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.T5_T5_mg37.QPC4.izumi_nag.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ ERI_D_Ln18_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_eoyttrac (Overall: NLFAIL) details:
+ ERI_D_Ln18_Vnuopc.f19_f19_mg17.QPC6.izumi_nag.cam-ghgrmp_e8 (Overall: NLFAIL) details:
+ ERI_D_Ln18_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s_bwic (Overall: NLFAIL) details:
+ ERI_D_Ln18_Vnuopc.ne5pg3_ne5pg3_mg37.FADIAB.izumi_nag.cam-outfrq3s_bwic (Overall: NLFAIL) details:
+ ERP_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC6.izumi_nag.cam-outfrq9s_clubbmf (Overall: NLFAIL) details:
+ ERS_Ln27_Vnuopc.ne5pg3_ne5pg3_mg37.FKESSLER.izumi_nag.cam-outfrq9s (Overall: NLFAIL) details:
+ ERS_Ln9_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq9s (Overall: NLFAIL) details:
+ PEM_D_Ln9_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details:
+ PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 (Overall: NLFAIL) details:
+ PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 (Overall: NLFAIL) details:
+ PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 (Overall: NLFAIL) details:
+ PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 (Overall: NLFAIL) details:
+ PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 (Overall: NLFAIL) details:
+ PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 (Overall: NLFAIL) details:
+ SMS_D_Ld2_Vnuopc.f45_f45_mg37.PC5.izumi_nag.cam-outfrq24h_port (Overall: NLFAIL) details:
+ SMS_D_Ln3_Vnuopc.ne5pg3_ne5pg3_mg37.QPX2000.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details:
+ SMS_D_Ln6_Vnuopc.ne5_ne5_mg37.QPWmaC4.izumi_nag.cam-outfrq3s_physgrid_tem (Overall: NLFAIL) details:
+ SMS_D_Ln7_Vnuopc.T42_T42_mg17.QPSCAMC5.izumi_nag.cam-scmarm (Overall: NLFAIL) details:
+ SMS_D_Ln9_P1x1_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details:
+ SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-rad_diag_mam (Overall: NLFAIL) details:
+ SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_ba (Overall: NLFAIL) details:
+ SMS_P48x1_D_Ln3_Vnuopc.f09_f09_mg17.QPC6HIST.izumi_nag.cam-outfrq3s_co2cycle_usecase (Overall: NLFAIL) details:
+ SUB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details:
+ TMC_D_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_eoyttrac (Overall: NLFAIL) details:
+ TMC_D_Vnuopc.T5_T5_mg37.QPC5.izumi_nag.cam-ghgrmp_e8 (Overall: NLFAIL) details:
+ - NLCOMP failures are due to new lightning_coupling_nl namelist group in drv_flds_in
+
+izumi/gnu/aux_cam: all bit-for-bit
+
+ SMS_P48x1_D_Ln9_Vnuopc.f19_f19_mg17.FW4madSD.izumi_gnu.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9.f10_f10_mg37.2000_CAM%DEV%GHGMAM4_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV_SESP.izumi_gnu.cam-outfrq9s (Overall: DIFF) details:
+ - differences are due to new atmImp_Sa_lightning coupler field -- otherwise all bit-for-bit
+ - NLCOMP failures are due to new lightning_coupling_nl namelist group in drv_flds_in
+
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.FADIAB.izumi_gnu.cam-terminator (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC4.izumi_gnu.cam-outfrq3s_diags (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_gnu.cam-outfrq3s_unicon (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_gnu.cam-rad_diag (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPSPCAMM.izumi_gnu.cam-outfrq3s (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC4.izumi_gnu.cam-outfrq3s_nudging_ne5_L26 (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq3s_ba (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.ne5pg2_ne5pg2_mg37.FADIAB.izumi_gnu.cam-outfrq3s (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.ne5pg4_ne5pg4_mg37.FADIAB.izumi_gnu.cam-outfrq3s (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.T5_T5_mg37.QPC3.izumi_gnu.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ ERI_D_Ln18_Vnuopc.T5_T5_mg37.QPC4.izumi_gnu.cam-co2rmp (Overall: NLFAIL) details:
+ ERP_Ln9_Vnuopc.ne5_ne5_mg37.FHS94.izumi_gnu.cam-outfrq9s (Overall: NLFAIL) details:
+ ERP_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq9s (Overall: NLFAIL) details:
+ PEM_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.FADIAB.izumi_gnu.cam-outfrq3s (Overall: NLFAIL) details:
+ PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal0 (Overall: NLFAIL) details:
+ PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal1 (Overall: NLFAIL) details:
+ PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal3 (Overall: NLFAIL) details:
+ SCT_D_Ln7_Vnuopc.T42_T42_mg17.QPC4.izumi_gnu.cam-scm_prep (Overall: NLFAIL) details:
+ SCT_D_Ln7_Vnuopc.T42_T42_mg17.QPC6.izumi_gnu.cam-scm_prep_c6 (Overall: NLFAIL) details:
+ SMS_D_Ln3_Vnuopc.f10_f10_mg37.QPMOZ.izumi_gnu.cam-outfrq3s_chemproc (Overall: NLFAIL) details:
+ SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPWmaC4.izumi_gnu.cam-outfrq9s_apmee (Overall: NLFAIL) details:
+ SMS_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-outfrq3s_ttrac (Overall: NLFAIL) details:
+ - NLCOMP failures are due to new lightning_coupling_nl namelist group in drv_flds_in
+
+Summarize any changes to answers: bit-for-bit unchanged
+
+===============================================================
+===============================================================
+
+Tag name: cam6_3_107
+Originator(s): eaton
+Date: Tue Apr 18 10:27:45 AM EDT 2023
+One-line Summary: Reimplement zonal_mean_mod::Invert_Matrix using LAPACK DGESV
+Github PR URL: https://github.com/ESCOMP/CAM/pull/788
+
+Purpose of changes (include the issue number and title text for each relevant GitHub issue):
+
+The Invert_Matrix subroutine in module zonal_mean_mod has been
+reimplemented using the LAPACK subroutine DGESV.
+
+Resolves:
+. Replace "Invert_Matrix" subroutine in "zonal_mean_mod.F90" with LAPACK version #736
+ (https://github.com/ESCOMP/CAM/issues/736)
+. Bug in zonal mean "Invert_Matrix" subroutine #745
+ (https://github.com/ESCOMP/CAM/issues/745)
+
+Describe any changes made to build system: none
+
+Describe any changes made to the namelist: none
+
+List any changes to the defaults for the boundary datasets: none
+
+Describe any substantial timing or memory changes: not tested
+
+Code reviewed by: fvitt, cacraigucar, peverwhee, patcal
+
+List all files eliminated: none
+
+List all files added and what they do: none
+
+List all existing files that have been modified, and describe the changes:
+
+src/utils/zonal_mean_mod.F90
+. modify subroutine Invert_Matrix to use LAPACK DGESV routine.
+
+If there were any failures reported from running test_driver.sh on any test
+platform, and checkin with these failures has been OK'd by the gatekeeper,
+then copy the lines from the td.*.status files for the failed tests to the
+appropriate machine below. All failed tests must be justified.
+
+cheyenne/intel/aux_cam:
+ ERP_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.FW2000climo.cheyenne_intel.cam-outfrq9s_wcm_ne30 (Overall: FAIL) details:
+ - pre-existing failure
+
+ ERS_Ld3_Vnuopc.f10_f10_mg37.F1850.cheyenne_intel.cam-outfrq1d_14dec_ghg_cam_dev (Overall: DIFF) details:
+ - the zonal mean (*zm) fields in the h1 file have 2-3 significant digits of agreement
+
+izumi/nag/aux_cam:
+ DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) details:
+ - pre-existing failure
+
+ SMS_D_Ln6_Vnuopc.ne5_ne5_mg37.QPWmaC4.izumi_nag.cam-outfrq3s_physgrid_tem (Overall: DIFF) details:
+ - the zonal mean (*zm) fields in the h2 file have 2-3 significant digits of agreement
+
+izumi/gnu/aux_cam:
+ ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC4.izumi_gnu.cam-outfrq3s_nudging_ne5_L26 (Overall: DIFF) details:
+ - diffs in all fields in h0 and h1 files. This is expected because the
+ the nudging uses the zonal_mean_mod code if Nudge_ZonalFilter is true,
+ which it is in this test.
+
+CAM tag used for the baseline comparison tests if different than previous
+tag:
+
+Summarize any changes to answers:
+
+. The only changes to answers are for runs using nudging with
+ Nudge_ZonalFilter set to true.
+
+. The zonal mean diagnostic output only agrees with previous output to a
+ couple of significant figures. That's because previous output was
+ produced with a bug in the Invert_Matrix subroutine (issue #745).
+ Independent testing showed that fixing that bug and comparing with the
+ new version of Invert_Matrix yields roundoff level differences (15-16
+ significant digits of agreement).
+
+===============================================================
+===============================================================
+
+Tag name: cam6_3_106
+Originator(s): cacraig, fvitt, eaton
+Date: Thu Apr 6 07:10:24 PM EDT 2023
+One-line Summary: Initialize CO2 when it's missing from initial file.
+Github PR URL: https://github.com/ESCOMP/CAM/pull/780
+
+Purpose of changes (include the issue number and title text for each relevant GitHub issue):
+
+Fixes: When CO2 is not in IC file, needs to initialize to a non-zero value #779
+ https://github.com/ESCOMP/CAM/issues/779
+
+Describe any changes made to build system: none
+
+Describe any changes made to the namelist: none
+
+List any changes to the defaults for the boundary datasets: none
+
+Describe any substantial timing or memory changes: none
+
+Code reviewed by: brian-eaton, fvitt, nusbaume
+
+List all files eliminated: none
+
+List all files added and what they do: none
+
+List all existing files that have been modified, and describe the changes:
+
+src/chemistry/mozart/chemisty.F90
+. For ghg_chem, add CO2 to the case statement to use chem_surfvals_get
+ for initialization.
+
+If there were any failures reported from running test_driver.sh on any test
+platform, and checkin with these failures has been OK'd by the gatekeeper,
+then copy the lines from the td.*.status files for the failed tests to the
+appropriate machine below. All failed tests must be justified.
+
+cheyenne/intel/aux_cam:
+ ERP_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.FW2000climo.cheyenne_intel.cam-outfrq9s_wcm_ne30 (Overall: FAIL) details:
+ - pre-existing failure
+
+ ERS_Ld3_Vnuopc.f10_f10_mg37.F1850.cheyenne_intel.cam-outfrq1d_14dec_ghg_cam_dev (Overall: DIFF) details:
+ - expected diff due to change in CO2 initialization
+
+izumi/nag/aux_cam:
+ DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) details:
+ - pre-existing failure
+
+izumi/gnu/aux_cam:
+ SMS_D_Ln9.f10_f10_mg37.2000_CAM%DEV%GHGMAM4_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV_SESP.izumi_gnu.cam-outfrq9s (Overall: DIFF) details:
+ - expected diff due to change in CO2 initialization
+
+CAM tag used for the baseline comparison tests if different than previous
+tag:
+
+Summarize any changes to answers: BFB except for any run using ghg_mam4
+ chemistry and using an initial file that doesn't contain CO2. In that
+ case the CO2 is now being initialized by chem_surf_vals. Previously it was
+ zero above the surface layer which is set by the LBC code.
+
+===============================================================
+===============================================================
+
+Tag name: cam6_3_105
+Originator(s): bstephens, eaton
+Date: Thu Apr 6 09:51:59 AM EDT 2023
+One-line Summary: fix for COSP with cam_dev physics
+Github PR URL: https://github.com/ESCOMP/CAM/pull/777
+
+Purpose of changes (include the issue number and title text for each relevant GitHub issue):
+
+Fixes: Add PBUF fields to make cosp compatible with cam_dev #776
+ https://github.com/ESCOMP/CAM/issues/776
+ Note: the original fix was reimplemented to just check whether or
+ not fields used by the cosp simulator are present in the pbuf, and
+ if not then to use local arrays of zeros.
+
+Describe any changes made to build system: none
+
+Describe any changes made to the namelist: none
+
+List any changes to the defaults for the boundary datasets: none
+
+Describe any substantial timing or memory changes: none
+
+Code reviewed by: brian-eaton, cacraigucar, adamrher
+
+List all files eliminated: none
+
+List all files added and what they do: none
+
+List all existing files that have been modified, and describe the changes:
+
+src/physics/cam/cospsimulator_intr.F90
+. remove pbuf_get_index calls for SH_CLDLIQ, SH_CLDICE. The indices were
+ not being used.
+. add optional arg to pbuf_get_index calls for SH_FLXPRC, SH_FLXSNW to
+ avoid endrun calls if fields not present in the pbuf. In that case
+ negative value indices are returned and appropriate action can be taken.
+ In this case the fields are assigned values of zero.
+
+If there were any failures reported from running test_driver.sh on any test
+platform, and checkin with these failures has been OK'd by the gatekeeper,
+then copy the lines from the td.*.status files for the failed tests to the
+appropriate machine below. All failed tests must be justified.
+
+cheyenne/intel/aux_cam:
+ERP_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.FW2000climo.cheyenne_intel.cam-outfrq9s_wcm_ne30 (Overall: FAIL) details:
+. expected failure
+
+izumi/nag/aux_cam:
+DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) details:
+. expected failure
+
+izumi/gnu/aux_cam: All PASS.
+
+CAM tag used for the baseline comparison tests if different than previous
+tag:
+
+Summarize any changes to answers: BFB
+
+===============================================================
+===============================================================
+
+Tag name: cam6_3_104
+Originator(s): fvitt
+Date: 5 Apr 2023
+One-line Summary: Misc bug fixes
+Github PR URL: https://github.com/ESCOMP/CAM/pull/785
+
+Purpose of changes (include the issue number and title text for each relevant GitHub issue):
+
+ Fix issues:
+ - ghg_mam4 is not working with cam_dev regression tests #773
+ - undefined rho values in nucleate_ice_cam_calc #781
+
+Describe any changes made to build system: N/A
+
+Describe any changes made to the namelist: N/A
+
+List any changes to the defaults for the boundary datasets: N/A
+
+Describe any substantial timing or memory changes: N/A
+
+Code reviewed by: brian-eaton cacraigucar nusbaume
+
+List all files eliminated: N/A
+
+List all files added and what they do: N/A
+
+List all existing files that have been modified, and describe the changes:
+
+M bld/namelist_files/use_cases/2000_cam6.xml
+ - use appropriate prescribed tracer inputs for trop_mam4 and ghg_mam4 chemistry
+ -- ghg_mam4 needs HALONS
+
+M cime_config/testdefs/testlist_cam.xml
+ - add regression test for GHG chem with cam_dev phys and year 2000 use case
+
+M src/chemistry/mozart/tracer_cnst.F90
+ - add error checking
+
+M src/physics/cam/nucleate_ice_cam.F90
+ - define rho for all model layers
+
+If there were any failures reported from running test_driver.sh on any test
+platform, and checkin with these failures has been OK'd by the gatekeeper,
+then copy the lines from the td.*.status files for the failed tests to the
+appropriate machine below. All failed tests must be justified.
+
+cheyenne/intel/aux_cam:
+ ERP_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.FW2000climo.cheyenne_intel.cam-outfrq9s_wcm_ne30 (Overall: FAIL) details:
+ - pre-existing failure
+
+izumi/nag/aux_cam:
+ DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) details:
+ - pre-existing failure
+
+izumi/gnu/aux_cam:
+ SMS_D_Ln9.f10_f10_mg37.2000_CAM%DEV%GHGMAM4_CLM50%SP_CICE%PRES_DOCN%DOM_MOSART_SGLC_SWAV_SESP.izumi_gnu.cam-outfrq9s (Overall: DIFF) details:
+ - new test
+
+Summarize any changes to answers: bit-for-bit unchanged
+
+===============================================================
+===============================================================
+
+Tag name: cam6_3_103
+Originator(s): cacraig
+Date: Apr 5, 2023
+One-line Summary: Update externals to almost match cesm2_3_alpha12d
+Github PR URL: https://github.com/ESCOMP/CAM/pull/783
+
+Purpose of changes (include the issue number and title text for each relevant GitHub issue):
+ - CLM tag is one newer than was used in alpha12d as it contains some of the coarse grid modifications
+ - FMS is an older version (inherited from cam6_3_102)
+ - cpl7 is one tag newer (inherited from cam6_3_102)
+ - Multi-instance is broken with current CMEPS external: https://github.com/ESCOMP/CAM/issues/733
+
+Describe any changes made to build system: N/A
+
+Describe any changes made to the namelist: N/A
+
+List any changes to the defaults for the boundary datasets: N/A
+
+Describe any substantial timing or memory changes: N/A
+
+Code reviewed by: nusbaume, eaton
+
+List all files eliminated: N/A
+
+List all files added and what they do: N/A
+
+List all existing files that have been modified, and describe the changes:
+M Externals.cfg
+ - Externals updated as described above
+
+If there were any failures reported from running test_driver.sh on any test
+platform, and checkin with these failures has been OK'd by the gatekeeper,
+then copy the lines from the td.*.status files for the failed tests to the
+appropriate machine below. All failed tests must be justified.
+
+cheyenne/intel/aux_cam:
+
+ ERP_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.FW2000climo.cheyenne_intel.cam-outfrq9s_wcm_ne30 (Overall: FAIL) details:
+ - pre-existing failure
+
+ ERC_D_Ln9_P144x1_Vnuopc.ne16pg3_ne16pg3_mg17.QPC6HIST.cheyenne_intel.cam-outfrq3s_ttrac_usecase (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq3s_cosp (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPMOZ.cheyenne_intel.cam-outfrq3s (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPX2000.cheyenne_intel.cam-outfrq3s (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.FADIAB.cheyenne_intel.cam-terminator (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.QPC5HIST.cheyenne_intel.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.T42_T42_mg17.FDABIP04.cheyenne_intel.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.T42_T42_mg17.FHS94.cheyenne_intel.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ ERI_D_Ln18_Vnuopc.f45_f45_mg37.QPC41850.cheyenne_intel.cam-co2rmp_usecase (Overall: NLFAIL) details:
+ ERP_D_Ln9_Vnuopc.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq9s (Overall: NLFAIL) details:
+ ERP_Lh12_Vnuopc.f19_f19_mg17.FW4madSD.cheyenne_intel.cam-outfrq3h (Overall: NLFAIL) details:
+ ERP_Ln9_P24x3_Vnuopc.f45_f45_mg37.QPWmaC6.cheyenne_intel.cam-outfrq9s_mee_fluxes (Overall: NLFAIL) details:
+ ERS_Ln9_Vnuopc.f19_f19_mg17.FSPCAMS.cheyenne_intel.cam-outfrq9s (Overall: NLFAIL) details:
+ ERS_Ln9_Vnuopc.ne0TESTONLYne5x4_ne0TESTONLYne5x4_mg37.FADIAB.cheyenne_intel.cam-outfrq3s_refined (Overall: NLFAIL) details:
+ SCT_D_Ln7_Vnuopc.T42_T42_mg17.QPC5.cheyenne_intel.cam-scm_prep (Overall: NLFAIL) details:
+ SMS_D_Ld2_Vnuopc.f19_f19_mg17.QPC5HIST.cheyenne_intel.cam-volc_usecase (Overall: NLFAIL) details:
+ SMS_D_Ld5_Vnuopc.f19_f19_mg17.PC4.cheyenne_intel.cam-cam4_port5d (Overall: NLFAIL) details:
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.QPC2000climo.cheyenne_intel.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.QPC5M7.cheyenne_intel.cam-outfrq9s (Overall: NLFAIL) details:
+ SMS_D_Ln9_Vnuopc.ne16_ne16_mg17.QPX2000.cheyenne_intel.cam-outfrq9s (Overall: NLFAIL) details:
+ SMS_D_Ln9_Vnuopc.T42_T42.FSCAM.cheyenne_intel.cam-outfrq9s (Overall: NLFAIL) details:
+ SMS_Ld5_Vnuopc.f09_f09_mg17.PC6.cheyenne_intel.cam-cam6_port_f09 (Overall: NLFAIL) details:
+ - namelist differences due to 'import_data_fields' added to docn_in and nuopc.runseq run seqeunce modified
+
+ ERP_D_Ln9_Vnuopc.f09_f09_mg17.QSC6.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ - concluded this answer change was most likely due to the change in value of the run sequence in nuopc.runseq having
+ phases_aofluxes_run being run before the ocn elements
+
+ ERP_D_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.F2000dev.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ld3_Vnuopc.f09_f09_mg17.FWHIST.cheyenne_intel.cam-reduced_hist1d (Overall: DIFF) details:
+ ERP_Ln9_Vmct.f09_f09_mg17.2000_CAM60_CLM50%SP_CICE5%PRES_DOCN%DOM_MOSART_SGLC_SWAV.cheyenne_intel.cam-outfrq9s (Overall: DIFF)
+details:
+ ERP_Ln9_Vnuopc.C96_C96_mg17.F2000climo.cheyenne_intel.cam-outfrq9s_mg3 (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F1850.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F2000climo.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F2000dev.cheyenne_intel.cam-outfrq9s_mg3 (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F2010climo.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.FHIST_BDRD.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f19_f19_mg17.FWsc1850.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.ne30_ne30_mg17.FCnudged.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERS_Ld3_Vnuopc.f10_f10_mg37.F1850.cheyenne_intel.cam-outfrq1d_14dec_ghg_cam_dev (Overall: DIFF) details:
+ ERS_Ln9_P288x1_Vnuopc.mpasa120_mpasa120.F2000climo.cheyenne_intel.cam-outfrq9s_mpasa120 (Overall: DIFF) details:
+ ERS_Ln9_P36x1_Vnuopc.mpasa480_mpasa480.F2000climo.cheyenne_intel.cam-outfrq9s_mpasa480 (Overall: DIFF) details:
+ ERS_Ln9_Vnuopc.f09_f09_mg17.FX2000.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERS_Ln9_Vnuopc.f19_f19_mg17.FXSD.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f09_f09_mg17.FCts2nudged.cheyenne_intel.cam-outfrq9s_leapday (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f09_f09_mg17.FCvbsxHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f09_f09_mg17.FSD.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.FWma2000climo.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.FWma2000climo.cheyenne_intel.cam-outfrq9s_waccm_ma_mam4 (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.FXHIST.cheyenne_intel.cam-outfrq9s_amie (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.ne16_ne16_mg17.FX2000.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc_P720x1.ne0ARCTICne30x4_ne0ARCTICne30x4_mt12.FHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc_P720x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc_P720x1.ne30pg3_ne30pg3_mg17.FCLTHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_Ld1_Vnuopc.f09_f09_mg17.FW2000climo.cheyenne_intel.cam-outfrq1d (Overall: DIFF) details:
+ SMS_Ld1_Vnuopc.f19_f19.F2000dev.cheyenne_intel.cam-outfrq1d (Overall: DIFF) details:
+ SMS_Ld1_Vnuopc.ne30pg3_ne30pg3_mg17.FC2010climo.cheyenne_intel.cam-outfrq1d (Overall: DIFF) details:
+ SMS_Lm13_Vnuopc.f10_f10_mg37.F2000climo.cheyenne_intel.cam-outfrq1m (Overall: DIFF) details:
+ SMS_Ln9_Vnuopc.f09_f09_mg17.F2010climo.cheyenne_intel.cam-nudging (Overall: DIFF) details:
+ SMS_Ln9_Vnuopc.f09_f09_mg17.FW1850.cheyenne_intel.cam-reduced_hist3s (Overall: DIFF) details:
+ SMS_Ln9_Vnuopc.f19_f19.F2000climo.cheyenne_intel.cam-silhs (Overall: DIFF) details:
+ SMS_Ln9_Vnuopc.f19_f19_mg17.FHIST.cheyenne_intel.cam-outfrq9s_nochem (Overall: DIFF) details:
+ - CTSM has answer changes which expect to change F compsets
+
+izumi/nag/aux_cam:
+ DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) details:
+ - pre-existing failure
+
+ ERP_Vnuopc_Ln9.ne5pg3_ne5pg3_mg37.QPC6.izumi_nag.cam-outfrq9s_clubbmf (Overall: DIFF) details:
+ - baseline failure due to new test accidentally introduced in CMEPS
+
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-carma_sea_salt (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_cosp (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_subcol (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_am (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_convmic (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_cospsathist (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPWmaC6.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QSPCAMS.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.mpasa480z32_mpasa480.FHS94.izumi_nag.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.ne16pg3_ne16pg3_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-outfrq3s_ttrac (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.T5_T5_mg37.QPC4.izumi_nag.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ ERI_D_Ln18_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_eoyttrac (Overall: NLFAIL) details:
+ ERI_D_Ln18_Vnuopc.f19_f19_mg17.QPC6.izumi_nag.cam-ghgrmp_e8 (Overall: NLFAIL) details:
+ ERI_D_Ln18_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s_bwic (Overall: NLFAIL) details:
+ ERI_D_Ln18_Vnuopc.ne5pg3_ne5pg3_mg37.FADIAB.izumi_nag.cam-outfrq3s_bwic (Overall: NLFAIL) details:
+ ERP_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC6.izumi_nag.cam-outfrq9s_clubbmf (Overall: NLFAIL) details:
+ ERS_Ln27_Vnuopc.ne5pg3_ne5pg3_mg37.FKESSLER.izumi_nag.cam-outfrq9s (Overall: NLFAIL) details:
+ ERS_Ln9_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq9s (Overall: NLFAIL) details:
+ PEM_D_Ln9_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details:
+ PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 (Overall: NLFAIL) details:
+ PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 (Overall: NLFAIL) details:
+ PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 (Overall: NLFAIL) details:
+ PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 (Overall: NLFAIL) details:
+ PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 (Overall: NLFAIL) details:
+ PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 (Overall: NLFAIL) details:
+ SMS_D_Ld2_Vnuopc.f45_f45_mg37.PC5.izumi_nag.cam-outfrq24h_port (Overall: NLFAIL) details:
+ SMS_D_Ln3_Vnuopc.ne5pg3_ne5pg3_mg37.QPX2000.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details:
+ SMS_D_Ln6_Vnuopc.ne5_ne5_mg37.QPWmaC4.izumi_nag.cam-outfrq3s_physgrid_tem (Overall: NLFAIL) details:
+ SMS_D_Ln7_Vnuopc.T42_T42_mg17.QPSCAMC5.izumi_nag.cam-scmarm (Overall: NLFAIL) details:
+ SMS_D_Ln9_P1x1_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details:
+ SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-rad_diag_mam (Overall: NLFAIL) details:
+ SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_ba (Overall: NLFAIL) details:
+ SMS_P48x1_D_Ln3_Vnuopc.f09_f09_mg17.QPC6HIST.izumi_nag.cam-outfrq3s_co2cycle_usecase (Overall: NLFAIL) details:
+ SUB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details:
+ TMC_D_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_eoyttrac (Overall: NLFAIL) details:
+ TMC_D_Vnuopc.T5_T5_mg37.QPC5.izumi_nag.cam-ghgrmp_e8 (Overall: NLFAIL) details:
+
+izumi/gnu/aux_cam:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.FADIAB.izumi_gnu.cam-terminator (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC4.izumi_gnu.cam-outfrq3s_diags (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_gnu.cam-outfrq3s_unicon (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_gnu.cam-rad_diag (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPSPCAMM.izumi_gnu.cam-outfrq3s (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC4.izumi_gnu.cam-outfrq3s_nudging_ne5_L26 (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq3s_ba (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.ne5pg2_ne5pg2_mg37.FADIAB.izumi_gnu.cam-outfrq3s (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.ne5pg4_ne5pg4_mg37.FADIAB.izumi_gnu.cam-outfrq3s (Overall: NLFAIL) details:
+ ERC_D_Ln9_Vnuopc.T5_T5_mg37.QPC3.izumi_gnu.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ ERI_D_Ln18_Vnuopc.T5_T5_mg37.QPC4.izumi_gnu.cam-co2rmp (Overall: NLFAIL) details:
+ ERP_Ln9_Vnuopc.ne5_ne5_mg37.FHS94.izumi_gnu.cam-outfrq9s (Overall: NLFAIL) details:
+ ERP_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq9s (Overall: NLFAIL) details:
+ PEM_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.FADIAB.izumi_gnu.cam-outfrq3s (Overall: NLFAIL) details:
+ PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal0 (Overall: NLFAIL) details:
+ PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal1 (Overall: NLFAIL) details:
+ PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal3 (Overall: NLFAIL) details:
+ SCT_D_Ln7_Vnuopc.T42_T42_mg17.QPC4.izumi_gnu.cam-scm_prep (Overall: NLFAIL) details:
+ SCT_D_Ln7_Vnuopc.T42_T42_mg17.QPC6.izumi_gnu.cam-scm_prep_c6 (Overall: NLFAIL) details:
+ SMS_D_Ln3_Vnuopc.f10_f10_mg37.QPMOZ.izumi_gnu.cam-outfrq3s_chemproc (Overall: NLFAIL) details:
+ SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPWmaC4.izumi_gnu.cam-outfrq9s_apmee (Overall: NLFAIL) details:
+ SMS_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-outfrq3s_ttrac (Overall: NLFAIL) details:
+ SMS_P48x1_D_Ln9_Vnuopc.f19_f19_mg17.FW4madSD.izumi_gnu.cam-outfrq9s (Overall: NLFAIL) details:
+ - namelist differences due to 'import_data_fields' added to docn_in and nuopc.runseq run seqeunce modified
+
+===============================================================
+===============================================================
+
+Tag name: cam6_3_102
+Originator(s): fvitt
+Date: 4 Apr 2023
+One-line Summary: Updates to TEM diagnostics
+Github PR URL: https://github.com/ESCOMP/CAM/pull/770
+
+Purpose of changes (include the issue number and title text for each relevant GitHub issue):
+
+ - fix issue with TEM diagnostics not implemented in cam_dev physics #769
+ - adopt the zm naming convention for the zonal mean outputs
+ - add 'Uzm','Vzm','Wzm','THzm' output fields
+
+Describe any changes made to build system: N/A
+
+Describe any changes made to the namelist: N/A
+
+List any changes to the defaults for the boundary datasets: N/A
+
+Describe any substantial timing or memory changes: N/A
+
+Code reviewed by: brian-eaton cacraigucar nusbaume
+
+List all files eliminated: N/A
+
+List all files added and what they do: N/A
+
+List all existing files that have been modified, and describe the changes:
+M cime_config/testdefs/testmods_dirs/cam/outfrq1d_14dec_ghg_cam_dev/user_nl_cam
+ - include namelist options to test TEM output
+
+M cime_config/testdefs/testmods_dirs/cam/outfrq1d_physgrid_tem_mpasa120_wcmsc/user_nl_cam
+M cime_config/testdefs/testmods_dirs/cam/outfrq3s_physgrid_tem/user_nl_cam
+M cime_config/testdefs/testmods_dirs/cam/outfrq9s_physgrid_tem_1deg/user_nl_cam
+ - use zm history field names for the TEM output
+
+M src/physics/cam/phys_grid_ctem.F90
+ - adopts the zm naming convention for the zonal mean outputs
+ - add 'Uzm','Vzm','Wzm','THzm' output fields
+
+M src/physics/cam_dev/physpkg.F90
+ - add calls to the phys_grid_ctem interface
+
+If there were any failures reported from running test_driver.sh on any test
+platform, and checkin with these failures has been OK'd by the gatekeeper,
+then copy the lines from the td.*.status files for the failed tests to the
+appropriate machine below. All failed tests must be justified.
+
+cheyenne/intel/aux_cam:
+ ERP_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.FW2000climo.cheyenne_intel.cam-outfrq9s_wcm_ne30 (Overall: FAIL) details:
+ - pre-existing failure
+
+ ERS_Ld3_Vnuopc.f10_f10_mg37.F1850.cheyenne_intel.cam-outfrq1d_14dec_ghg_cam_dev (Overall: DIFF) details:
+ FAIL ERS_Ld3_Vnuopc.f10_f10_mg37.F1850.cheyenne_intel.cam-outfrq1d_14dec_ghg_cam_dev NLCOMP
+ FAIL ERS_Ld3_Vnuopc.f10_f10_mg37.F1850.cheyenne_intel.cam-outfrq1d_14dec_ghg_cam_dev BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_101: ERROR BFAIL some baseline files were missing
+ - expected failure -- TEM output added to this test
+
+izumi/nag/aux_cam:
+ DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) details:
+ - pre-existing failure
+
+ SMS_D_Ln6_Vnuopc.ne5_ne5_mg37.QPWmaC4.izumi_nag.cam-outfrq3s_physgrid_tem (Overall: DIFF) details:
+ FAIL SMS_D_Ln6_Vnuopc.ne5_ne5_mg37.QPWmaC4.izumi_nag.cam-outfrq3s_physgrid_tem NLCOMP
+ FAIL SMS_D_Ln6_Vnuopc.ne5_ne5_mg37.QPWmaC4.izumi_nag.cam-outfrq3s_physgrid_tem BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_101_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ - change in TEM output field names
+
+izumi/gnu/aux_cam: All PASS
+
+Summarize any changes to answers: bit-for-bit unchanged
+
+===============================================================
+===============================================================
+
+Tag name: cam6_3_101
+Originator(s): cacraig, eaton, hannay, Thomas Toniazzo, Vince Larson
+Date: March 31, 2023
+One-line Summary: Create FLTHIST_v0a compset
+Github PR URL: Create initial FLTHIST and FMTHIST compsets for CAM7: https://github.com/ESCOMP/CAM/pull/767
+
+Purpose of changes (include the issue number and title text for each relevant GitHub issue):
+ - Create testing compsets based on FLT,FMT,FW and FX: https://github.com/ESCOMP/CAM/issues/765
+ - Partially implements these compsets: FLTHIST_v0a has been worked on with Cecile
+ FMTHIST_v0a has been started, but is not complete
+ Other compsets have not been worked on
+ - Update CLUBB external (fix bug found by Thomas Toniazzo): https://github.com/ESCOMP/CAM/issues/768
+
+Describe any changes made to build system:
+ - Introduce %LT (low_top) %MT (mid_top) and %GHGMAM4 (turn on ghg_mam4 chemistry)
+ - Remove %L58 and %L93 settings and replace with %LT and %MT
+
+Describe any changes made to the namelist: N/A
+
+List any changes to the defaults for the boundary datasets: N/A
+
+Describe any substantial timing or memory changes: N/A
+
+Code reviewed by: eaton, nusbaume, fvitt
+
+List all files eliminated: N/A
+
+List all files added and what they do:
+A bld/namelist_files/use_cases/hist_cam_lt.xml
+ - use_case for FLTHIST_v0a - developed in consultation with Cecile
+
+A bld/namelist_files/use_cases/hist_cam_mt.xml
+ - template use_case for FMTHIST_v0a - not completed
+
+List all existing files that have been modified, and describe the changes:
+M Externals_CAM.cfg
+ - Bring in CLUBB bug fix tag which fixes small bug in mono_flux_limiter.F90
+
+M bld/namelist_files/namelist_defaults_cam.xml
+ - Add initial condition files for ne30np4, npg=3 for 58 and 93 levels
+ - Add topo file for ne30np4, npg=3
+
+M cime_config/config_component.xml
+ - Remove %L58 and %L93
+ - Introduce %LT, %MT and %GHGMAM4 options
+
+M cime_config/config_compsets.xml
+ - Introduce FLTHIST_v0a compset (note that a regression test was not introduced for it yet)
+ - Create FMTHIST_v0a compset (not completed)
+ - replace %L58 and %L93 with %LT and %MT
+
+If there were any failures reported from running test_driver.sh on any test
+platform, and checkin with these failures has been OK'd by the gatekeeper,
+then copy the lines from the td.*.status files for the failed tests to the
+appropriate machine below. All failed tests must be justified.
+
+cheyenne/intel/aux_cam: all BFB except:
+ FAIL ERP_D_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.F2000dev.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL ERP_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.FW2000climo.cheyenne_intel.cam-outfrq9s_wcm_ne30 NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc_P720x1.ne30pg3_ne30pg3_mg17.FCLTHIST.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL SMS_Ld1_Vnuopc.ne30pg3_ne30pg3_mg17.FC2010climo.cheyenne_intel.cam-outfrq1d NLCOMP
+ - topo file change
+
+ FAIL ERP_D_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.F2000dev.cheyenne_intel.cam-outfrq9s BASELINE
+ FAIL SMS_D_Ln9_Vnuopc_P720x1.ne30pg3_ne30pg3_mg17.FCLTHIST.cheyenne_intel.cam-outfrq9s BASELINE
+ FAIL SMS_Ld1_Vnuopc.ne30pg3_ne30pg3_mg17.FC2010climo.cheyenne_intel.cam-outfrq1d BASELINE
+ - expected baseline changes due to new topo file
+
+ FAIL ERP_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.FW2000climo.cheyenne_intel.cam-outfrq9s_wcm_ne30 RUN time=119
+ - New failing test - issue https://github.com/ESCOMP/CAM/issues/772 opened
+
+izumi/nag/aux_cam: all BFB except:
+ FAIL DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae RUN time=180
+ - pre-existing failure
+
+izumi/gnu/aux_cam: all BFB
+
+===============================================================
+===============================================================
+
+Tag name: cam6_3_100
+Originator(s): fvitt
+Date: 20 Mar 2023
+One-line Summary: Introduce prognostic GHG chemistry mechanism for CAM7
+Github PR URL: https://github.com/ESCOMP/CAM/pull/766
+
+Purpose of changes (include the issue number and title text for each relevant GitHub issue):
+
+ New chemistry mechanism for CAM7 prognostic GHGs #762
+
+Describe any changes made to build system: N/A
+
+Describe any changes made to the namelist: N/A
+
+List any changes to the defaults for the boundary datasets: N/A
+
+Describe any substantial timing or memory changes: N/A
+
+Code reviewed by: brian-eaton jtruesdal cacraigucar nusbaume
+
+List all files eliminated: N/A
+
+List all files added and what they do:
+A src/chemistry/pp_ghg_mam4/chem_mech.doc
+A src/chemistry/pp_ghg_mam4/chem_mech.in
+A src/chemistry/pp_ghg_mam4/chem_mods.F90
+A src/chemistry/pp_ghg_mam4/m_rxt_id.F90
+A src/chemistry/pp_ghg_mam4/m_spc_id.F90
+A src/chemistry/pp_ghg_mam4/mo_adjrxt.F90
+A src/chemistry/pp_ghg_mam4/mo_exp_sol.F90
+A src/chemistry/pp_ghg_mam4/mo_imp_sol.F90
+A src/chemistry/pp_ghg_mam4/mo_indprd.F90
+A src/chemistry/pp_ghg_mam4/mo_lin_matrix.F90
+A src/chemistry/pp_ghg_mam4/mo_lu_factor.F90
+A src/chemistry/pp_ghg_mam4/mo_lu_solve.F90
+A src/chemistry/pp_ghg_mam4/mo_nln_matrix.F90
+A src/chemistry/pp_ghg_mam4/mo_phtadj.F90
+A src/chemistry/pp_ghg_mam4/mo_prod_loss.F90
+A src/chemistry/pp_ghg_mam4/mo_rxt_rates_conv.F90
+A src/chemistry/pp_ghg_mam4/mo_setrxt.F90
+A src/chemistry/pp_ghg_mam4/mo_sim_dat.F90
+ - add ghg_mam4 chemistry mechanism
+
+List all existing files that have been modified, and describe the changes:
+M bld/namelist_files/namelist_definition.xml
+M bld/config_files/definition.xml
+M bld/configure
+ - add ghg_mam4 chem option
+
+M bld/build-namelist
+M bld/namelist_files/namelist_defaults_cam.xml
+ - default namelist settings for ghg_mam4 chemistry
+
+M cime_config/testdefs/testlist_cam.xml
+ - add test for ghg_mam4
+ - replace outfrq1d_14dec_L32wsc with outfrq1d_14dec_ghg_cam_dev
+ -- replaces "-chem waccm_sc_mam4" with "-chem ghg_mam4"
+ -- this is more relevant for CAM7 development
+
+If there were any failures reported from running test_driver.sh on any test
+platform, and checkin with these failures has been OK'd by the gatekeeper,
+then copy the lines from the td.*.status files for the failed tests to the
+appropriate machine below. All failed tests must be justified.
+
+cheyenne/intel/aux_cam:
+ ERS_Ld3_Vnuopc.f10_f10_mg37.F1850.cheyenne_intel.cam-outfrq1d_14dec_ghg_cam_dev (Overall: DIFF) details:
+ - new test which replaces outfrq1d_14dec_L32wsc
+
+izumi/nag/aux_cam:
+ DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) details:
+ - pre-existing failure
+
+izumi/gnu/aux_cam: All PASS
+
+Summarize any changes to answers: bit-for-bit unchanged
+
+===============================================================
+===============================================================
+
+Tag name: cam6_3_099
+Originator(s): adamrher, eaton
+Date: Thu Mar 16 11:22:00 AM EDT 2023
+One-line Summary: fix drydep emissions for cam_dev physics
+Github PR URL: https://github.com/ESCOMP/CAM/pull/763
+
+Purpose of changes (include the issue number and title text for each relevant GitHub issue):
+
+. Fixes #759 (https://github.com/ESCOMP/CAM/issues/759)
+ drydep of gas phase species "skipped" in cam_dev
+
+Describe any changes made to build system: none
+
+Describe any changes made to the namelist: none
+
+List any changes to the defaults for the boundary datasets: none
+
+Describe any substantial timing or memory changes: none
+
+Code reviewed by: jtruesdal, cacraigucar, fvitt, nusbaume
+
+List all files eliminated: none
+
+List all files added and what they do: none
+
+List all existing files that have been modified, and describe the changes:
+
+src/chemistry/mozart/chemistry.F90
+. add state%rpdel, state%rpdeldry to actual args in call to
+ gas_phase_chemdr
+
+src/chemistry/mozart/mo_gas_phase_chemdr.F90
+. add rpdel, rpdeldry to dummy args for gas_phase_chemdr
+. access cam_physpkg_is from phys_control module
+. access gravit from physconst
+. access cnst_type from constituents
+. if cam_dev physics then apply drydep fluxes directly to the species
+ tendency array, else apply to the emissions array.
+
+
+If there were any failures reported from running test_driver.sh on any test
+platform, and checkin with these failures has been OK'd by the gatekeeper,
+then copy the lines from the td.*.status files for the failed tests to the
+appropriate machine below. All failed tests must be justified.
+
+cheyenne/intel/aux_cam:
+ ERP_D_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.F2000dev.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F2000dev.cheyenne_intel.cam-outfrq9s_mg3 (Overall: DIFF) details:
+ ERS_Ld3_Vnuopc.f10_f10_mg37.F1850.cheyenne_intel.cam-outfrq1d_14dec_L32wsc (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc_P720x1.ne30pg3_ne30pg3_mg17.FCLTHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_Ld1_Vnuopc.f19_f19.F2000dev.cheyenne_intel.cam-outfrq1d (Overall: DIFF) details:
+
+ - There are baseline diffs in all tests that use cam_dev physics.
+
+izumi/nag/aux_cam:
+ DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) details:
+
+ - pre-existing failure
+
+izumi/gnu/aux_cam:
+
+ - All PASS
+
+CAM tag used for the baseline comparison tests if different than previous
+tag:
+
+Summarize any changes to answers: BFB except for cam_dev physics due to
+ fix in treatment of drydep fluxes.
+
+===============================================================
+===============================================================
+
+Tag name: cam6_3_098
+Originator(s): mvertens, eaton
+Date: Tue Mar 14 09:16:31 MDT 2023
+One-line Summary: always pass NDEP from CAM and remove sst specs
+Github PR URL: https://github.com/ESCOMP/CAM/pull/764
+
+Purpose of changes (include the issue number and title text for each relevant GitHub issue):
+
+. Resolve issue #104 - https://github.com/ESCOMP/CAM/issues/104
+ Always send Nitrogen-deposition to surface components.
+
+ This PR enables CAM to read in ndep (using the CDEPS inline API) from
+ forcing files if it is not computing NDEP prognostically. As a result
+ CAM will ALWAYS send NDEP to the mediator.
+
+ Right how, CLM is not using the passed NDEP from the streams - since it
+ is still reading the drv_flds_in for NDEP.
+
+ It is now possible for the drv_flds_in entry for ndep to be removed
+ and CLM can always accept NDEP from either CAM or DATM.
+
+ New XML variables are introduced to specify the stream forcing. This is
+ being done in CTSM as well for all of its CDEPS stream specific variables.
+
+ NOTE: that CTSM also needs a new PR in order to accept these new fields
+ from CAM rather than use its own internal streams.
+
+. Remove old sst specs from the namelist. This is a cleanup.
+
+Describe any changes made to build system: none
+
+Describe any changes made to the namelist:
+. The follow variables are in new group ndep_stream_nl which is read in
+ src/cpl/nuopc/atm_stream_ndep.F90
+ stream_ndep_year_first
+ stream_ndep_year_last
+ stream_ndep_year_align
+ stream_ndep_data_filename
+ stream_ndep_mesh_filename
+
+List any changes to the defaults for the boundary datasets:
+. NDEP datasets are added by cime_config/config_component.xml
+
+Describe any substantial timing or memory changes: not tested
+
+Code reviewed by: gold2718, fvitt, cacraigucar, nusbaume, brian-eaton
+
+List all files eliminated: none
+
+List all files added and what they do:
+
+src/cpl/nuopc/atm_stream_ndep.F90
+. Contains methods for reading in nitrogen deposition data file. Also
+ includes functions for dynamic ndep file handling and interpolation.
+. Reads namelist group ndep_stream_nl from the atm_in file.
+
+List all existing files that have been modified, and describe the changes:
+bld/configure
+. remove documentation for -ocn option.
+
+bld/namelist_files/namelist_defaults_cam.xml
+. remove old settings for bndtvs, bndtvs_domain, and focndomain. DOM and
+ DOCN are no longer used.
+
+bld/namelist_files/namelist_definition.xml
+. 5 new variables, stream_ndep_*, are added to group ndep_stream_nl
+. bndtvs, focndomain, and bndtvs_domain removed
+. 5 new variables, *_ndep, added to group ndep_stream_nml
+
+bld/namelist_files/use_cases/1850-2005_cam5.xml
+bld/namelist_files/use_cases/sd_waccm_sulfur.xml
+bld/namelist_files/use_cases/waccm_carma_bc_2013_cam4.xml
+. remove defaults for stream_year_*, bndtvs, sstcyc
+
+bld/namelist_files/use_cases/aquaplanet_cam3.xml
+bld/namelist_files/use_cases/aquaplanet_cam4.xml
+bld/namelist_files/use_cases/aquaplanet_cam5.xml
+bld/namelist_files/use_cases/aquaplanet_cam6.xml
+bld/namelist_files/use_cases/aquaplanet_rce_cam6.xml
+. remove default for aqua_planet (no longer in the namelist definition file)
+
+cime_config/buildnml
+. get values of stream_ndep_* from the corresponding case variables
+ (CAM_STREAM_NDEP_*). Add the namelist key=value pairs to the string that
+ is generated to be passed via the -namelist option.
+
+cime_config/config_component.xml
+. add values for the case variables CAM_STREAM_NDEP_*
+
+src/control/camsrfexch.F90
+. remove conditionals from allocation of cam_out%nhx_nitrogen_flx and
+ cam_out%noy_nitrogen_flx. CAM always provides this data now.
+
+src/cpl/nuopc/atm_comp_nuopc.F90
+. add explicit use/only statements for ESMF module
+. add ESMF Mesh and clock objects with module scope, and add to the calling
+ args for export_fields. They are needed to generate streams.
+
+src/cpl/nuopc/atm_import_export.F90
+. mods so that nhx/noy are always in the list of fields that are exported.
+ If ndep_nflds=0 then the set_active_Faxa_* flags are set false.
+. model_mesh, model_clock added to export_fields arg list
+. add code to export_fields to use the stream code to set nhx/noy
+ deposition if it hasn't been computed.
+
+If there were any failures reported from running test_driver.sh on any test
+platform, and checkin with these failures has been OK'd by the gatekeeper,
+then copy the lines from the td.*.status files for the failed tests to the
+appropriate machine below. All failed tests must be justified.
+
+cheyenne/intel/aux_cam:
+ ERC_D_Ln9_P144x1_Vnuopc.ne16pg3_ne16pg3_mg17.QPC6HIST.cheyenne_intel.cam-outfrq3s_ttrac_usecase (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_P144x1_Vnuopc.ne16pg3_ne16pg3_mg17.QPC6HIST.cheyenne_intel.cam-outfrq3s_ttrac_usecase NLCOMP
+ FAIL ERC_D_Ln9_P144x1_Vnuopc.ne16pg3_ne16pg3_mg17.QPC6HIST.cheyenne_intel.cam-outfrq3s_ttrac_usecase BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vmct.T42_T42_mg17.FDABIP04.cheyenne_intel.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ FAIL ERC_D_Ln9_Vmct.T42_T42_mg17.FDABIP04.cheyenne_intel.cam-outfrq3s_usecase NLCOMP
+ ERC_D_Ln9_Vmct.T42_T42_mg17.FHS94.cheyenne_intel.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ FAIL ERC_D_Ln9_Vmct.T42_T42_mg17.FHS94.cheyenne_intel.cam-outfrq3s_usecase NLCOMP
+ ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq3s_cosp (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq3s_cosp NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq3s_cosp BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPMOZ.cheyenne_intel.cam-outfrq3s (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPMOZ.cheyenne_intel.cam-outfrq3s NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPMOZ.cheyenne_intel.cam-outfrq3s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPX2000.cheyenne_intel.cam-outfrq3s (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPX2000.cheyenne_intel.cam-outfrq3s NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPX2000.cheyenne_intel.cam-outfrq3s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.FADIAB.cheyenne_intel.cam-terminator (Overall: NLFAIL) details:
+ FAIL ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.FADIAB.cheyenne_intel.cam-terminator NLCOMP
+ ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.QPC5HIST.cheyenne_intel.cam-outfrq3s_usecase (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.QPC5HIST.cheyenne_intel.cam-outfrq3s_usecase NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.QPC5HIST.cheyenne_intel.cam-outfrq3s_usecase BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.T42_T42_mg17.FDABIP04.cheyenne_intel.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ FAIL ERC_D_Ln9_Vnuopc.T42_T42_mg17.FDABIP04.cheyenne_intel.cam-outfrq3s_usecase NLCOMP
+ ERC_D_Ln9_Vnuopc.T42_T42_mg17.FHS94.cheyenne_intel.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ FAIL ERC_D_Ln9_Vnuopc.T42_T42_mg17.FHS94.cheyenne_intel.cam-outfrq3s_usecase NLCOMP
+ ERI_D_Ln18_Vnuopc.f45_f45_mg37.QPC41850.cheyenne_intel.cam-co2rmp_usecase (Overall: DIFF) details:
+ FAIL ERI_D_Ln18_Vnuopc.f45_f45_mg37.QPC41850.cheyenne_intel.cam-co2rmp_usecase NLCOMP
+ FAIL ERI_D_Ln18_Vnuopc.f45_f45_mg37.QPC41850.cheyenne_intel.cam-co2rmp_usecase BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERP_D_Ln9_Vmct.f09_f09_mg17.QSC6.cheyenne_intel.cam-outfrq9s (Overall: NLFAIL) details:
+ FAIL ERP_D_Ln9_Vmct.f09_f09_mg17.QSC6.cheyenne_intel.cam-outfrq9s NLCOMP
+ ERP_D_Ln9_Vmct.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq9s (Overall: NLFAIL) details:
+ FAIL ERP_D_Ln9_Vmct.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq9s NLCOMP
+ ERP_D_Ln9_Vnuopc.f09_f09_mg17.QSC6.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ FAIL ERP_D_Ln9_Vnuopc.f09_f09_mg17.QSC6.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL ERP_D_Ln9_Vnuopc.f09_f09_mg17.QSC6.cheyenne_intel.cam-outfrq9s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERP_D_Ln9_Vnuopc.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ FAIL ERP_D_Ln9_Vnuopc.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL ERP_D_Ln9_Vnuopc.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq9s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERP_D_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.F2000dev.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ FAIL ERP_D_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.F2000dev.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL ERP_D_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.F2000dev.cheyenne_intel.cam-outfrq9s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERP_Ld3_Vnuopc.f09_f09_mg17.FWHIST.cheyenne_intel.cam-reduced_hist1d (Overall: NLFAIL) details:
+ FAIL ERP_Ld3_Vnuopc.f09_f09_mg17.FWHIST.cheyenne_intel.cam-reduced_hist1d NLCOMP
+ ERP_Lh12_Vnuopc.f19_f19_mg17.FW4madSD.cheyenne_intel.cam-outfrq3h (Overall: DIFF) details:
+ FAIL ERP_Lh12_Vnuopc.f19_f19_mg17.FW4madSD.cheyenne_intel.cam-outfrq3h NLCOMP
+ FAIL ERP_Lh12_Vnuopc.f19_f19_mg17.FW4madSD.cheyenne_intel.cam-outfrq3h BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERP_Ln9_P24x3_Vnuopc.f45_f45_mg37.QPWmaC6.cheyenne_intel.cam-outfrq9s_mee_fluxes (Overall: DIFF) details:
+ FAIL ERP_Ln9_P24x3_Vnuopc.f45_f45_mg37.QPWmaC6.cheyenne_intel.cam-outfrq9s_mee_fluxes NLCOMP
+ FAIL ERP_Ln9_P24x3_Vnuopc.f45_f45_mg37.QPWmaC6.cheyenne_intel.cam-outfrq9s_mee_fluxes BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERP_Ln9_Vmct.f09_f09_mg17.2000_CAM60_CLM50%SP_CICE5%PRES_DOCN%DOM_MOSART_SGLC_SWAV.cheyenne_intel.cam-outfrq9s (Overall: NLFAIL) details:
+ FAIL ERP_Ln9_Vmct.f09_f09_mg17.2000_CAM60_CLM50%SP_CICE5%PRES_DOCN%DOM_MOSART_SGLC_SWAV.cheyenne_intel.cam-outfrq9s NLCOMP
+ ERP_Ln9_Vnuopc.C96_C96_mg17.F2000climo.cheyenne_intel.cam-outfrq9s_mg3 (Overall: DIFF) details:
+ FAIL ERP_Ln9_Vnuopc.C96_C96_mg17.F2000climo.cheyenne_intel.cam-outfrq9s_mg3 NLCOMP
+ FAIL ERP_Ln9_Vnuopc.C96_C96_mg17.F2000climo.cheyenne_intel.cam-outfrq9s_mg3 BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F1850.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ FAIL ERP_Ln9_Vnuopc.f09_f09_mg17.F1850.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL ERP_Ln9_Vnuopc.f09_f09_mg17.F1850.cheyenne_intel.cam-outfrq9s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F2000climo.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ FAIL ERP_Ln9_Vnuopc.f09_f09_mg17.F2000climo.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL ERP_Ln9_Vnuopc.f09_f09_mg17.F2000climo.cheyenne_intel.cam-outfrq9s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F2000dev.cheyenne_intel.cam-outfrq9s_mg3 (Overall: DIFF) details:
+ FAIL ERP_Ln9_Vnuopc.f09_f09_mg17.F2000dev.cheyenne_intel.cam-outfrq9s_mg3 NLCOMP
+ FAIL ERP_Ln9_Vnuopc.f09_f09_mg17.F2000dev.cheyenne_intel.cam-outfrq9s_mg3 BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F2010climo.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ FAIL ERP_Ln9_Vnuopc.f09_f09_mg17.F2010climo.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL ERP_Ln9_Vnuopc.f09_f09_mg17.F2010climo.cheyenne_intel.cam-outfrq9s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERP_Ln9_Vnuopc.f09_f09_mg17.FHIST_BDRD.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ FAIL ERP_Ln9_Vnuopc.f09_f09_mg17.FHIST_BDRD.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL ERP_Ln9_Vnuopc.f09_f09_mg17.FHIST_BDRD.cheyenne_intel.cam-outfrq9s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERP_Ln9_Vnuopc.f19_f19_mg17.FWsc1850.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ FAIL ERP_Ln9_Vnuopc.f19_f19_mg17.FWsc1850.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL ERP_Ln9_Vnuopc.f19_f19_mg17.FWsc1850.cheyenne_intel.cam-outfrq9s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERP_Ln9_Vnuopc.ne30_ne30_mg17.FCnudged.cheyenne_intel.cam-outfrq9s (Overall: NLFAIL) details:
+ FAIL ERP_Ln9_Vnuopc.ne30_ne30_mg17.FCnudged.cheyenne_intel.cam-outfrq9s NLCOMP
+ ERP_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.FW2000climo.cheyenne_intel.cam-outfrq9s_wcm_ne30 (Overall: NLFAIL) details:
+ FAIL ERP_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.FW2000climo.cheyenne_intel.cam-outfrq9s_wcm_ne30 NLCOMP
+ ERS_Ld3_Vnuopc.f10_f10_mg37.F1850.cheyenne_intel.cam-outfrq1d_14dec_L32wsc (Overall: DIFF) details:
+ FAIL ERS_Ld3_Vnuopc.f10_f10_mg37.F1850.cheyenne_intel.cam-outfrq1d_14dec_L32wsc NLCOMP
+ FAIL ERS_Ld3_Vnuopc.f10_f10_mg37.F1850.cheyenne_intel.cam-outfrq1d_14dec_L32wsc BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERS_Ln9_P288x1_Vnuopc.mpasa120_mpasa120.F2000climo.cheyenne_intel.cam-outfrq9s_mpasa120 (Overall: DIFF) details:
+ FAIL ERS_Ln9_P288x1_Vnuopc.mpasa120_mpasa120.F2000climo.cheyenne_intel.cam-outfrq9s_mpasa120 NLCOMP
+ FAIL ERS_Ln9_P288x1_Vnuopc.mpasa120_mpasa120.F2000climo.cheyenne_intel.cam-outfrq9s_mpasa120 BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERS_Ln9_P36x1_Vnuopc.mpasa480_mpasa480.F2000climo.cheyenne_intel.cam-outfrq9s_mpasa480 (Overall: DIFF) details:
+ FAIL ERS_Ln9_P36x1_Vnuopc.mpasa480_mpasa480.F2000climo.cheyenne_intel.cam-outfrq9s_mpasa480 NLCOMP
+ FAIL ERS_Ln9_P36x1_Vnuopc.mpasa480_mpasa480.F2000climo.cheyenne_intel.cam-outfrq9s_mpasa480 BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERS_Ln9_Vnuopc.f09_f09_mg17.FX2000.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ FAIL ERS_Ln9_Vnuopc.f09_f09_mg17.FX2000.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL ERS_Ln9_Vnuopc.f09_f09_mg17.FX2000.cheyenne_intel.cam-outfrq9s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERS_Ln9_Vnuopc.f19_f19_mg17.FSPCAMS.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ FAIL ERS_Ln9_Vnuopc.f19_f19_mg17.FSPCAMS.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL ERS_Ln9_Vnuopc.f19_f19_mg17.FSPCAMS.cheyenne_intel.cam-outfrq9s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERS_Ln9_Vnuopc.f19_f19_mg17.FXSD.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ FAIL ERS_Ln9_Vnuopc.f19_f19_mg17.FXSD.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL ERS_Ln9_Vnuopc.f19_f19_mg17.FXSD.cheyenne_intel.cam-outfrq9s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERS_Ln9_Vnuopc.ne0TESTONLYne5x4_ne0TESTONLYne5x4_mg37.FADIAB.cheyenne_intel.cam-outfrq3s_refined (Overall: NLFAIL) details:
+ FAIL ERS_Ln9_Vnuopc.ne0TESTONLYne5x4_ne0TESTONLYne5x4_mg37.FADIAB.cheyenne_intel.cam-outfrq3s_refined NLCOMP
+ SCT_D_Ln7_Vnuopc.T42_T42_mg17.QPC5.cheyenne_intel.cam-scm_prep (Overall: DIFF) details:
+ FAIL SCT_D_Ln7_Vnuopc.T42_T42_mg17.QPC5.cheyenne_intel.cam-scm_prep NLCOMP
+ FAIL SCT_D_Ln7_Vnuopc.T42_T42_mg17.QPC5.cheyenne_intel.cam-scm_prep BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_D_Ld2_Vnuopc.f19_f19_mg17.QPC5HIST.cheyenne_intel.cam-volc_usecase (Overall: DIFF) details:
+ FAIL SMS_D_Ld2_Vnuopc.f19_f19_mg17.QPC5HIST.cheyenne_intel.cam-volc_usecase NLCOMP
+ FAIL SMS_D_Ld2_Vnuopc.f19_f19_mg17.QPC5HIST.cheyenne_intel.cam-volc_usecase BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_D_Ld5_Vnuopc.f19_f19_mg17.PC4.cheyenne_intel.cam-cam4_port5d (Overall: NLFAIL) details:
+ FAIL SMS_D_Ld5_Vnuopc.f19_f19_mg17.PC4.cheyenne_intel.cam-cam4_port5d NLCOMP
+ SMS_D_Ln9_Vmct.T42_T42.2000_CAM60%SCAM_CLM50%SP_CICE5%PRES_DOCN%DOM_SROF_SGLC_SWAV.cheyenne_intel.cam-outfrq9s (Overall: NLFAIL) details:
+ FAIL SMS_D_Ln9_Vmct.T42_T42.2000_CAM60%SCAM_CLM50%SP_CICE5%PRES_DOCN%DOM_SROF_SGLC_SWAV.cheyenne_intel.cam-outfrq9s NLCOMP
+ SMS_D_Ln9_Vnuopc.f09_f09_mg17.FCts2nudged.cheyenne_intel.cam-outfrq9s_leapday (Overall: NLFAIL) details:
+ FAIL SMS_D_Ln9_Vnuopc.f09_f09_mg17.FCts2nudged.cheyenne_intel.cam-outfrq9s_leapday NLCOMP
+ SMS_D_Ln9_Vnuopc.f09_f09_mg17.FCvbsxHIST.cheyenne_intel.cam-outfrq9s (Overall: NLFAIL) details:
+ FAIL SMS_D_Ln9_Vnuopc.f09_f09_mg17.FCvbsxHIST.cheyenne_intel.cam-outfrq9s NLCOMP
+ SMS_D_Ln9_Vnuopc.f09_f09_mg17.FSD.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ FAIL SMS_D_Ln9_Vnuopc.f09_f09_mg17.FSD.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc.f09_f09_mg17.FSD.cheyenne_intel.cam-outfrq9s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.FWma2000climo.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ FAIL SMS_D_Ln9_Vnuopc.f19_f19_mg17.FWma2000climo.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc.f19_f19_mg17.FWma2000climo.cheyenne_intel.cam-outfrq9s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.FWma2000climo.cheyenne_intel.cam-outfrq9s_waccm_ma_mam4 (Overall: DIFF) details:
+ FAIL SMS_D_Ln9_Vnuopc.f19_f19_mg17.FWma2000climo.cheyenne_intel.cam-outfrq9s_waccm_ma_mam4 NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc.f19_f19_mg17.FWma2000climo.cheyenne_intel.cam-outfrq9s_waccm_ma_mam4 BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.FXHIST.cheyenne_intel.cam-outfrq9s_amie (Overall: DIFF) details:
+ FAIL SMS_D_Ln9_Vnuopc.f19_f19_mg17.FXHIST.cheyenne_intel.cam-outfrq9s_amie NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc.f19_f19_mg17.FXHIST.cheyenne_intel.cam-outfrq9s_amie BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.QPC2000climo.cheyenne_intel.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ FAIL SMS_D_Ln9_Vnuopc.f19_f19_mg17.QPC2000climo.cheyenne_intel.cam-outfrq3s_usecase NLCOMP
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.QPC5M7.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ FAIL SMS_D_Ln9_Vnuopc.f19_f19_mg17.QPC5M7.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc.f19_f19_mg17.QPC5M7.cheyenne_intel.cam-outfrq9s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_D_Ln9_Vnuopc.ne16_ne16_mg17.FX2000.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ FAIL SMS_D_Ln9_Vnuopc.ne16_ne16_mg17.FX2000.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc.ne16_ne16_mg17.FX2000.cheyenne_intel.cam-outfrq9s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_D_Ln9_Vnuopc.ne16_ne16_mg17.QPX2000.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ FAIL SMS_D_Ln9_Vnuopc.ne16_ne16_mg17.QPX2000.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc.ne16_ne16_mg17.QPX2000.cheyenne_intel.cam-outfrq9s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_D_Ln9_Vnuopc_P720x1.ne0ARCTICne30x4_ne0ARCTICne30x4_mt12.FHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ FAIL SMS_D_Ln9_Vnuopc_P720x1.ne0ARCTICne30x4_ne0ARCTICne30x4_mt12.FHIST.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc_P720x1.ne0ARCTICne30x4_ne0ARCTICne30x4_mt12.FHIST.cheyenne_intel.cam-outfrq9s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_D_Ln9_Vnuopc_P720x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.cheyenne_intel.cam-outfrq9s (Overall: NLFAIL) details:
+ FAIL SMS_D_Ln9_Vnuopc_P720x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.cheyenne_intel.cam-outfrq9s NLCOMP
+ SMS_D_Ln9_Vnuopc_P720x1.ne30pg3_ne30pg3_mg17.FCLTHIST.cheyenne_intel.cam-outfrq9s (Overall: NLFAIL) details:
+ FAIL SMS_D_Ln9_Vnuopc_P720x1.ne30pg3_ne30pg3_mg17.FCLTHIST.cheyenne_intel.cam-outfrq9s NLCOMP
+ SMS_D_Ln9_Vnuopc.T42_T42.FSCAM.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ FAIL SMS_D_Ln9_Vnuopc.T42_T42.FSCAM.cheyenne_intel.cam-outfrq9s NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc.T42_T42.FSCAM.cheyenne_intel.cam-outfrq9s BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_Ld1_Vnuopc.f09_f09_mg17.FW2000climo.cheyenne_intel.cam-outfrq1d (Overall: NLFAIL) details:
+ FAIL SMS_Ld1_Vnuopc.f09_f09_mg17.FW2000climo.cheyenne_intel.cam-outfrq1d NLCOMP
+ SMS_Ld1_Vnuopc.f19_f19.F2000dev.cheyenne_intel.cam-outfrq1d (Overall: DIFF) details:
+ FAIL SMS_Ld1_Vnuopc.f19_f19.F2000dev.cheyenne_intel.cam-outfrq1d NLCOMP
+ FAIL SMS_Ld1_Vnuopc.f19_f19.F2000dev.cheyenne_intel.cam-outfrq1d BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_Ld1_Vnuopc.ne30pg3_ne30pg3_mg17.FC2010climo.cheyenne_intel.cam-outfrq1d (Overall: NLFAIL) details:
+ FAIL SMS_Ld1_Vnuopc.ne30pg3_ne30pg3_mg17.FC2010climo.cheyenne_intel.cam-outfrq1d NLCOMP
+ SMS_Ld5_Vnuopc.f09_f09_mg17.PC6.cheyenne_intel.cam-cam6_port_f09 (Overall: NLFAIL) details:
+ FAIL SMS_Ld5_Vnuopc.f09_f09_mg17.PC6.cheyenne_intel.cam-cam6_port_f09 NLCOMP
+ SMS_Lm13_Vnuopc.f10_f10_mg37.F2000climo.cheyenne_intel.cam-outfrq1m (Overall: DIFF) details:
+ FAIL SMS_Lm13_Vnuopc.f10_f10_mg37.F2000climo.cheyenne_intel.cam-outfrq1m NLCOMP
+ FAIL SMS_Lm13_Vnuopc.f10_f10_mg37.F2000climo.cheyenne_intel.cam-outfrq1m BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_Ln9_Vnuopc.f09_f09_mg17.F2010climo.cheyenne_intel.cam-nudging (Overall: DIFF) details:
+ FAIL SMS_Ln9_Vnuopc.f09_f09_mg17.F2010climo.cheyenne_intel.cam-nudging NLCOMP
+ FAIL SMS_Ln9_Vnuopc.f09_f09_mg17.F2010climo.cheyenne_intel.cam-nudging BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_Ln9_Vnuopc.f09_f09_mg17.FW1850.cheyenne_intel.cam-reduced_hist3s (Overall: NLFAIL) details:
+ FAIL SMS_Ln9_Vnuopc.f09_f09_mg17.FW1850.cheyenne_intel.cam-reduced_hist3s NLCOMP
+ SMS_Ln9_Vnuopc.f19_f19.F2000climo.cheyenne_intel.cam-silhs (Overall: DIFF) details:
+ FAIL SMS_Ln9_Vnuopc.f19_f19.F2000climo.cheyenne_intel.cam-silhs NLCOMP
+ FAIL SMS_Ln9_Vnuopc.f19_f19.F2000climo.cheyenne_intel.cam-silhs BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_Ln9_Vnuopc.f19_f19_mg17.FHIST.cheyenne_intel.cam-outfrq9s_nochem (Overall: DIFF) details:
+ FAIL SMS_Ln9_Vnuopc.f19_f19_mg17.FHIST.cheyenne_intel.cam-outfrq9s_nochem NLCOMP
+ FAIL SMS_Ln9_Vnuopc.f19_f19_mg17.FHIST.cheyenne_intel.cam-outfrq9s_nochem BASELINE /glade/p/cesm/amwg/cesm_baselines/cam6_3_097: FIELDLIST field lists differ (otherwise bit-for-bit)
+
+The NLCOMP failures are due to adding the ndep_stream_nl group to atm_in.
+The BASELINE test failures are due to different field list in the cpl.hi files.
+
+izumi/nag/aux_cam:
+ DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) details:
+ FAIL DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae NLCOMP
+ FAIL DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae RUN time=223
+ PEND DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae COMPARE_base_da
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-carma_sea_salt (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-carma_sea_salt NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-carma_sea_salt BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_cosp (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_cosp NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_cosp BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_subcol (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_subcol NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_subcol BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_am (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_am NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_am BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_convmic (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_convmic NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_convmic BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_cospsathist (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_cospsathist NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_cospsathist BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPWmaC6.izumi_nag.cam-outfrq3s (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPWmaC6.izumi_nag.cam-outfrq3s NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPWmaC6.izumi_nag.cam-outfrq3s BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QSPCAMS.izumi_nag.cam-outfrq3s (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QSPCAMS.izumi_nag.cam-outfrq3s NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QSPCAMS.izumi_nag.cam-outfrq3s BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.mpasa480z32_mpasa480.FHS94.izumi_nag.cam-outfrq3s_usecase (Overall: NLFAIL) details:
+ FAIL ERC_D_Ln9_Vnuopc.mpasa480z32_mpasa480.FHS94.izumi_nag.cam-outfrq3s_usecase NLCOMP
+ ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.ne16pg3_ne16pg3_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.ne16pg3_ne16pg3_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.ne16pg3_ne16pg3_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-outfrq3s_ttrac (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-outfrq3s_ttrac NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-outfrq3s_ttrac BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.T5_T5_mg37.QPC4.izumi_nag.cam-outfrq3s_usecase (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.T5_T5_mg37.QPC4.izumi_nag.cam-outfrq3s_usecase NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.T5_T5_mg37.QPC4.izumi_nag.cam-outfrq3s_usecase BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERI_D_Ln18_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_eoyttrac (Overall: DIFF) details:
+ FAIL ERI_D_Ln18_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_eoyttrac NLCOMP
+ FAIL ERI_D_Ln18_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_eoyttrac BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERI_D_Ln18_Vnuopc.f19_f19_mg17.QPC6.izumi_nag.cam-ghgrmp_e8 (Overall: DIFF) details:
+ FAIL ERI_D_Ln18_Vnuopc.f19_f19_mg17.QPC6.izumi_nag.cam-ghgrmp_e8 NLCOMP
+ FAIL ERI_D_Ln18_Vnuopc.f19_f19_mg17.QPC6.izumi_nag.cam-ghgrmp_e8 BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERI_D_Ln18_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s_bwic (Overall: NLFAIL) details:
+ FAIL ERI_D_Ln18_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s_bwic NLCOMP
+ ERI_D_Ln18_Vnuopc.ne5pg3_ne5pg3_mg37.FADIAB.izumi_nag.cam-outfrq3s_bwic (Overall: NLFAIL) details:
+ FAIL ERI_D_Ln18_Vnuopc.ne5pg3_ne5pg3_mg37.FADIAB.izumi_nag.cam-outfrq3s_bwic NLCOMP
+ ERP_Ln9_Vmct.ne5pg3_ne5pg3_mg37.QPC6.izumi_nag.cam-outfrq9s_clubbmf (Overall: NLFAIL) details:
+ FAIL ERP_Ln9_Vmct.ne5pg3_ne5pg3_mg37.QPC6.izumi_nag.cam-outfrq9s_clubbmf NLCOMP
+ ERP_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC6.izumi_nag.cam-outfrq9s_clubbmf (Overall: DIFF) details:
+ FAIL ERP_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC6.izumi_nag.cam-outfrq9s_clubbmf NLCOMP
+ FAIL ERP_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC6.izumi_nag.cam-outfrq9s_clubbmf BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERS_Ln27_Vnuopc.ne5pg3_ne5pg3_mg37.FKESSLER.izumi_nag.cam-outfrq9s (Overall: NLFAIL) details:
+ FAIL ERS_Ln27_Vnuopc.ne5pg3_ne5pg3_mg37.FKESSLER.izumi_nag.cam-outfrq9s NLCOMP
+ ERS_Ln9_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq9s (Overall: NLFAIL) details:
+ FAIL ERS_Ln9_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq9s NLCOMP
+ PEM_D_Ln9_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details:
+ FAIL PEM_D_Ln9_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s NLCOMP
+ PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 (Overall: DIFF) details:
+ FAIL PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 NLCOMP
+ FAIL PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 (Overall: DIFF) details:
+ FAIL PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 NLCOMP
+ FAIL PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 (Overall: DIFF) details:
+ FAIL PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 NLCOMP
+ FAIL PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 (Overall: DIFF) details:
+ FAIL PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 NLCOMP
+ FAIL PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 (Overall: DIFF) details:
+ FAIL PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 NLCOMP
+ FAIL PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 (Overall: DIFF) details:
+ FAIL PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 NLCOMP
+ FAIL PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_D_Ld2_Vnuopc.f45_f45_mg37.PC5.izumi_nag.cam-outfrq24h_port (Overall: NLFAIL) details:
+ FAIL SMS_D_Ld2_Vnuopc.f45_f45_mg37.PC5.izumi_nag.cam-outfrq24h_port NLCOMP
+ SMS_D_Ln3_Vnuopc.ne5pg3_ne5pg3_mg37.QPX2000.izumi_nag.cam-outfrq3s (Overall: DIFF) details:
+ FAIL SMS_D_Ln3_Vnuopc.ne5pg3_ne5pg3_mg37.QPX2000.izumi_nag.cam-outfrq3s NLCOMP
+ FAIL SMS_D_Ln3_Vnuopc.ne5pg3_ne5pg3_mg37.QPX2000.izumi_nag.cam-outfrq3s BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_D_Ln6_Vnuopc.ne5_ne5_mg37.QPWmaC4.izumi_nag.cam-outfrq3s_physgrid_tem (Overall: DIFF) details:
+ FAIL SMS_D_Ln6_Vnuopc.ne5_ne5_mg37.QPWmaC4.izumi_nag.cam-outfrq3s_physgrid_tem NLCOMP
+ FAIL SMS_D_Ln6_Vnuopc.ne5_ne5_mg37.QPWmaC4.izumi_nag.cam-outfrq3s_physgrid_tem BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_D_Ln7_Vnuopc.T42_T42_mg17.QPSCAMC5.izumi_nag.cam-scmarm (Overall: DIFF) details:
+ FAIL SMS_D_Ln7_Vnuopc.T42_T42_mg17.QPSCAMC5.izumi_nag.cam-scmarm NLCOMP
+ FAIL SMS_D_Ln7_Vnuopc.T42_T42_mg17.QPSCAMC5.izumi_nag.cam-scmarm BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_D_Ln9_P1x1_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details:
+ FAIL SMS_D_Ln9_P1x1_Vnuopc.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s NLCOMP
+ SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-rad_diag_mam (Overall: DIFF) details:
+ FAIL SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-rad_diag_mam NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-rad_diag_mam BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_ba (Overall: DIFF) details:
+ FAIL SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_ba NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_ba BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_P48x1_D_Ln3_Vnuopc.f09_f09_mg17.QPC6HIST.izumi_nag.cam-outfrq3s_co2cycle_usecase (Overall: DIFF) details:
+ FAIL SMS_P48x1_D_Ln3_Vnuopc.f09_f09_mg17.QPC6HIST.izumi_nag.cam-outfrq3s_co2cycle_usecase NLCOMP
+ FAIL SMS_P48x1_D_Ln3_Vnuopc.f09_f09_mg17.QPC6HIST.izumi_nag.cam-outfrq3s_co2cycle_usecase BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SUB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s (Overall: DIFF) details:
+ FAIL SUB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s NLCOMP
+ FAIL SUB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_nag: FIELDLIST field lists differ (otherwise bit-for-bit)
+ TMC_D_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_eoyttrac (Overall: NLFAIL) details:
+ FAIL TMC_D_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_eoyttrac NLCOMP
+ TMC_D_Vnuopc.T5_T5_mg37.QPC5.izumi_nag.cam-ghgrmp_e8 (Overall: NLFAIL) details:
+ FAIL TMC_D_Vnuopc.T5_T5_mg37.QPC5.izumi_nag.cam-ghgrmp_e8 NLCOMP
+
+The DAE failure is pre-existing.
+The NLCOMP failures are due to adding the ndep_stream_nl group to atm_in.
+The BASELINE test failures are due to different field list in the cpl.hi files.
+
+izumi/gnu/aux_cam:
+
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.FADIAB.izumi_gnu.cam-terminator (Overall: NLFAIL) details:
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.FADIAB.izumi_gnu.cam-terminator NLCOMP
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC4.izumi_gnu.cam-outfrq3s_diags (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC4.izumi_gnu.cam-outfrq3s_diags NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC4.izumi_gnu.cam-outfrq3s_diags BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_gnu: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_gnu.cam-outfrq3s_unicon (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_gnu.cam-outfrq3s_unicon NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_gnu.cam-outfrq3s_unicon BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_gnu: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_gnu.cam-rad_diag (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_gnu.cam-rad_diag NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_gnu.cam-rad_diag BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_gnu: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPSPCAMM.izumi_gnu.cam-outfrq3s (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPSPCAMM.izumi_gnu.cam-outfrq3s NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPSPCAMM.izumi_gnu.cam-outfrq3s BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_gnu: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC4.izumi_gnu.cam-outfrq3s_nudging_ne5_L26 (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC4.izumi_gnu.cam-outfrq3s_nudging_ne5_L26 NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC4.izumi_gnu.cam-outfrq3s_nudging_ne5_L26 BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_gnu: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq3s_ba (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq3s_ba NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq3s_ba BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_gnu: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERC_D_Ln9_Vnuopc.ne5pg2_ne5pg2_mg37.FADIAB.izumi_gnu.cam-outfrq3s (Overall: NLFAIL) details:
+ FAIL ERC_D_Ln9_Vnuopc.ne5pg2_ne5pg2_mg37.FADIAB.izumi_gnu.cam-outfrq3s NLCOMP
+ ERC_D_Ln9_Vnuopc.ne5pg4_ne5pg4_mg37.FADIAB.izumi_gnu.cam-outfrq3s (Overall: NLFAIL) details:
+ FAIL ERC_D_Ln9_Vnuopc.ne5pg4_ne5pg4_mg37.FADIAB.izumi_gnu.cam-outfrq3s NLCOMP
+ ERC_D_Ln9_Vnuopc.T5_T5_mg37.QPC3.izumi_gnu.cam-outfrq3s_usecase (Overall: DIFF) details:
+ FAIL ERC_D_Ln9_Vnuopc.T5_T5_mg37.QPC3.izumi_gnu.cam-outfrq3s_usecase NLCOMP
+ FAIL ERC_D_Ln9_Vnuopc.T5_T5_mg37.QPC3.izumi_gnu.cam-outfrq3s_usecase BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_gnu: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERI_D_Ln18_Vnuopc.T5_T5_mg37.QPC4.izumi_gnu.cam-co2rmp (Overall: DIFF) details:
+ FAIL ERI_D_Ln18_Vnuopc.T5_T5_mg37.QPC4.izumi_gnu.cam-co2rmp NLCOMP
+ FAIL ERI_D_Ln18_Vnuopc.T5_T5_mg37.QPC4.izumi_gnu.cam-co2rmp BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_gnu: FIELDLIST field lists differ (otherwise bit-for-bit)
+ ERP_Ln9_Vnuopc.ne5_ne5_mg37.FHS94.izumi_gnu.cam-outfrq9s (Overall: NLFAIL) details:
+ FAIL ERP_Ln9_Vnuopc.ne5_ne5_mg37.FHS94.izumi_gnu.cam-outfrq9s NLCOMP
+ ERP_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq9s (Overall: DIFF) details:
+ FAIL ERP_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq9s NLCOMP
+ FAIL ERP_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq9s BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_gnu: FIELDLIST field lists differ (otherwise bit-for-bit)
+ PEM_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.FADIAB.izumi_gnu.cam-outfrq3s (Overall: NLFAIL) details:
+ FAIL PEM_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.FADIAB.izumi_gnu.cam-outfrq3s NLCOMP
+ PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal0 (Overall: DIFF) details:
+ FAIL PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal0 NLCOMP
+ FAIL PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal0 BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_gnu: FIELDLIST field lists differ (otherwise bit-for-bit)
+ PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal1 (Overall: DIFF) details:
+ FAIL PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal1 NLCOMP
+ FAIL PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal1 BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_gnu: FIELDLIST field lists differ (otherwise bit-for-bit)
+ PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal3 (Overall: DIFF) details:
+ FAIL PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal3 NLCOMP
+ FAIL PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal3 BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_gnu: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SCT_D_Ln7_Vnuopc.T42_T42_mg17.QPC4.izumi_gnu.cam-scm_prep (Overall: DIFF) details:
+ FAIL SCT_D_Ln7_Vnuopc.T42_T42_mg17.QPC4.izumi_gnu.cam-scm_prep NLCOMP
+ FAIL SCT_D_Ln7_Vnuopc.T42_T42_mg17.QPC4.izumi_gnu.cam-scm_prep BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_gnu: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SCT_D_Ln7_Vnuopc.T42_T42_mg17.QPC6.izumi_gnu.cam-scm_prep_c6 (Overall: DIFF) details:
+ FAIL SCT_D_Ln7_Vnuopc.T42_T42_mg17.QPC6.izumi_gnu.cam-scm_prep_c6 NLCOMP
+ FAIL SCT_D_Ln7_Vnuopc.T42_T42_mg17.QPC6.izumi_gnu.cam-scm_prep_c6 BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_gnu: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_D_Ln3_Vnuopc.f10_f10_mg37.QPMOZ.izumi_gnu.cam-outfrq3s_chemproc (Overall: DIFF) details:
+ FAIL SMS_D_Ln3_Vnuopc.f10_f10_mg37.QPMOZ.izumi_gnu.cam-outfrq3s_chemproc NLCOMP
+ FAIL SMS_D_Ln3_Vnuopc.f10_f10_mg37.QPMOZ.izumi_gnu.cam-outfrq3s_chemproc BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_gnu: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPWmaC4.izumi_gnu.cam-outfrq9s_apmee (Overall: DIFF) details:
+ FAIL SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPWmaC4.izumi_gnu.cam-outfrq9s_apmee NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPWmaC4.izumi_gnu.cam-outfrq9s_apmee BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_gnu: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-outfrq3s_ttrac (Overall: DIFF) details:
+ FAIL SMS_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-outfrq3s_ttrac NLCOMP
+ FAIL SMS_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-outfrq3s_ttrac BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_gnu: FIELDLIST field lists differ (otherwise bit-for-bit)
+ SMS_P48x1_D_Ln9_Vnuopc.f19_f19_mg17.FW4madSD.izumi_gnu.cam-outfrq9s (Overall: DIFF) details:
+ FAIL SMS_P48x1_D_Ln9_Vnuopc.f19_f19_mg17.FW4madSD.izumi_gnu.cam-outfrq9s NLCOMP
+ FAIL SMS_P48x1_D_Ln9_Vnuopc.f19_f19_mg17.FW4madSD.izumi_gnu.cam-outfrq9s BASELINE /fs/cgd/csm/models/atm/cam/pretag_bl/cam6_3_097_gnu: FIELDLIST field lists differ (otherwise bit-for-bit)
+
+The NLCOMP failures are due to adding the ndep_stream_nl group to atm_in.
+The BASELINE test failures are due to different field list in the cpl.hi files.
+
+CAM tag used for the baseline comparison tests if different than previous
+tag:
+
+Summarize any changes to answers: none.
+
+===============================================================
+===============================================================
+
+Tag name: cam6_3_097
+Originator(s): andrewgettelman, tilmes, fvitt
+Date: 13 Mar 2023
+One-line Summary: Heterogeneous freezing science updates and bug fixes
+Github PR URL: https://github.com/ESCOMP/CAM/pull/755
+
+Purpose of changes (include the issue number and title text for each relevant GitHub issue):
+
+ The following science updates and bug fixes to heterogeneous freezing parameterization
+ - new namelist parameters for scaling of dust and black carbon contributions
+ to heterogeneous freezing rates
+ - use physical approach to calculate species fractions
+ - use consistent concentrations of cloud-borne and ambient aerosol
+ - include sulfate in coarse dust fraction calculation
+ Update PUMAS external
+
+Describe any changes made to build system: N/A
+
+Describe any changes made to the namelist:
+
+ New namelist parameters:
+
+ hetfrz_bc_scalfac
+ Heterogeneous freezing scaling factor for black carbon aerosols.
+ Default: 0.01
+
+ hetfrz_dust_scalfac
+ Heterogeneous freezing scaling factor for dust aerosols.
+ Default: 0.05
+
+List any changes to the defaults for the boundary datasets: N/A
+
+Describe any substantial timing or memory changes: N/A
+
+Code reviewed by: andrewgettelman, cacraigucar, jtruesdal, adamrher, nusbaume
+
+List all files eliminated: N/A
+
+List all files added and what they do: N/A
+
+List all existing files that have been modified, and describe the changes:
+M Externals_CAM.cfg
+ - pumas update
+
+M bld/build-namelist
+M bld/namelist_files/namelist_defaults_cam.xml
+M bld/namelist_files/namelist_definition.xml
+ - new hetfrz scaling factors namelist parameters
+
+M src/physics/cam/hetfrz_classnuc_cam.F90
+ - add scaling factor for dust
+
+M src/physics/cam/hetfrz_classnuc.F90
+ - new hetfrz scaling factors namelist parameters for dust and BC
+ - remove separate interface for collection of cloud-borne aerosols
+ so that cloud-borne and ambient aerosol concentrations are consistent
+ - set num_to_mass_in to false (use physical approach to calc species fractions)
+ and calc primary carbon fraction consistently
+ - include SO4 in dst3 fraction calculation
+
+M src/physics/cam/microp_aero.F90
+ - remove separate interface for collection of cloud-borne aerosols
+ so that cloud-borne and ambient aerosol concentrations are consistent
+
+If there were any failures reported from running test_driver.sh on any test
+platform, and checkin with these failures has been OK'd by the gatekeeper,
+then copy the lines from the td.*.status files for the failed tests to the
+appropriate machine below. All failed tests must be justified.
+
+cheyenne/intel/aux_cam:
+ ERC_D_Ln9_P144x1_Vnuopc.ne16pg3_ne16pg3_mg17.QPC6HIST.cheyenne_intel.cam-outfrq3s_ttrac_usecase (Overall: DIFF) details:
+ ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq3s_cosp (Overall: DIFF) details:
+ ERP_D_Ln9_Vmct.f09_f09_mg17.QSC6.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_D_Ln9_Vmct.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_D_Ln9_Vnuopc.f09_f09_mg17.QSC6.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_D_Ln9_Vnuopc.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_D_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.F2000dev.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ld3_Vnuopc.f09_f09_mg17.FWHIST.cheyenne_intel.cam-reduced_hist1d (Overall: DIFF) details:
+ ERP_Ln9_P24x3_Vnuopc.f45_f45_mg37.QPWmaC6.cheyenne_intel.cam-outfrq9s_mee_fluxes (Overall: DIFF) details:
+ ERP_Ln9_Vmct.f09_f09_mg17.2000_CAM60_CLM50%SP_CICE5%PRES_DOCN%DOM_MOSART_SGLC_SWAV.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.C96_C96_mg17.F2000climo.cheyenne_intel.cam-outfrq9s_mg3 (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F1850.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F2000climo.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F2000dev.cheyenne_intel.cam-outfrq9s_mg3 (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F2010climo.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.FHIST_BDRD.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f19_f19_mg17.FWsc1850.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.ne30_ne30_mg17.FCnudged.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.FW2000climo.cheyenne_intel.cam-outfrq9s_wcm_ne30 (Overall: DIFF) details:
+ ERS_Ld3_Vnuopc.f10_f10_mg37.F1850.cheyenne_intel.cam-outfrq1d_14dec_L32wsc (Overall: DIFF) details:
+ ERS_Ln9_P288x1_Vnuopc.mpasa120_mpasa120.F2000climo.cheyenne_intel.cam-outfrq9s_mpasa120 (Overall: DIFF) details:
+ ERS_Ln9_P36x1_Vnuopc.mpasa480_mpasa480.F2000climo.cheyenne_intel.cam-outfrq9s_mpasa480 (Overall: DIFF) details:
+ ERS_Ln9_Vnuopc.f09_f09_mg17.FX2000.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERS_Ln9_Vnuopc.f19_f19_mg17.FXSD.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vmct.T42_T42.2000_CAM60%SCAM_CLM50%SP_CICE5%PRES_DOCN%DOM_SROF_SGLC_SWAV.cheyenne_intel.cam-outfrq9s (Overall: NLFAIL) details:
+ SMS_D_Ln9_Vnuopc.f09_f09_mg17.FCts2nudged.cheyenne_intel.cam-outfrq9s_leapday (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f09_f09_mg17.FCvbsxHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f09_f09_mg17.FSD.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.FWma2000climo.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.FWma2000climo.cheyenne_intel.cam-outfrq9s_waccm_ma_mam4 (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.FXHIST.cheyenne_intel.cam-outfrq9s_amie (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.QPC2000climo.cheyenne_intel.cam-outfrq3s_usecase (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.ne16_ne16_mg17.FX2000.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc_P720x1.ne0ARCTICne30x4_ne0ARCTICne30x4_mt12.FHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc_P720x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc_P720x1.ne30pg3_ne30pg3_mg17.FCLTHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.T42_T42.FSCAM.cheyenne_intel.cam-outfrq9s (Overall: NLFAIL) details:
+ SMS_Ld1_Vnuopc.f09_f09_mg17.FW2000climo.cheyenne_intel.cam-outfrq1d (Overall: DIFF) details:
+ SMS_Ld1_Vnuopc.f19_f19.F2000dev.cheyenne_intel.cam-outfrq1d (Overall: DIFF) details:
+ SMS_Ld1_Vnuopc.ne30pg3_ne30pg3_mg17.FC2010climo.cheyenne_intel.cam-outfrq1d (Overall: DIFF) details:
+ SMS_Ld5_Vnuopc.f09_f09_mg17.PC6.cheyenne_intel.cam-cam6_port_f09 (Overall: NLFAIL) details:
+ SMS_Lm13_Vnuopc.f10_f10_mg37.F2000climo.cheyenne_intel.cam-outfrq1m (Overall: DIFF) details:
+ SMS_Ln9_Vnuopc.f09_f09_mg17.F2010climo.cheyenne_intel.cam-nudging (Overall: DIFF) details:
+ SMS_Ln9_Vnuopc.f09_f09_mg17.FW1850.cheyenne_intel.cam-reduced_hist3s (Overall: DIFF) details:
+ SMS_Ln9_Vnuopc.f19_f19.F2000climo.cheyenne_intel.cam-silhs (Overall: DIFF) details:
+ - expect different answers in cam6 configurations
+
+izumi/nag/aux_cam:
+ DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) details:
+ - pre-existing failure
+
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_am (Overall: DIFF) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_convmic (Overall: DIFF) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_cospsathist (Overall: DIFF) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s (Overall: DIFF) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPWmaC6.izumi_nag.cam-outfrq3s (Overall: DIFF) details:
+ ERI_D_Ln18_Vnuopc.f19_f19_mg17.QPC6.izumi_nag.cam-ghgrmp_e8 (Overall: DIFF) details:
+ ERP_Ln9_Vmct.ne5pg3_ne5pg3_mg37.QPC6.izumi_nag.cam-outfrq9s_clubbmf (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC6.izumi_nag.cam-outfrq9s_clubbmf (Overall: DIFF) details:
+ SMS_P48x1_D_Ln3_Vnuopc.f09_f09_mg17.QPC6HIST.izumi_nag.cam-outfrq3s_co2cycle_usecase (Overall: DIFF) details:
+ - expect different answers in cam6 configurations
+
+izumi/gnu/aux_cam:
+ SCT_D_Ln7_Vnuopc.T42_T42_mg17.QPC6.izumi_gnu.cam-scm_prep_c6 (Overall: DIFF) details:
+ - expect different answers in cam6 configurations
+
+Summarize any changes to answers: larger than roundoff
+
+===============================================================
+===============================================================
+
+Tag name: cam6_3_096
+Originator(s): tilmes, fvitt
+Date: 8 Mar 2023
+One-line Summary: Aqueous chemistry bug fix
+Github PR URL: https://github.com/ESCOMP/CAM/pull/760
+
+Purpose of changes (include the issue number and title text for each relevant GitHub issue):
+
+ Exclude cloud ice from the water constituent input into the aqueous chemistry so that
+ only cloud liquid is used.
+ (See issue: Aq.chemistry update #758)
+
+Describe any changes made to build system: N/A
+
+Describe any changes made to the namelist: N/A
+
+List any changes to the defaults for the boundary datasets: N/A
+
+Describe any substantial timing or memory changes: N/A
+
+Code reviewed by: nusbaume, cacraig, tilmes
+
+List all files eliminated: N/A
+
+List all files added and what they do: N/A
+
+List all existing files that have been modified, and describe the changes:
+
+M src/chemistry/mozart/chemistry.F90
+ - cloud water input is only the cloud liquid constituent
+
+If there were any failures reported from running test_driver.sh on any test
+platform, and checkin with these failures has been OK'd by the gatekeeper,
+then copy the lines from the td.*.status files for the failed tests to the
+appropriate machine below. All failed tests must be justified.
+
+cheyenne/intel/aux_cam:
+ ERC_D_Ln9_P144x1_Vnuopc.ne16pg3_ne16pg3_mg17.QPC6HIST.cheyenne_intel.cam-outfrq3s_ttrac_usecase (Overall: DIFF) details:
+ ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq3s_cosp (Overall: DIFF) details:
+ ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPMOZ.cheyenne_intel.cam-outfrq3s (Overall: DIFF) details:
+ ERC_D_Ln9_Vnuopc.f19_f19_mg17.QPX2000.cheyenne_intel.cam-outfrq3s (Overall: DIFF) details:
+ ERC_D_Ln9_Vnuopc.ne16_ne16_mg17.QPC5HIST.cheyenne_intel.cam-outfrq3s_usecase (Overall: DIFF) details:
+ ERP_D_Ln9_Vmct.f09_f09_mg17.QSC6.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_D_Ln9_Vmct.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_D_Ln9_Vnuopc.f09_f09_mg17.QSC6.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_D_Ln9_Vnuopc.f19_f19_mg17.QPC6.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_D_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.F2000dev.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ld3_Vnuopc.f09_f09_mg17.FWHIST.cheyenne_intel.cam-reduced_hist1d (Overall: DIFF) details:
+ ERP_Lh12_Vnuopc.f19_f19_mg17.FW4madSD.cheyenne_intel.cam-outfrq3h (Overall: DIFF) details:
+ ERP_Ln9_P24x3_Vnuopc.f45_f45_mg37.QPWmaC6.cheyenne_intel.cam-outfrq9s_mee_fluxes (Overall: DIFF) details:
+ ERP_Ln9_Vmct.f09_f09_mg17.2000_CAM60_CLM50%SP_CICE5%PRES_DOCN%DOM_MOSART_SGLC_SWAV.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.C96_C96_mg17.F2000climo.cheyenne_intel.cam-outfrq9s_mg3 (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F1850.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F2000climo.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F2000dev.cheyenne_intel.cam-outfrq9s_mg3 (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.F2010climo.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f09_f09_mg17.FHIST_BDRD.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.f19_f19_mg17.FWsc1850.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.ne30_ne30_mg17.FCnudged.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.ne30pg3_ne30pg3_mg17.FW2000climo.cheyenne_intel.cam-outfrq9s_wcm_ne30 (Overall: DIFF) details:
+ ERS_Ld3_Vnuopc.f10_f10_mg37.F1850.cheyenne_intel.cam-outfrq1d_14dec_L32wsc (Overall: DIFF) details:
+ ERS_Ln9_P288x1_Vnuopc.mpasa120_mpasa120.F2000climo.cheyenne_intel.cam-outfrq9s_mpasa120 (Overall: DIFF) details:
+ ERS_Ln9_P36x1_Vnuopc.mpasa480_mpasa480.F2000climo.cheyenne_intel.cam-outfrq9s_mpasa480 (Overall: DIFF) details:
+ ERS_Ln9_Vnuopc.f09_f09_mg17.FX2000.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ ERS_Ln9_Vnuopc.f19_f19_mg17.FXSD.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SCT_D_Ln7_Vnuopc.T42_T42_mg17.QPC5.cheyenne_intel.cam-scm_prep (Overall: DIFF) details:
+ SMS_D_Ld2_Vnuopc.f19_f19_mg17.QPC5HIST.cheyenne_intel.cam-volc_usecase (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f09_f09_mg17.FCts2nudged.cheyenne_intel.cam-outfrq9s_leapday (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f09_f09_mg17.FCvbsxHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f09_f09_mg17.FSD.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.FWma2000climo.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.FWma2000climo.cheyenne_intel.cam-outfrq9s_waccm_ma_mam4 (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.FXHIST.cheyenne_intel.cam-outfrq9s_amie (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.QPC2000climo.cheyenne_intel.cam-outfrq3s_usecase (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f19_f19_mg17.QPC5M7.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.ne16_ne16_mg17.FX2000.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.ne16_ne16_mg17.QPX2000.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc_P720x1.ne0ARCTICne30x4_ne0ARCTICne30x4_mt12.FHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc_P720x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc_P720x1.ne30pg3_ne30pg3_mg17.FCLTHIST.cheyenne_intel.cam-outfrq9s (Overall: DIFF) details:
+ SMS_Ld1_Vnuopc.f09_f09_mg17.FW2000climo.cheyenne_intel.cam-outfrq1d (Overall: DIFF) details:
+ SMS_Ld1_Vnuopc.f19_f19.F2000dev.cheyenne_intel.cam-outfrq1d (Overall: DIFF) details:
+ SMS_Ld1_Vnuopc.ne30pg3_ne30pg3_mg17.FC2010climo.cheyenne_intel.cam-outfrq1d (Overall: DIFF) details:
+ SMS_Lm13_Vnuopc.f10_f10_mg37.F2000climo.cheyenne_intel.cam-outfrq1m (Overall: DIFF) details:
+ SMS_Ln9_Vnuopc.f09_f09_mg17.F2010climo.cheyenne_intel.cam-nudging (Overall: DIFF) details:
+ SMS_Ln9_Vnuopc.f09_f09_mg17.FW1850.cheyenne_intel.cam-reduced_hist3s (Overall: DIFF) details:
+ SMS_Ln9_Vnuopc.f19_f19.F2000climo.cheyenne_intel.cam-silhs (Overall: DIFF) details:
+ - configurations with aqueous chemistry are expected to change answers
+
+izumi/nag/aux_cam:
+ DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) details:
+ - pre-existing failure
+
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-carma_sea_salt (Overall: DIFF) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_cosp (Overall: DIFF) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_subcol (Overall: DIFF) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_am (Overall: DIFF) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_convmic (Overall: DIFF) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_cospsathist (Overall: DIFF) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s (Overall: DIFF) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPWmaC6.izumi_nag.cam-outfrq3s (Overall: DIFF) details:
+ ERC_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-outfrq3s_ttrac (Overall: DIFF) details:
+ ERI_D_Ln18_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_eoyttrac (Overall: DIFF) details:
+ ERI_D_Ln18_Vnuopc.f19_f19_mg17.QPC6.izumi_nag.cam-ghgrmp_e8 (Overall: DIFF) details:
+ ERP_Ln9_Vmct.ne5pg3_ne5pg3_mg37.QPC6.izumi_nag.cam-outfrq9s_clubbmf (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC6.izumi_nag.cam-outfrq9s_clubbmf (Overall: DIFF) details:
+ PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 (Overall: DIFF) details:
+ PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 (Overall: DIFF) details:
+ PLB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 (Overall: DIFF) details:
+ PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 (Overall: DIFF) details:
+ PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 (Overall: DIFF) details:
+ PLB_D_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 (Overall: DIFF) details:
+ SMS_D_Ln3_Vnuopc.ne5pg3_ne5pg3_mg37.QPX2000.izumi_nag.cam-outfrq3s (Overall: DIFF) details:
+ SMS_D_Ln6_Vnuopc.ne5_ne5_mg37.QPWmaC4.izumi_nag.cam-outfrq3s_physgrid_tem (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-rad_diag_mam (Overall: DIFF) details:
+ SMS_P48x1_D_Ln3_Vnuopc.f09_f09_mg17.QPC6HIST.izumi_nag.cam-outfrq3s_co2cycle_usecase (Overall: DIFF) details:
+ SUB_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s (Overall: DIFF) details:
+ TMC_D_Vnuopc.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_eoyttrac (Overall: DIFF) details:
+ TMC_D_Vnuopc.T5_T5_mg37.QPC5.izumi_nag.cam-ghgrmp_e8 (Overall: DIFF) details:
+ - configurations with aqueous chemistry are expected to change answers
+
+izumi/gnu/aux_cam:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPC5.izumi_gnu.cam-outfrq3s_unicon (Overall: DIFF) details:
+ ERC_D_Ln9_Vnuopc.f10_f10_mg37.QPSPCAMM.izumi_gnu.cam-outfrq3s (Overall: DIFF) details:
+ ERP_Ln9_Vnuopc.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq9s (Overall: DIFF) details:
+ PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal0 (Overall: DIFF) details:
+ PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal1 (Overall: DIFF) details:
+ PLB_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal3 (Overall: DIFF) details:
+ SCT_D_Ln7_Vnuopc.T42_T42_mg17.QPC6.izumi_gnu.cam-scm_prep_c6 (Overall: DIFF) details:
+ SMS_D_Ln3_Vnuopc.f10_f10_mg37.QPMOZ.izumi_gnu.cam-outfrq3s_chemproc (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.f10_f10_mg37.QPWmaC4.izumi_gnu.cam-outfrq9s_apmee (Overall: DIFF) details:
+ SMS_D_Ln9_Vnuopc.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-outfrq3s_ttrac (Overall: DIFF) details:
+ SMS_P48x1_D_Ln9_Vnuopc.f19_f19_mg17.FW4madSD.izumi_gnu.cam-outfrq9s (Overall: DIFF) details:
+ - configurations with aqueous chemistry are expected to change answers
+
+Summarize any changes to answers: larger than roundoff
+
+===============================================================
+===============================================================
+
Tag name: cam6_3_095
Originator(s): fvitt
Date: 15 Feb 2023
diff --git a/src/chemistry/mozart/chemistry.F90 b/src/chemistry/mozart/chemistry.F90
index 5aba3224c6..2e870f4922 100644
--- a/src/chemistry/mozart/chemistry.F90
+++ b/src/chemistry/mozart/chemistry.F90
@@ -59,10 +59,6 @@ module chemistry
character(len=shr_kind_cl) :: bndtvg = ' ' ! pathname for greenhouse gas loss rate
character(len=shr_kind_cl) :: h2orates = ' ' ! pathname for greenhouse gas (lyman-alpha H2O loss)
- ! lightning
-
- real(r8) :: lght_no_prd_factor = 1._r8
-
! photolysis
character(len=shr_kind_cl) :: rsf_file = 'rsf_file'
@@ -110,7 +106,7 @@ module chemistry
character(len=fieldname_len) :: srcnam(gas_pcnst) ! names of source/sink tendencies
- integer :: ixcldliq, ixcldice ! indicies of liquid and ice cloud water
+ integer :: ixcldliq ! index of liquid cloud water
integer :: ndx_cld
integer :: ndx_cmfdqr
integer :: ndx_nevapr
@@ -377,7 +373,6 @@ subroutine chem_readnl(nlfile)
xs_coef_file, xs_short_file, &
exo_coldens_file, &
xs_long_file, rsf_file, photo_max_zen, &
- lght_no_prd_factor, &
depvel_lnd_file, drydep_srf_file, &
srf_emis_type, srf_emis_cycle_yr, srf_emis_fixed_ymd, srf_emis_fixed_tod, srf_emis_specifier, &
fstrat_file, fstrat_list, &
@@ -454,10 +449,6 @@ subroutine chem_readnl(nlfile)
call mpibcast (bndtvg, len(bndtvg), mpichar, 0, mpicom)
call mpibcast (h2orates, len(h2orates), mpichar, 0, mpicom)
- ! lightning
-
- call mpibcast (lght_no_prd_factor,1, mpir8, 0, mpicom)
-
! photolysis
call mpibcast (rsf_file, len(rsf_file), mpichar, 0, mpicom)
@@ -687,7 +678,6 @@ subroutine chem_init(phys_state, pbuf2d)
! Get liq and ice cloud water indicies
!-----------------------------------------------------------------------
call cnst_get_ind( 'CLDLIQ', ixcldliq )
- call cnst_get_ind( 'CLDICE', ixcldice )
call cnst_get_ind( 'NUMLIQ', ixndrop, abort=.false. )
!-----------------------------------------------------------------------
@@ -767,7 +757,6 @@ subroutine chem_init(phys_state, pbuf2d)
, ext_frc_fixed_ymd &
, ext_frc_fixed_tod &
, exo_coldens_file &
- , lght_no_prd_factor &
, pbuf2d &
)
@@ -979,6 +968,10 @@ subroutine chem_init_cnst( name, latvals, lonvals, mask, q)
where(mask)
q(:,ilev) = rmwf12 * chem_surfvals_get('F12VMR')
end where
+ case ('CO2')
+ where(mask)
+ q(:,ilev) = chem_surfvals_get('CO2MMR')
+ end where
end select
end do
end if
@@ -1210,16 +1203,15 @@ subroutine chem_timestep_tend( state, ptend, cam_in, cam_out, dt, pbuf, fh2o)
!-----------------------------------------------------------------------
call t_startf( 'chemdr' )
do k = 1,pver
- cldw(:ncol,k) = state%q(:ncol,k,ixcldliq) + state%q(:ncol,k,ixcldice)
+ cldw(:ncol,k) = state%q(:ncol,k,ixcldliq)
if (ixndrop>0) &
ncldwtr(:ncol,k) = state%q(:ncol,k,ixndrop)
end do
call gas_phase_chemdr(lchnk, ncol, imozart, state%q, &
state%phis, state%zm, state%zi, calday, &
- state%t, state%pmid, state%pdel, state%pint, &
- cldw, tropLev, tropLevChem, ncldwtr, state%u, state%v, &
- chem_dt, state%ps, &
+ state%t, state%pmid, state%pdel, state%pint, state%rpdel, state%rpdeldry, &
+ cldw, tropLev, tropLevChem, ncldwtr, state%u, state%v, chem_dt, state%ps, &
fsds, cam_in%ts, cam_in%asdir, cam_in%ocnfrac, cam_in%icefrac, &
cam_out%precc, cam_out%precl, cam_in%snowhland, ghg_chem, state%latmapback, &
drydepflx, wetdepflx, cam_in%cflx, cam_in%fireflx, cam_in%fireztop, &
diff --git a/src/chemistry/mozart/mo_chemini.F90 b/src/chemistry/mozart/mo_chemini.F90
index d66458e8fc..9c31b2ba61 100644
--- a/src/chemistry/mozart/mo_chemini.F90
+++ b/src/chemistry/mozart/mo_chemini.F90
@@ -36,7 +36,6 @@ subroutine chemini &
, ext_frc_fixed_ymd &
, ext_frc_fixed_tod &
, exo_coldens_file &
- , lght_no_prd_factor &
, pbuf2d &
)
@@ -48,7 +47,6 @@ subroutine chemini &
use mo_srf_emissions, only : srf_emissions_inti
use mo_sulf, only : sulf_inti
use mo_photo, only : photo_inti
- use mo_lightning, only : lightning_inti
use mo_drydep, only : drydep_inti
use mo_imp_sol, only : imp_slv_inti
use mo_exp_sol, only : exp_sol_inti
@@ -94,7 +92,6 @@ subroutine chemini &
character(len=*), dimension(:), intent(in) :: srf_emis_specifier
character(len=*), dimension(:), intent(in) :: ext_frc_specifier
character(len=*), intent(in) :: exo_coldens_file
- real(r8), intent(in) :: lght_no_prd_factor
character(len=*), intent(in) :: ext_frc_type
integer, intent(in) :: ext_frc_cycle_yr
integer, intent(in) :: ext_frc_fixed_ymd
@@ -161,12 +158,6 @@ subroutine chemini &
call sad_inti(pbuf2d)
if (masterproc) write(iulog,*) 'chemini: after sad_inti on node ',iam
- !-----------------------------------------------------------------------
- ! ... initialize the lightning module
- !-----------------------------------------------------------------------
- call lightning_inti(lght_no_prd_factor)
- if (masterproc) write(iulog,*) 'chemini: after lightning_inti on node ',iam
-
!-----------------------------------------------------------------------
! ... initialize the dry deposition module
!-----------------------------------------------------------------------
diff --git a/src/chemistry/mozart/mo_gas_phase_chemdr.F90 b/src/chemistry/mozart/mo_gas_phase_chemdr.F90
index 323d9bbdaf..9e4e51df1f 100644
--- a/src/chemistry/mozart/mo_gas_phase_chemdr.F90
+++ b/src/chemistry/mozart/mo_gas_phase_chemdr.F90
@@ -232,7 +232,7 @@ end subroutine gas_phase_chemdr_inti
!-----------------------------------------------------------------------
subroutine gas_phase_chemdr(lchnk, ncol, imozart, q, &
phis, zm, zi, calday, &
- tfld, pmid, pdel, pint, &
+ tfld, pmid, pdel, pint, rpdel, rpdeldry, &
cldw, troplev, troplevchem, &
ncldwtr, ufld, vfld, &
delt, ps, &
@@ -246,8 +246,9 @@ subroutine gas_phase_chemdr(lchnk, ncol, imozart, q, &
! ebi, hov, fully implicit, and/or rodas algorithms.
!-----------------------------------------------------------------------
+ use phys_control, only : cam_physpkg_is
use chem_mods, only : nabscol, nfs, indexm, clscnt4
- use physconst, only : rga
+ use physconst, only : rga, gravit
use mo_photo, only : set_ub_col, setcol, table_photo
use mo_exp_sol, only : exp_sol
use mo_imp_sol, only : imp_sol
@@ -268,7 +269,7 @@ subroutine gas_phase_chemdr(lchnk, ncol, imozart, q, &
use mo_mean_mass, only : set_mean_mass
use cam_history, only : outfld
use wv_saturation, only : qsat
- use constituents, only : cnst_mw
+ use constituents, only : cnst_mw, cnst_type
use mo_ghg_chem, only : ghg_chem_set_rates, ghg_chem_set_flbc
use mo_sad, only : sad_strat_calc
use charge_neutrality, only : charge_balance
@@ -306,6 +307,8 @@ subroutine gas_phase_chemdr(lchnk, ncol, imozart, q, &
real(r8),target,intent(in) :: tfld(pcols,pver) ! midpoint temperature (K)
real(r8), intent(in) :: pmid(pcols,pver) ! midpoint pressures (Pa)
real(r8), intent(in) :: pdel(pcols,pver) ! pressure delta about midpoints (Pa)
+ real(r8), intent(in) :: rpdel(pcols,pver) ! reciprocal pressure delta about midpoints (Pa)
+ real(r8), intent(in) :: rpdeldry(pcols,pver) ! reciprocal dry pressure delta about midpoints (Pa)
real(r8), intent(in) :: ufld(pcols,pver) ! zonal velocity (m/s)
real(r8), intent(in) :: vfld(pcols,pver) ! meridional velocity (m/s)
real(r8), intent(in) :: cldw(pcols,pver) ! cloud water (kg/kg)
@@ -1022,7 +1025,17 @@ subroutine gas_phase_chemdr(lchnk, ncol, imozart, q, &
do m = 1,pcnst
n = map2chm( m )
if ( n > 0 ) then
- cflx(:ncol,m) = cflx(:ncol,m) - sflx(:ncol,n)
+ if (cam_physpkg_is("cam_dev")) then
+ ! apply to qtend array
+ if (cnst_type(m).eq.'dry') then
+ qtend(:ncol,pver,m) = qtend(:ncol,pver,m) - sflx(:ncol,n)*rpdeldry(:ncol,pver)*gravit
+ else
+ qtend(:ncol,pver,m) = qtend(:ncol,pver,m) - sflx(:ncol,n)*rpdel(:ncol,pver)*gravit
+ end if
+ else
+ ! apply to emissions array
+ cflx(:ncol,m) = cflx(:ncol,m) - sflx(:ncol,n)
+ end if
drydepflx(:ncol,m) = sflx(:ncol,n)
wetdepflx_diag(:ncol,n) = wetdepflx(:ncol,m)
endif
diff --git a/src/chemistry/mozart/mo_lightning.F90 b/src/chemistry/mozart/mo_lightning.F90
index 7f5860d173..4ef18fbaf6 100644
--- a/src/chemistry/mozart/mo_lightning.F90
+++ b/src/chemistry/mozart/mo_lightning.F90
@@ -10,140 +10,205 @@ module mo_lightning
use cam_logfile, only : iulog
use spmd_utils, only : masterproc, mpicom
+ use physics_buffer, only : pbuf_get_index, physics_buffer_desc, pbuf_get_field, pbuf_get_chunk
+ use physics_buffer, only : pbuf_add_field, pbuf_set_field, dtype_r8
+
implicit none
private
- public :: lightning_inti
+
+ public :: lightning_readnl
+ public :: lightning_register
+ public :: lightning_init
public :: lightning_no_prod
public :: prod_no
- save
+ real(r8),protected, allocatable :: prod_no(:,:,:)
real(r8) :: factor = 0.1_r8 ! user-controlled scaling factor to achieve arbitrary no prod.
- real(r8) :: geo_factor ! grid cell area factor
- real(r8) :: vdist(16,3) ! vertical distribution of lightning
- real(r8), allocatable :: prod_no(:,:,:)
- real(r8), allocatable :: glob_prod_no_col(:,:)
- real(r8), allocatable :: flash_freq(:,:)
- integer :: no_ndx,xno_ndx
- logical :: has_no_lightning_prod = .false.
+ real(r8) :: geo_factor = -huge(1._r8) ! grid cell area factor
+ real(r8), allocatable :: vdist(:,:) ! vertical distribution of lightning
+
+ logical :: calc_nox_prod = .false.
+ logical :: calc_lightning = .false.
+
+ integer :: flsh_frq_ndx = -1
+ integer :: cldtop_ndx = -1, cldbot_ndx = -1
+
+ ! namelist parameter
+ real(r8) :: lght_no_prd_factor = -huge(1._r8)
contains
- subroutine lightning_inti( lght_no_prd_factor )
+ !-------------------------------------------------------------------------
+ ! Read namelist options
+ !-------------------------------------------------------------------------
+ subroutine lightning_readnl(nlfile)
+ use namelist_utils, only : find_group_name
+ use spmd_utils, only : mpicom, masterprocid, mpi_real8, mpi_success
+
+ character(len=*), intent(in) :: nlfile ! filepath for file containing namelist input
+
+ integer :: unitn, ierr
+ character(len=*), parameter :: subname = 'lightning_readnl'
+
+ ! ===================
+ ! Namelist definition
+ ! ===================
+ namelist /lightning_nl/ lght_no_prd_factor
+
+ ! =============
+ ! Read namelist
+ ! =============
+ if (masterproc) then
+ open( newunit=unitn, file=trim(nlfile), status='old' )
+ call find_group_name(unitn, 'lightning_nl', status=ierr)
+ if (ierr == 0) then
+ read(unitn, lightning_nl, iostat=ierr)
+ if (ierr /= 0) then
+ call endrun(subname // ':: ERROR reading namelist')
+ end if
+ end if
+ close(unitn)
+ end if
+
+ ! ============================
+ ! Broadcast namelist variables
+ ! ============================
+ call mpi_bcast(lght_no_prd_factor, 1, mpi_real8, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) then
+ call endrun(subname//': MPI_BCAST ERROR: lght_no_prd_factor')
+ end if
+
+ if (masterproc) then
+ write(iulog,*) subname,' lght_no_prd_factor: ',lght_no_prd_factor
+ end if
+
+ if( lght_no_prd_factor /= 1._r8 ) then
+ factor = factor*lght_no_prd_factor
+ end if
+
+ end subroutine lightning_readnl
+
+ !-------------------------------------------------------------------------
+ ! register phys buffer field for cloud to ground lightning flash frequency
+ ! to pass to the mediator for land model
+ !-------------------------------------------------------------------------
+ subroutine lightning_register()
+
+ call pbuf_add_field('LGHT_FLASH_FREQ','global',dtype_r8,(/pcols/),flsh_frq_ndx) ! per minute
+
+ end subroutine lightning_register
+
+ !-------------------------------------------------------------------------
+ !-------------------------------------------------------------------------
+ subroutine lightning_init( pbuf2d )
!----------------------------------------------------------------------
! ... initialize the lightning module
!----------------------------------------------------------------------
use mo_constants, only : pi
- use mo_chem_utls, only : get_spc_ndx
use cam_history, only : addfld, add_default, horiz_only
use phys_control, only : phys_getopts
-
- implicit none
+ use time_manager, only : is_first_step
!----------------------------------------------------------------------
! ... dummy args
!----------------------------------------------------------------------
- real(r8), intent(in) :: lght_no_prd_factor ! lightning no production factor
+ type(physics_buffer_desc), pointer :: pbuf2d(:,:)
!----------------------------------------------------------------------
! ... local variables
!----------------------------------------------------------------------
- integer :: astat
+ integer :: astat, err
logical :: history_cesm_forcing
+ character(len=*),parameter :: prefix = 'lightning_init: '
+
+ cldtop_ndx = pbuf_get_index('CLDTOP',errcode=err)
+ cldbot_ndx = pbuf_get_index('CLDBOT',errcode=err)
+ calc_lightning = cldtop_ndx>0 .and. cldbot_ndx>0
+
+ if (.not.calc_lightning) return
+
+ calc_nox_prod = lght_no_prd_factor>0._r8
+
+ if (calc_nox_prod) then
+
+ if (masterproc) write(iulog,*) prefix,'lightning no production scaling factor = ',factor
+
+ !----------------------------------------------------------------------
+ ! ... vdist(kk,itype) = % of lightning nox between (kk-1) and (kk)
+ ! km for profile itype
+ !----------------------------------------------------------------------
+ allocate(vdist(16,3),stat=astat)
+ if( astat /= 0 ) then
+ write(iulog,*) prefix,'failed to allocate vdist; error = ',astat
+ call endrun(prefix//'failed to allocate vdist')
+ end if
+ vdist(:,1) = (/ 3.0_r8, 3.0_r8, 3.0_r8, 3.0_r8, 3.4_r8, 3.5_r8, 3.6_r8, 4.0_r8, & ! midlat cont
+ 5.0_r8, 7.0_r8, 9.0_r8, 14.0_r8, 16.0_r8, 14.0_r8, 8.0_r8, 0.5_r8 /)
+ vdist(:,2) = (/ 2.5_r8, 2.5_r8, 2.5_r8, 2.5_r8, 2.5_r8, 2.5_r8, 2.5_r8, 6.1_r8, & ! trop marine
+ 17.0_r8, 15.4_r8, 14.5_r8, 13.0_r8, 12.5_r8, 2.8_r8, 0.9_r8, 0.3_r8 /)
+ vdist(:,3) = (/ 2.0_r8, 2.0_r8, 2.0_r8, 1.5_r8, 1.5_r8, 1.5_r8, 3.0_r8, 5.8_r8, & ! trop cont
+ 7.6_r8, 9.6_r8, 11.0_r8, 14.0_r8, 14.0_r8, 14.0_r8, 8.2_r8, 2.3_r8 /)
+
+ allocate( prod_no(pcols,pver,begchunk:endchunk),stat=astat )
+ if( astat /= 0 ) then
+ write(iulog,*) prefix, 'failed to allocate prod_no; error = ',astat
+ call endrun(prefix//'failed to allocate prod_no')
+ end if
+ geo_factor = ngcols_p/(4._r8*pi)
+
+ call addfld( 'LNO_COL_PROD', horiz_only, 'I', 'Tg N yr-1', 'lightning column NO source' )
+ call addfld( 'LNO_PROD', (/ 'lev' /), 'I', 'molecules/cm3/s', 'lightning insitu NO source' )
+ call addfld( 'FLASHENGY', horiz_only, 'I', 'J', 'lightning flash energy' ) ! flash energy
+
+ call phys_getopts( history_cesm_forcing_out = history_cesm_forcing )
+ if ( history_cesm_forcing ) then
+ call add_default('LNO_COL_PROD',1,' ')
+ endif
+
+ if (is_first_step()) then
+ call pbuf_set_field(pbuf2d, flsh_frq_ndx, 0.0_r8)
+ endif
- call phys_getopts( history_cesm_forcing_out = history_cesm_forcing )
-
- no_ndx = get_spc_ndx('NO')
- xno_ndx = get_spc_ndx('XNO')
-
- has_no_lightning_prod = no_ndx>0 .or. xno_ndx>0
- if (.not.has_no_lightning_prod) return
-
-
- if( lght_no_prd_factor /= 1._r8 ) then
- factor = factor*lght_no_prd_factor
- end if
-
-
- if (masterproc) write(iulog,*) 'lght_inti: lightning no production scaling factor = ',factor
-
- !----------------------------------------------------------------------
- ! ... vdist(kk,itype) = % of lightning nox between (kk-1) and (kk)
- ! km for profile itype
- !----------------------------------------------------------------------
- vdist(:,1) = (/ 3.0_r8, 3.0_r8, 3.0_r8, 3.0_r8, 3.4_r8, 3.5_r8, 3.6_r8, 4.0_r8, & ! midlat cont
- 5.0_r8, 7.0_r8, 9.0_r8, 14.0_r8, 16.0_r8, 14.0_r8, 8.0_r8, 0.5_r8 /)
- vdist(:,2) = (/ 2.5_r8, 2.5_r8, 2.5_r8, 2.5_r8, 2.5_r8, 2.5_r8, 2.5_r8, 6.1_r8, & ! trop marine
- 17.0_r8, 15.4_r8, 14.5_r8, 13.0_r8, 12.5_r8, 2.8_r8, 0.9_r8, 0.3_r8 /)
- vdist(:,3) = (/ 2.0_r8, 2.0_r8, 2.0_r8, 1.5_r8, 1.5_r8, 1.5_r8, 3.0_r8, 5.8_r8, & ! trop cont
- 7.6_r8, 9.6_r8, 11.0_r8, 14.0_r8, 14.0_r8, 14.0_r8, 8.2_r8, 2.3_r8 /)
-
- allocate( prod_no(pcols,pver,begchunk:endchunk),stat=astat )
- if( astat /= 0 ) then
- write(iulog,*) 'lght_inti: failed to allocate prod_no; error = ',astat
- call endrun
- end if
- allocate( flash_freq(pcols,begchunk:endchunk),stat=astat )
- if( astat /= 0 ) then
- write(iulog,*) 'lght_inti: failed to allocate flash_freq; error = ',astat
- call endrun
- end if
- allocate( glob_prod_no_col(pcols,begchunk:endchunk),stat=astat )
- if( astat /= 0 ) then
- write(iulog,*) 'lght_inti: failed to allocate glob_prod_no_col; error = ',astat
- call endrun
- end if
- prod_no(:,:,:) = 0._r8
- flash_freq(:,:) = 0._r8
- geo_factor = ngcols_p/(4._r8*pi)
-
-
- call addfld( 'LNO_COL_PROD', horiz_only, 'I', 'TG N/YR', 'lighting column NO source' )
- call addfld( 'LNO_PROD', (/ 'lev' /), 'I', '/cm3/s', 'lighting insitu NO source' )
- call addfld( 'FLASHFRQ', horiz_only, 'I', '1/MIN', 'lighting flash rate' ) ! flash frequency in grid box per minute (PPP)
- call addfld( 'FLASHENGY', horiz_only, 'I', ' ', 'lighting flash rate' ) ! flash frequency in grid box per minute (PPP)
- call addfld( 'CLDHGT', horiz_only, 'I', 'KM', 'cloud top height' ) ! cloud top height
- call addfld( 'DCHGZONE', horiz_only, 'I', 'KM', 'depth of discharge zone' ) ! depth of discharge zone
- call addfld( 'CGIC', horiz_only, 'I', 'RATIO', 'ratio of cloud-ground/intracloud discharges' ) ! ratio of cloud-ground/intracloud discharges
-
- if ( history_cesm_forcing ) then
- call add_default('LNO_COL_PROD',1,' ')
endif
- end subroutine lightning_inti
+ call addfld( 'FLASHFRQ', horiz_only, 'I', 'min-1', 'lightning flash rate' ) ! flash frequency in grid box per minute (PPP)
+ call addfld( 'CLDHGT', horiz_only, 'I', 'km', 'cloud top height' ) ! cloud top height
+ call addfld( 'DCHGZONE', horiz_only, 'I', 'km', 'depth of discharge zone' ) ! depth of discharge zone
+ call addfld( 'CGIC', horiz_only, 'I', '1', 'ratio of cloud-ground/intracloud discharges' ) ! ratio of cloud-ground/intracloud discharges
+ call addfld( 'LGHTNG_CLD2GRND', horiz_only, 'I', 'min-1', 'clound-to-ground lightning flash rate') ! clound to ground flash frequency
+ end subroutine lightning_init
+
+ !-------------------------------------------------------------------------
+ !-------------------------------------------------------------------------
subroutine lightning_no_prod( state, pbuf2d, cam_in )
!----------------------------------------------------------------------
! ... set no production from lightning
!----------------------------------------------------------------------
use physics_types, only : physics_state
-
- use physics_buffer, only : pbuf_get_index, physics_buffer_desc, pbuf_get_field, pbuf_get_chunk
use physconst, only : rga
use phys_grid, only : get_rlat_all_p, get_wght_all_p
use cam_history, only : outfld
use camsrfexch, only : cam_in_t
use shr_reprosum_mod, only : shr_reprosum_calc
- use mo_constants, only : rearth, d2r
- implicit none
+ use mo_constants, only : rearth, d2r
!----------------------------------------------------------------------
! ... dummy args
!----------------------------------------------------------------------
type(physics_state), intent(in) :: state(begchunk:endchunk) ! physics state
-
type(physics_buffer_desc), pointer :: pbuf2d(:,:)
type(cam_in_t), intent(in) :: cam_in(begchunk:endchunk) ! physics state
!----------------------------------------------------------------------
! ... local variables
!----------------------------------------------------------------------
- real(r8), parameter :: land = 1._r8
- real(r8), parameter :: secpyr = 365._r8 * 8.64e4_r8
+ real(r8), parameter :: land = 1._r8
+ real(r8), parameter :: secpyr = 365._r8 * 8.64e4_r8
- integer :: i, c
integer :: cldtind ! level index for cloud top
integer :: cldbind ! level index for cloud base > 273k
integer :: k, kk, zlow_ind, zhigh_ind, itype
@@ -162,16 +227,20 @@ subroutine lightning_no_prod( state, pbuf2d, cam_in )
real(r8) :: flash_energy(pcols,begchunk:endchunk) ! energy of flashes per second
real(r8) :: prod_no_col(pcols,begchunk:endchunk) ! global no production rate for diagnostics
real(r8) :: wrk, wrk1, wrk2(1)
+ integer :: icol ! column index
integer :: ncol ! columns per chunk
- integer :: lchnk ! columns per chunk
+ integer :: lchnk ! chunk index
real(r8),pointer :: cldtop(:) ! cloud top level index
real(r8),pointer :: cldbot(:) ! cloud bottom level index
real(r8) :: zmid(pcols,pver) ! geopot height above surface at midpoints (m)
real(r8) :: zint(pcols,pver+1,begchunk:endchunk) ! geopot height above surface at interfaces (m)
real(r8) :: zsurf(pcols) ! geopot height above surface at interfaces (m)
- real(r8) :: rlats(pcols,begchunk:endchunk) ! column latitudes in chunks
+ real(r8) :: rlats(pcols) ! column latitudes in chunks
real(r8) :: wght(pcols)
+ real(r8) :: glob_prod_no_col(pcols,begchunk:endchunk)
+ real(r8) :: flash_freq(pcols,begchunk:endchunk)
+
!----------------------------------------------------------------------
! ... parameters to determine cg/ic ratio [price and rind, 1993]
!----------------------------------------------------------------------
@@ -184,26 +253,29 @@ subroutine lightning_no_prod( state, pbuf2d, cam_in )
real(r8), parameter :: m2km = 1.e-3_r8
real(r8), parameter :: km2cm = 1.e5_r8
real(r8), parameter :: lat25 = 25._r8*d2r ! 25 degrees latitude in radians
- integer :: cldtop_ndx, cldbot_ndx
+
real(r8) :: flash_freq_land, flash_freq_ocn
+ real(r8), pointer :: cld2grnd_flash_freq(:)
+
+ if (.not.calc_lightning) return
- if (.not.has_no_lightning_prod) return
+ nullify(cld2grnd_flash_freq)
!----------------------------------------------------------------------
! ... initialization
!----------------------------------------------------------------------
flash_freq(:,:) = 0._r8
- prod_no(:,:,:) = 0._r8
- prod_no_col(:,:) = 0._r8
cldhgt(:,:) = 0._r8
dchgzone(:,:) = 0._r8
cgic(:,:) = 0._r8
flash_energy(:,:) = 0._r8
- glob_prod_no_col(:,:) = 0._r8
- cldtop_ndx = pbuf_get_index('CLDTOP')
- cldbot_ndx = pbuf_get_index('CLDBOT')
+ if (calc_nox_prod) then
+ prod_no(:,:,:) = 0._r8
+ prod_no_col(:,:) = 0._r8
+ glob_prod_no_col(:,:) = 0._r8
+ end if
!--------------------------------------------------------------------------------
! ... estimate flash frequency and resulting no emissions
@@ -223,29 +295,30 @@ subroutine lightning_no_prod( state, pbuf2d, cam_in )
! with 1e17 n atoms per j. the total number of n atoms is then distributed
! over the complete column of grid boxes.
!--------------------------------------------------------------------------------
- Chunk_loop : do c = begchunk,endchunk
- ncol = state(c)%ncol
- lchnk = state(c)%lchnk
+ Chunk_loop : do lchnk = begchunk,endchunk
+ ncol = state(lchnk)%ncol
+ call pbuf_get_field(pbuf_get_chunk(pbuf2d,lchnk), flsh_frq_ndx, cld2grnd_flash_freq )
call pbuf_get_field(pbuf_get_chunk(pbuf2d,lchnk), cldtop_ndx, cldtop )
call pbuf_get_field(pbuf_get_chunk(pbuf2d,lchnk), cldbot_ndx, cldbot )
- zsurf(:ncol) = state(c)%phis(:ncol)*rga
- call get_rlat_all_p(c, ncol, rlats(1,c) )
- call get_wght_all_p(c, ncol, wght)
+ zsurf(:ncol) = state(lchnk)%phis(:ncol)*rga
+ call get_wght_all_p(lchnk, pcols, wght)
do k = 1,pver
- zmid(:ncol,k) = state(c)%zm(:ncol,k) + zsurf(:ncol)
- zint(:ncol,k,c) = state(c)%zi(:ncol,k) + zsurf(:ncol)
+ zmid(:ncol,k) = state(lchnk)%zm(:ncol,k) + zsurf(:ncol)
+ zint(:ncol,k,lchnk) = state(lchnk)%zi(:ncol,k) + zsurf(:ncol)
end do
- zint(:ncol,pver+1,c) = state(c)%zi(:ncol,pver+1) + zsurf(:ncol)
+ zint(:ncol,pver+1,lchnk) = state(lchnk)%zi(:ncol,pver+1) + zsurf(:ncol)
+
+ cld2grnd_flash_freq(:) = 0.0_r8
- col_loop : do i = 1,ncol
+ col_loop : do icol = 1,ncol
!--------------------------------------------------------------------------------
! ... find cloud top and bottom level above 273k
!--------------------------------------------------------------------------------
- cldtind = nint( cldtop(i) )
- cldbind = nint( cldbot(i) )
+ cldtind = nint( cldtop(icol) )
+ cldbind = nint( cldbot(icol) )
do
- if( cldbind <= cldtind .or. state(c)%t(i,cldbind) < t0 ) then
+ if( cldbind <= cldtind .or. state(lchnk)%t(icol,cldbind) < t0 ) then
exit
end if
cldbind = cldbind - 1
@@ -254,58 +327,77 @@ subroutine lightning_no_prod( state, pbuf2d, cam_in )
!--------------------------------------------------------------------------------
! ... compute cloud top height and depth of charging zone
!--------------------------------------------------------------------------------
- cldhgt(i,c) = m2km*max( 0._r8,zint(i,cldtind,c) )
- dchgz = cldhgt(i,c) - m2km*zmid(i,cldbind)
- dchgzone(i,c) = dchgz
+ cldhgt(icol,lchnk) = m2km*max( 0._r8,zint(icol,cldtind,lchnk) )
+ dchgz = cldhgt(icol,lchnk) - m2km*zmid(icol,cldbind)
+ dchgzone(icol,lchnk) = dchgz
!--------------------------------------------------------------------------------
! ... compute flash frequency for given cloud top height
! (flashes storm^-1 min^-1)
!--------------------------------------------------------------------------------
- flash_freq_land = 3.44e-5_r8 * cldhgt(i,c)**4.9_r8
- flash_freq_ocn = 6.40e-4_r8 * cldhgt(i,c)**1.7_r8
- flash_freq(i,c) = cam_in(c)%landfrac(i)*flash_freq_land + &
- cam_in(c)%ocnfrac(i) *flash_freq_ocn
+ flash_freq_land = 3.44e-5_r8 * cldhgt(icol,lchnk)**4.9_r8
+ flash_freq_ocn = 6.40e-4_r8 * cldhgt(icol,lchnk)**1.7_r8
+ flash_freq(icol,lchnk) = cam_in(lchnk)%landfrac(icol)*flash_freq_land + &
+ cam_in(lchnk)%ocnfrac(icol) *flash_freq_ocn
!--------------------------------------------------------------------------------
- ! ... compute cg/ic ratio
- ! cgic = proportion of cg flashes (=pg from ppp paper)
+ ! cgic = proportion of cloud-to-ground flashes
+ ! NOx from lightning 1. Global distribution based on lightning physics, C Price et al
+ ! JOURNAL OF GEOPHYSICAL RESEARCH, VOL. 102, NO. D5, PAGES 5929-5941, MARCH 20, 1997
+ ! (https://agupubs.onlinelibrary.wiley.com/doi/epdf/10.1029/96JD03504)
+ ! eq 14
!--------------------------------------------------------------------------------
- cgic(i,c) = 1._r8/((((ca*dchgz + cb)*dchgz + cc) *dchgz + cd)*dchgz + ce)
+ cgic(icol,lchnk) = 1._r8/((((ca*dchgz + cb)*dchgz + cc) *dchgz + cd)*dchgz + ce)
if( dchgz < 5.5_r8 ) then
- cgic(i,c) = 0._r8
+ cgic(icol,lchnk) = 0._r8
else if( dchgz > 14._r8 ) then
- cgic(i,c) = .02_r8
+ cgic(icol,lchnk) = .02_r8
end if
- !--------------------------------------------------------------------------------
- ! ... compute flash energy (cg*6.7e9 + ic*6.7e8)
- ! and convert to total energy per second
- ! set ic = cg
- !--------------------------------------------------------------------------------
- flash_energy(i,c) = 6.7e9_r8 * flash_freq(i,c)/60._r8
- !--------------------------------------------------------------------------------
- ! ... LKE Aug 23, 2005: scale production to account for different grid
- ! box sizes. This requires a reduction in the overall fudge factor
- ! (e.g., from 1.2 to 0.5)
- !--------------------------------------------------------------------------------
- flash_energy(i,c) = flash_energy(i,c) * wght(i) * geo_factor
- !--------------------------------------------------------------------------------
- ! ... compute number of n atoms produced per second
- ! and convert to n atoms per second per cm2 and apply fudge factor
- !--------------------------------------------------------------------------------
- prod_no_col(i,c) = 1.e17_r8*flash_energy(i,c)/(1.e4_r8*rearth*rearth*wght(i)) * factor
-
- !--------------------------------------------------------------------------------
- ! ... compute global no production rate in tgn/yr:
- ! tgn per second: * 14.00674 * 1.65979e-24 * 1.e-12
- ! nb: 1.65979e-24 = 1/avo
- ! tgn per year: * secpyr
- !--------------------------------------------------------------------------------
- glob_prod_no_col(i,c) = 1.e17_r8*flash_energy(i,c) &
- * 14.00674_r8 * 1.65979e-24_r8 * 1.e-12_r8 * secpyr * factor
+ cld2grnd_flash_freq(icol) = cam_in(lchnk)%landfrac(icol)*flash_freq_land*cgic(icol,lchnk) ! cld-to-grnd flash frq (per min)
+
+ if (calc_nox_prod) then
+ !--------------------------------------------------------------------------------
+ ! ... compute flash energy (cg*6.7e9 + ic*6.7e8)
+ ! and convert to total energy per second
+ ! set ic = cg
+ !--------------------------------------------------------------------------------
+ flash_energy(icol,lchnk) = 6.7e9_r8 * flash_freq(icol,lchnk)/60._r8
+ !--------------------------------------------------------------------------------
+ ! ... LKE Aug 23, 2005: scale production to account for different grid
+ ! box sizes. This requires a reduction in the overall fudge factor
+ ! (e.g., from 1.2 to 0.5)
+ !--------------------------------------------------------------------------------
+ flash_energy(icol,lchnk) = flash_energy(icol,lchnk) * wght(icol) * geo_factor
+ !--------------------------------------------------------------------------------
+ ! ... compute number of n atoms produced per second
+ ! and convert to n atoms per second per cm2 and apply fudge factor
+ !--------------------------------------------------------------------------------
+ prod_no_col(icol,lchnk) = 1.e17_r8*flash_energy(icol,lchnk)/(1.e4_r8*rearth*rearth*wght(icol)) * factor
+
+ !--------------------------------------------------------------------------------
+ ! ... compute global no production rate in tgn/yr:
+ ! tgn per second: * 14.00674 * 1.65979e-24 * 1.e-12
+ ! nb: 1.65979e-24 = 1/avo
+ ! tgn per year: * secpyr
+ !--------------------------------------------------------------------------------
+ glob_prod_no_col(icol,lchnk) = 1.e17_r8*flash_energy(icol,lchnk) &
+ * 14.00674_r8 * 1.65979e-24_r8 * 1.e-12_r8 * secpyr * factor
+ end if
end if cloud_layer
end do Col_loop
+
+ call outfld( 'LGHTNG_CLD2GRND', cld2grnd_flash_freq, pcols, lchnk )
end do Chunk_loop
+
+ do lchnk = begchunk,endchunk
+ call outfld( 'FLASHFRQ', flash_freq(:,lchnk), pcols, lchnk )
+ call outfld( 'CGIC', cgic(:,lchnk), pcols, lchnk )
+ call outfld( 'CLDHGT', cldhgt(:,lchnk), pcols, lchnk )
+ call outfld( 'DCHGZONE', dchgzone(:,lchnk), pcols, lchnk )
+ enddo
+
+ if (.not.calc_nox_prod) return
+
!--------------------------------------------------------------------------------
! ... Accumulate global total, convert to flashes per second
! ... Accumulate global NO production rate
@@ -325,29 +417,29 @@ subroutine lightning_no_prod( state, pbuf2d, cam_in )
!--------------------------------------------------------------------------------
! ... Distribute production up to cloud top [Pickering et al., 1998 (JGR)]
!--------------------------------------------------------------------------------
- do c = begchunk,endchunk
- ncol = state(c)%ncol
- lchnk = state(c)%lchnk
+ do lchnk = begchunk,endchunk
+ call get_rlat_all_p(lchnk, pcols, rlats)
+ ncol = state(lchnk)%ncol
call pbuf_get_field(pbuf_get_chunk(pbuf2d,lchnk), cldtop_ndx, cldtop )
- do i = 1,ncol
- cldtind = nint( cldtop(i) )
- if( prod_no_col(i,c) > 0._r8 ) then
- if( cldhgt(i,c) > 0._r8 ) then
- if( abs( rlats(i,c) ) > lat25 ) then
- itype = 1 ! midlatitude continental
- else if( nint( cam_in(c)%landfrac(i) ) == land ) then
- itype = 3 ! tropical continental
+ do icol = 1,ncol
+ cldtind = nint( cldtop(icol) )
+ if( prod_no_col(icol,lchnk) > 0._r8 ) then
+ if( cldhgt(icol,lchnk) > 0._r8 ) then
+ if( abs( rlats(icol) ) > lat25 ) then
+ itype = 1 ! midlatitude continental
+ else if( nint( cam_in(lchnk)%landfrac(icol) ) == land ) then
+ itype = 3 ! tropical continental
else
- itype = 2 ! topical marine
+ itype = 2 ! topical marine
end if
frac_sum = 0._r8
do k = cldtind,pver
- zlow = zint(i,k+1,c) * m2km ! lower interface height (km)
- zlow_scal = zlow * 16._r8/cldhgt(i,c) ! scale to 16 km convection height
- zlow_ind = max( 1,INT(zlow_scal)+1 ) ! lowest vdist index to include in layer
- zhigh = zint(i,k,c) * m2km ! upper interface height (km)
- zhigh_scal = zhigh * 16._r8/cldhgt(i,c) ! height (km) scaled to 16km convection height
- zhigh_ind = max( 1,MIN( 16,INT(zhigh_scal)+1 ) ) ! highest vdist index to include in layer
+ zlow = zint(icol,k+1,lchnk) * m2km ! lower interface height (km)
+ zlow_scal = zlow * 16._r8/cldhgt(icol,lchnk) ! scale to 16 km convection height
+ zlow_ind = max( 1,INT(zlow_scal)+1 ) ! lowest vdist index to include in layer
+ zhigh = zint(icol,k,lchnk) * m2km ! upper interface height (km)
+ zhigh_scal = zhigh * 16._r8/cldhgt(icol,lchnk) ! height (km) scaled to 16km convection height
+ zhigh_ind = max( 1,MIN( 16,INT(zhigh_scal)+1 ) ) ! highest vdist index to include in layer
do kk = zlow_ind,zhigh_ind
wrk = kk
wrk1 = kk - 1
@@ -355,11 +447,11 @@ subroutine lightning_no_prod( state, pbuf2d, cam_in )
- max( zlow_scal,wrk1 )
fraction = max( 0._r8, min( 1._r8,fraction ) )
frac_sum = frac_sum + fraction*vdist(kk,itype)
- prod_no(i,k,c) = prod_no(i,k,c) & ! sum the fraction of column NOx in layer k
+ prod_no(icol,k,lchnk) = prod_no(icol,k,lchnk) & ! sum the fraction of column NOx in layer k
+ fraction*vdist(kk,itype)*.01_r8
end do
- prod_no(i,k,c) = prod_no_col(i,c) * prod_no(i,k,c) & ! multiply fraction by column amount
- / (km2cm*(zhigh - zlow)) ! and convert to atom N cm^-3 s^-1
+ prod_no(icol,k,lchnk) = prod_no_col(icol,lchnk) * prod_no(icol,k,lchnk) & ! multiply fraction by column amount
+ / (km2cm*(zhigh - zlow)) ! and convert to atom N cm^-3 s^-1
end do
end if
end if
@@ -370,15 +462,10 @@ subroutine lightning_no_prod( state, pbuf2d, cam_in )
!--------------------------------------------------------------------------------
! ... output lightning no production to history file
!--------------------------------------------------------------------------------
- do c = begchunk,endchunk
- lchnk = state(c)%lchnk
- call outfld( 'LNO_PROD', prod_no(:,:,c), pcols, lchnk )
- call outfld( 'LNO_COL_PROD', glob_prod_no_col(:,c), pcols, lchnk )
- call outfld( 'FLASHFRQ', flash_freq(:,c), pcols, lchnk )
- call outfld( 'FLASHENGY', flash_energy(:,c), pcols, lchnk )
- call outfld( 'CLDHGT', cldhgt(:,c), pcols, lchnk )
- call outfld( 'DCHGZONE', dchgzone(:,c), pcols, lchnk )
- call outfld( 'CGIC', cgic(:,c), pcols, lchnk )
+ do lchnk = begchunk,endchunk
+ call outfld( 'LNO_PROD', prod_no(:,:,lchnk), pcols, lchnk )
+ call outfld( 'LNO_COL_PROD', glob_prod_no_col(:,lchnk), pcols, lchnk )
+ call outfld( 'FLASHENGY', flash_energy(:,lchnk), pcols, lchnk )
enddo
end subroutine lightning_no_prod
diff --git a/src/chemistry/mozart/ocean_emis.F90 b/src/chemistry/mozart/ocean_emis.F90
index 26819fd846..289cafeb77 100644
--- a/src/chemistry/mozart/ocean_emis.F90
+++ b/src/chemistry/mozart/ocean_emis.F90
@@ -3,23 +3,23 @@
! Ref: Carpenter et al Chem Soc Rev (2012); Johnson, Ocean sci (2010)
! ------------------------------------------------------------------------------------
! Required inputs for the air-sea flux module:
-! - Seawater concentration (nanomoles per liter) and Sea surface salinity
+! - Seawater concentration (nanomoles per liter) and Sea surface salinity
! (parts per thousand) read from namelist (netCDF)
! - Concentration in the gas-phase (pptv), air temperature (K), 10m windspeed (m/s),
! surface pressure (atm), sea surface temperature (K): all from other modules
! ------------------------------------------------------------------------------------
! Key subroutines:
-! ocean_emis_readnl(..): Read salinity from namelist (user_nl_cam).
+! ocean_emis_readnl(..): Read salinity from namelist (user_nl_cam).
! Salinity not time-dependent. Flux depends very weakly on it
-! ocean_emis_init(...): Interpolate salinity, initialize the library for the flux
+! ocean_emis_init(...): Interpolate salinity, initialize the library for the flux
! reading time-dependent seawater conc. from user_nl_cam
! ocean_emis_advance(...): process the seawater concentration
-! ocean_emis_getflux(...): calculate the air-sea flux (upward or downward),
+! ocean_emis_getflux(...): calculate the air-sea flux (upward or downward),
! then add to total surface flux (sflx)
! ------------------------------------------------------------------------------------
! Last built: 9 March 2018.
! Written by: Siyuan Wang (ACOM/NCAR) siyuan@ucar.edu
-! Acknowledgement: Francis Vitt (NCAR). and of course Dr. Peppurr too
+! Acknowledgement: Francis Vitt (NCAR). and of course Dr. Peppurr too
! ====================================================================================
module ocean_emis
@@ -33,7 +33,7 @@ module ocean_emis
use tracer_data, only : trfld,trfile
use chem_mods, only : gas_pcnst
use cam_logfile, only : iulog
- use ioFileMod, only : getfil
+ use ioFileMod, only : getfil
implicit none
@@ -57,9 +57,9 @@ module ocean_emis
logical :: switch_bubble
type(Csw), allocatable :: Csw_nM(:)
- integer :: n_Csw_files
+ integer :: n_Csw_files
- real(r8), allocatable :: salinity(:,:)
+ real(r8), allocatable :: salinity(:,:)
! ================
! Air-sea exchange
@@ -69,32 +69,32 @@ module ocean_emis
Integer, Parameter :: HowManySalts = 5 ! Change this number if you wanna add more salts
Integer, Parameter :: HowManySaltProperties = 7 ! Don't touch this (unless you wanna add more fields)
- Type GasLib
+ Type GasLib
Character(16) :: CmpdName
Real(r8), Dimension(HowManyProperties) :: CmpdProperties
End Type GasLib
- Type SaltLib
+ Type SaltLib
Character(16) :: SaltName
- Real(r8), Dimension(HowManySaltProperties) :: SaltProperties
+ Real(r8), Dimension(HowManySaltProperties) :: SaltProperties
End Type SaltLib
Type(GasLib), Dimension(HowManyMolecules) :: GasList ! Library for the trace gas properties
Type(SaltLib), Dimension(HowManySalts) :: SaltList ! Library for the salt properties
- ! ===========================
+ ! ===========================
! seawater concentration:
! ===========================
- character(len=cl) :: csw_specifier(gas_pcnst) = ''
+ character(len=cl) :: csw_specifier(gas_pcnst) = ''
character(len=24) :: csw_time_type = 'CYCLICAL' ! 'CYCLICAL' | 'SERIAL' | 'INTERP_MISSING_MONTHS'
integer :: csw_cycle_yr = 0
- logical :: bubble_mediated_transfer = .false.
+ logical :: bubble_mediated_transfer = .false.
character(len=cl) :: ocean_salinity_file = 'NONE'
contains
-!--------------------------------------------------------------------------------
-!--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
subroutine ocean_emis_readnl(nlfile)
use namelist_utils, only : find_group_name
@@ -105,7 +105,7 @@ subroutine ocean_emis_readnl(nlfile)
integer :: unitn, ierr
character(len=*), parameter :: subname = 'ocean_emis_readnl'
- ! ===================
+ ! ===================
! Namelist definition
! ===================
namelist /ocean_emis_nl/ ocean_salinity_file
@@ -125,7 +125,7 @@ subroutine ocean_emis_readnl(nlfile)
end if
close(unitn)
end if
-
+
! ============================
! Broadcast namelist variables
! ============================
@@ -151,7 +151,7 @@ subroutine ocean_emis_init()
use pio, only : file_desc_t, pio_inq_dimid, pio_inq_dimlen, pio_inq_varid, pio_get_var
use pio, only : PIO_NOWRITE, PIO_NOERR
use pio, only : pio_seterrorhandling, PIO_BCAST_ERROR, pio_closefile
- use phys_grid, only : get_ncols_p, get_rlon_all_p, get_rlat_all_p
+ use phys_grid, only : get_ncols_p, get_rlon_all_p, get_rlat_all_p
use interpolate_data, only : lininterp_init, lininterp, interp_type, lininterp_finish
use mo_constants, only : pi
@@ -162,19 +162,19 @@ subroutine ocean_emis_init()
real(r8), allocatable :: file_lats(:), file_lons(:)
real(r8), allocatable :: wrk2d(:,:)
real(r8) :: to_lats(pcols), to_lons(pcols)
- type(interp_type) :: lon_wgts, lat_wgts
+ type(interp_type) :: lon_wgts, lat_wgts
real(r8), parameter :: zero=0_r8, twopi=2_r8*pi, degs2rads = pi/180._r8
character(len=*), parameter :: subname = 'ocean_emis_init'
-
+
if (trim(ocean_salinity_file) == 'NONE') return
call getfil( ocean_salinity_file, filen, 0 )
call cam_pio_openfile( fid, filen, PIO_NOWRITE)
-
+
call pio_seterrorhandling(fid, PIO_BCAST_ERROR)
-
+
ierr = pio_inq_dimid( fid, 'lon', dimid )
if (ierr /= PIO_NOERR) then
call endrun(subname//': pio_inq_dimid lon FAILED')
@@ -225,6 +225,7 @@ subroutine ocean_emis_init()
endif
allocate(salinity(pcols,begchunk:endchunk))
+ salinity = 0._r8
do c=begchunk,endchunk
@@ -235,17 +236,22 @@ subroutine ocean_emis_init()
call lininterp_init(file_lons, file_nlon, to_lons, ncols, 2, lon_wgts, zero, twopi)
call lininterp_init(file_lats, file_nlat, to_lats, ncols, 1, lat_wgts)
- call lininterp(wrk2d, file_nlon, file_nlat, salinity(1:ncols,c), ncols, lon_wgts, lat_wgts)
+ call lininterp(wrk2d, file_nlon, file_nlat, salinity(1:ncols,c), ncols, lon_wgts, lat_wgts)
call lininterp_finish(lon_wgts)
call lininterp_finish(lat_wgts)
end do
+ ! fill in missing values with climatology for modern-day
+ where(salinity < 0._r8)
+ salinity = 33.0_r8
+ end where
+
deallocate( file_lons, file_lats )
deallocate( wrk2d )
- call addfld('OCN_SALINITY', horiz_only, 'A', 'parts per thousands', 'ocean salinity' )
+ call addfld('OCN_SALINITY', horiz_only, 'A', 'parts per thousands', 'ocean salinity' )
! ======================================================
! initializing the libraries for the air-sea flux module
@@ -253,17 +259,17 @@ subroutine ocean_emis_init()
Call CmpLibInitialization()
Call SaltLibInitialization()
- ! ---------------------------------------------
+ ! ---------------------------------------------
! Read seawater concentration: WSY
! ---------------------------------------------
call cseawater_ini()
call pio_closefile (fid)
-
+
end subroutine ocean_emis_init
-!--------------------------------------------------------------------------------
-!--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
subroutine ocean_emis_advance( pbuf2d, state )
! -------------------------------
! check serial case for time span
@@ -274,7 +280,7 @@ subroutine ocean_emis_advance( pbuf2d, state )
use tracer_data, only : advance_trcdata
use physics_buffer, only : physics_buffer_desc
- type(physics_state), intent(in) :: state(begchunk:endchunk)
+ type(physics_state), intent(in) :: state(begchunk:endchunk)
type(physics_buffer_desc), pointer :: pbuf2d(:,:)
integer :: m
@@ -286,12 +292,12 @@ subroutine ocean_emis_advance( pbuf2d, state )
end subroutine ocean_emis_advance
-!--------------------------------------------------------------------------------
-!--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
subroutine ocean_emis_getflux(lchnk, ncol, state, u10, sst, ocnfrac, icefrac, sflx)
use physics_types, only : physics_state
- use ppgrid, only : pver
+ use ppgrid, only : pver
integer, intent(in) :: lchnk, ncol
type(physics_state), target, intent(in) :: state ! Physics state variables
@@ -301,13 +307,13 @@ subroutine ocean_emis_getflux(lchnk, ncol, state, u10, sst, ocnfrac, icefrac, sf
real(r8), intent(in) :: icefrac(:) ! Ice fraction
real(r8), intent(inout) :: sflx(:,:) ! Surface emissions (kg/m^2/s)
- integer :: m, isec, SpeciesID
- real(r8) :: Csw_col(ncol)
- real(r8) :: MW_species
- real(r8) :: oceanflux_kg_m2_s(ncol)
+ integer :: i, m, isec, SpeciesID
+ real(r8) :: Csw_col(ncol)
+ real(r8) :: MW_species
+ real(r8) :: oceanflux_kg_m2_s(ncol)
if (trim(ocean_salinity_file) == 'NONE') return
-
+
! ==================================================
! Get seawater concentrations and calculate the flux
! ==================================================
@@ -317,28 +323,30 @@ subroutine ocean_emis_getflux(lchnk, ncol, state, u10, sst, ocnfrac, icefrac, sf
isec = 1
Csw_col(:ncol) = Csw_nM(m)%scalefactor*Csw_nM(m)%fields(isec)%data(:ncol,1,lchnk)
- MW_species = MolecularWeight(SpeciesIndex( Csw_nM(m)%species ))
+ MW_species = MolecularWeight(SpeciesIndex( Csw_nM(m)%species ))
call cnst_get_ind( trim(Csw_nM(m)%species), SpeciesID, abort=.true. )
oceanflux_kg_m2_s = 0.0_r8
- where (ocnfrac(:ncol) >= 0.2_r8 .and. Csw_col(:ncol) >= 0._r8) ! calculate flux only for ocean
- oceanflux_kg_m2_s(:ncol) = Flux_kg_m2_s( &
- Csw_nM(m)%species, & ! name of species
- state%q(:ncol,pver,SpeciesID) * (28.97_r8/MW_species) * 1.0e+12_r8, & ! air concentration (ppt)
- Csw_col(:ncol), & ! sea water concentration (nM)
- state%t(:ncol,pver), & ! air temperature (K)
- u10(:ncol), & ! wind speed at 10m (m/s) <- should use this
- state%ps(:ncol) / 101325.0_r8, & ! surface pressure (atm)
- sst(:ncol), & ! sea surface temperautre (K)
- salinity(:ncol,lchnk), & ! ocean salinity (parts per thousands)
- switch_bubble, & ! bubble-mediated transfer: on or off
- ncol )
- end where
+ do i = 1,ncol
+ if (ocnfrac(i) >= 0.2_r8 .and. Csw_col(i) >= 0._r8) then
+ ! calculate flux only for ocean
+ oceanflux_kg_m2_s(i) = Flux_kg_m2_s( &
+ Csw_nM(m)%species, & ! name of species
+ state%q(i,pver,SpeciesID) * (28.97_r8/MW_species) * 1.0e+12_r8, & ! air concentration (ppt)
+ Csw_col(i), & ! sea water concentration (nM)
+ state%t(i,pver), & ! air temperature (K)
+ u10(i), & ! wind speed at 10m (m/s) <- should use this
+ state%ps(i) / 101325.0_r8, & ! surface pressure (atm)
+ sst(i), & ! sea surface temperautre (K)
+ salinity(i,lchnk), & ! ocean salinity (parts per thousands)
+ switch_bubble ) ! bubble-mediated transfer: on or off
+ end if
+ end do
! ===========================================================================
- ! Add the ocean flux to the other fluxes
+ ! Add the ocean flux to the other fluxes
! Make sure this ocean module is called after other surface emissions are set
! ===========================================================================
sflx(:ncol,SpeciesID) = sflx(:ncol,SpeciesID) + oceanflux_kg_m2_s(:ncol) * ocnfrac(:ncol)
@@ -355,10 +363,8 @@ subroutine ocean_emis_getflux(lchnk, ncol, state, u10, sst, ocnfrac, icefrac, sf
end subroutine ocean_emis_getflux
-
-!--------------------------------------------------------------------------------
-!--------------------------------------------------------------------------------
-
+ !--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
Subroutine CmpLibInitialization()
! =====================================================================================
! This is the lookup table for molecular weight, Vb, and Henry's law constant
@@ -377,7 +383,7 @@ Subroutine CmpLibInitialization()
GasList(2) = GasLib('C2H5OH', (/ 46.07_r8, 2.0_r8, 6.0_r8, 0.0_r8, 1.0_r8, 0.0_r8, 0.0_r8, &
0.0_r8, 0.0_r8, 0.0_r8, 0.0_r8, 0.0_r8, 0.0_r8, 0.0_r8, 190.0_r8, 6500.0_r8 /))
GasList(3) = GasLib('CH2O', (/ 30.03_r8, 1.0_r8, 2.0_r8, 0.0_r8, 1.0_r8, 0.0_r8, 0.0_r8, &
- 0.0_r8, 0.0_r8, 0.0_r8, 1.0_r8, 0.0_r8, 0.0_r8, 0.0_r8, 3230.0_r8, 7100.0_r8 /))
+ 0.0_r8, 0.0_r8, 0.0_r8, 1.0_r8, 0.0_r8, 0.0_r8, 0.0_r8, 3230.0_r8, 7100.0_r8 /))
GasList(4) = GasLib('CH3CHO', (/ 44.05_r8, 2.0_r8, 4.0_r8, 0.0_r8, 1.0_r8, 0.0_r8, 0.0_r8, &
0.0_r8, 0.0_r8, 0.0_r8, 1.0_r8, 0.0_r8, 0.0_r8, 0.0_r8, 12.9_r8, 5890.0_r8/))
GasList(5) = GasLib('PROPANAL', (/ 58.08_r8, 3.0_r8, 6.0_r8, 0.0_r8, 1.0_r8, 0.0_r8, 0.0_r8, &
@@ -409,10 +415,12 @@ Subroutine CmpLibInitialization()
! --------------------------------------------------------------------------------
End Subroutine CmpLibInitialization
+ !--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
Subroutine SaltLibInitialization()
! ================================================================================
- ! This is the lookup table for common solutes in seawater and the parameters to
- ! calculate the dynamic viscosity of seawater.
+ ! This is the lookup table for common solutes in seawater and the parameters to
+ ! calculate the dynamic viscosity of seawater.
! You may add other solutes or change the mass fractions.
! --------------------------------------------------------------------------------
! Col 1: mass fraction of solute
@@ -431,6 +439,8 @@ Subroutine SaltLibInitialization()
! ---------------------------------------------
End Subroutine SaltLibInitialization
+ !--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
Function SpeciesIndex(SpeciesName)
! ==============================================
! This function is to look for the species index
@@ -439,7 +449,7 @@ Function SpeciesIndex(SpeciesName)
Character(Len=16) :: SpeciesName
SpeciesIndex = -1 ! return -1 if species is not found
-
+
Do i = 1, HowManyMolecules
If (trim(SpeciesName) == trim(GasList(i)%CmpdName)) Then
SpeciesIndex = i
@@ -448,13 +458,15 @@ Function SpeciesIndex(SpeciesName)
End Do
End Function SpeciesIndex
- Function Flux_kg_m2_s(SpeciesName,Cgas_ppt,Cwater_nM,T_air_K,u10_m_s,P_atm,T_water_K,&
- Salinity_PartsPerThousand,switch_bubble,ncol)
+ !--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
+ Real(r8) Function Flux_kg_m2_s(SpeciesName,Cgas_ppt,Cwater_nM,T_air_K,u10_m_s,P_atm,T_water_K,&
+ Salinity_PartsPerThousand,switch_bubble)
! ===========================================================================
! This is the main module function. Input variables:
! ---------------------------------------------------------------------------
! - SpeciesName: name of species
- ! - Cgas_ppt: mixing ratio (parts per trillion) of trace gas of interest
+ ! - Cgas_ppt: mixing ratio (parts per trillion) of trace gas of interest
! in the gas-phase (lowest modeling layer)
! - Cwater_nM: concentration of trace gas of interest in the surface ocean
! - T_air_K: temperature in the lowest modeling layer
@@ -463,52 +475,51 @@ Function Flux_kg_m2_s(SpeciesName,Cgas_ppt,Cwater_nM,T_air_K,u10_m_s,P_atm,T_wat
! - T_water_K: sea surface temperature
! - Salinity_PartsPerThousand: surface ocean salinity
! - switch_bubble: bubble-mediated transfer switch
- ! All must be 1D arrays with same dimension(ncol, so CESM-compatible)
! ===========================================================================
- Integer :: ncol, SpeciesID
- Character(16) :: SpeciesName
- Real(r8), Dimension(ncol) :: Flux_kg_m2_s
- Real(r8), Dimension(ncol) :: Cgas_ppt, Cwater_nM, T_air_K, u10_m_s, P_atm, T_water_K, Salinity_PartsPerThousand
- Real(r8), Dimension(ncol) :: H_gas_over_liquid_dimless, kt_m_s
- Logical :: switch_bubble
+ Character(16),intent(in) :: SpeciesName
+ Real(r8),intent(in) :: Cgas_ppt, Cwater_nM, T_air_K, u10_m_s, P_atm, T_water_K, Salinity_PartsPerThousand
+ Logical ,intent(in) :: switch_bubble
- where(Salinity_PartsPerThousand .lt. 0.0_r8) Salinity_PartsPerThousand = 33.0_r8
+ Integer :: SpeciesID
+ Real(r8) :: H_gas_over_liquid_dimless, kt_m_s
- SpeciesID = SpeciesIndex(SpeciesName)
- H_gas_over_liquid_dimless = 1.0_r8/(Henry_M_atm(SpeciesID,T_water_K,Salinity_PartsPerThousand,ncol)*&
+ SpeciesID = SpeciesIndex(SpeciesName)
+ H_gas_over_liquid_dimless = 1.0_r8/(Henry_M_atm(SpeciesID,T_water_K,Salinity_PartsPerThousand)*&
0.082_r8*T_water_K)
If (switch_bubble) then
! --------------------------------------------------------
! k_water parameterization with bubble-induced enhancement
! --------------------------------------------------------
kt_m_s = (1.0_r8/k_water_m_s_bubble(SpeciesID, T_water_K, Salinity_PartsPerThousand, &
- u10_m_s, Cgas_ppt, P_atm, T_air_K, ncol) &
- + 1.0_r8/k_air_m_s(SpeciesID, u10_m_s, T_air_K, P_atm, ncol)&
+ u10_m_s, Cgas_ppt, P_atm, T_air_K) &
+ + 1.0_r8/k_air_m_s(SpeciesID, u10_m_s, T_air_K, P_atm)&
/H_gas_over_liquid_dimless)**(-1.0_r8)
else
! ------------------------------------------------
! Original k_water parameterization, scaled to CO2
! ------------------------------------------------
- kt_m_s = (1.0_r8/k_water_m_s(SpeciesID, T_water_K, Salinity_PartsPerThousand, u10_m_s, ncol) &
- + 1.0_r8/k_air_m_s(SpeciesID, u10_m_s, T_air_K, P_atm, ncol)/H_gas_over_liquid_dimless)**(-1.0_r8)
+ kt_m_s = (1.0_r8/k_water_m_s(SpeciesID, T_water_K, Salinity_PartsPerThousand, u10_m_s) &
+ + 1.0_r8/k_air_m_s(SpeciesID, u10_m_s, T_air_K, P_atm)/H_gas_over_liquid_dimless)**(-1.0_r8)
endif
Flux_kg_m2_s = kt_m_s * (Cwater_nM*1E-9_r8*1000.0_r8 &
- Cgas_ppt*1E-12_r8*(101325.0_r8*P_atm)/8.314_r8/T_air_K/H_gas_over_liquid_dimless) & ! g/m2/s
* MolecularWeight(SpeciesIndex(SpeciesName)) / 1000.0_r8 ! convert to kg/m2/s
End Function Flux_kg_m2_s
-
- Function k_air_m_s(SpeciesIndex, u10_m_s, T_air_K, P_atm, ncol)
+ !--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
+ Real(r8) Function k_air_m_s(SpeciesIndex, u10_m_s, T_air_K, P_atm)
use shr_const_mod, only: vonKarman=>SHR_CONST_KARMAN
! =============================================================================
- ! Air-side transfer velocity. Slightly modified NOAA COARE (Fairall et al 2003;
- ! Feffery et al 2010), as recommended by Johnson Ocean Sci. 2010.
+ ! Air-side transfer velocity. Slightly modified NOAA COARE (Fairall et al 2003;
+ ! Feffery et al 2010), as recommended by Johnson Ocean Sci. 2010.
! Dynamic viscosity of air: Tsilingiris 2008
! =============================================================================
- Integer :: ncol, SpeciesIndex
- Real(r8), Dimension(ncol) :: k_air_m_s
- Real(r8), Dimension(ncol) :: u10_m_s, T_air_K, P_atm, ustar_m_s, DragCoeff
- Real(r8), Dimension(ncol) :: DynamicViscosityAir_kg_m_s, DensityAir_kg_m3, DiffusivityInAir, SchmidtNumberInAir
+ Integer ,intent(in) :: SpeciesIndex
+ Real(r8),intent(in) :: u10_m_s, T_air_K, P_atm
+
+ Real(r8) :: ustar_m_s, DragCoeff
+ Real(r8) :: DynamicViscosityAir_kg_m_s, DensityAir_kg_m3, DiffusivityInAir, SchmidtNumberInAir
! WSY: If local friction velocity is available from the model, might as well use that?
ustar_m_s = u10_m_s * sqrt(6.1E-4_r8 + 6.3E-5_r8 * u10_m_s)
@@ -516,53 +527,53 @@ Function k_air_m_s(SpeciesIndex, u10_m_s, T_air_K, P_atm, ncol)
DynamicViscosityAir_kg_m_s = 1.715747771E-5_r8 + 4.722402075E-8_r8 * (T_air_K-273.15_r8) &
- 3.663027156E-10_r8 * ((T_air_K-273.15_r8)**2.0_r8) &
+ 1.873236686E-12_r8 * ((T_air_K-273.15_r8)**3.0_r8) &
- - 8.050218737E-14_r8 * ((T_air_K-273.15_r8)**4.0_r8)
+ - 8.050218737E-14_r8 * ((T_air_K-273.15_r8)**4.0_r8)
DensityAir_kg_m3 = 1.293393662_r8 - 5.538444326e-3_r8 * (T_air_K-273.15_r8) &
+ 3.860201577e-5_r8 * (T_air_K-273.15_r8)**2.0_r8 &
- 5.2536065e-7_r8 * (T_air_K-273.15_r8)**3.0_r8
- DiffusivityInAir = DiffusivityInAir_cm2_s(SpeciesIndex, T_air_K, P_atm, ncol)
- SchmidtNumberInAir = DynamicViscosityAir_kg_m_s / DensityAir_kg_m3 / (DiffusivityInAir/10000.0_r8)
+ DiffusivityInAir = DiffusivityInAir_cm2_s(SpeciesIndex, T_air_K, P_atm)
+ SchmidtNumberInAir = DynamicViscosityAir_kg_m_s / DensityAir_kg_m3 / (DiffusivityInAir/10000.0_r8)
k_air_m_s = 1E-3_r8 + ustar_m_s / (13.3_r8*(SchmidtNumberInAir**0.5_r8)+(DragCoeff**(-0.5_r8))-&
5.0_r8+log(SchmidtNumberInAir)/2.0_r8/vonKarman)
End Function k_air_m_s
-
-
-
- Function k_water_m_s(SpeciesIndex, T_water_K, Salinity_PartsPerThousand, u10_m_s, ncol)
+ !--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
+ Real(r8) Function k_water_m_s(SpeciesIndex, T_water_K, Salinity_PartsPerThousand, u10_m_s)
! ================================================================================
! Water-side transfer velocity. Ref: Nightingale et al (2000). Salinity considered
! ================================================================================
- Integer :: ncol, SpeciesIndex
- Real(r8), Dimension(ncol) :: k_water_m_s
- Real(r8), Dimension(ncol) :: T_water_K, Salinity_PartsPerThousand, u10_m_s
- Real(r8), Dimension(ncol) :: DiffusivityInWater, SchmidtNumberInWater
- Real(r8) :: SchmidtNumberInWater_CO2ref
+ Integer ,intent(in) :: SpeciesIndex
+ Real(r8),intent(in) :: T_water_K, Salinity_PartsPerThousand, u10_m_s
+
+ Real(r8) :: DiffusivityInWater, SchmidtNumberInWater
+ Real(r8) :: SchmidtNumberInWater_CO2ref
+
SchmidtNumberInWater_CO2ref = 660.0_r8 ! this is the Schmidt number of CO2 at 20 degC in fresh water
- DiffusivityInWater = DiffusivityInWater_cm2_s(SpeciesIndex, T_water_K, Salinity_PartsPerThousand, ncol)
- SchmidtNumberInWater = DynamicViscosityWater_g_m_s(T_water_K, Salinity_PartsPerThousand, ncol) / 1000.0_r8 &
- / DensityWater_kg_m3(T_water_K,Salinity_PartsPerThousand,ncol)/(DiffusivityInWater/10000.0_r8)
+ DiffusivityInWater = DiffusivityInWater_cm2_s(SpeciesIndex, T_water_K, Salinity_PartsPerThousand)
+ SchmidtNumberInWater = DynamicViscosityWater_g_m_s(T_water_K, Salinity_PartsPerThousand) / 1000.0_r8 &
+ / DensityWater_kg_m3(T_water_K,Salinity_PartsPerThousand)/(DiffusivityInWater/10000.0_r8)
k_water_m_s = ((0.222_r8*(u10_m_s**2.0_r8)+0.333_r8*u10_m_s)*&
((SchmidtNumberInWater/SchmidtNumberInWater_CO2ref)**(-0.5_r8)))/360000.0_r8
End Function k_water_m_s
-
-
-
- Function k_water_m_s_bubble(SpeciesIndex, T_water_K, Salinity_PartsPerThousand, u10_m_s, Cgas_ppt, P_atm, T_air_K, ncol)
+ !--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
+ Real(r8) Function k_water_m_s_bubble(SpeciesIndex, T_water_K, Salinity_PartsPerThousand, u10_m_s, Cgas_ppt, P_atm, T_air_K)
! ==============================================================
! Water-side transfer velocity. Ref: Asher and Wanninkhof (1998).
! ==============================================================
- Integer :: ncol, SpeciesIndex
- Real(r8), Dimension(ncol) :: k_water_m_s_bubble
- Real(r8), Dimension(ncol) :: T_water_K, Salinity_PartsPerThousand, u10_m_s, Cgas_ppt, P_atm, T_air_K
- Real(r8), Dimension(ncol) :: DiffusivityInWater, SchmidtNumberInWater
- Real(r8), Dimension(ncol) :: FracCoverage_WhiteCaps, OstwaldSolubilityCoefficient
- DiffusivityInWater = DiffusivityInWater_cm2_s(SpeciesIndex, T_water_K, Salinity_PartsPerThousand, ncol)
- SchmidtNumberInWater = DynamicViscosityWater_g_m_s(T_water_K, Salinity_PartsPerThousand, ncol) / 1000.0_r8 &
- / DensityWater_kg_m3(T_water_K,Salinity_PartsPerThousand,ncol)/(DiffusivityInWater/10000.0_r8)
- FracCoverage_WhiteCaps = 2.56e-6_r8 * (u10_m_s - 1.77_r8)**3.0_r8
- OstwaldSolubilityCoefficient = Henry_M_atm(SpeciesIndex,T_water_K,Salinity_PartsPerThousand,ncol) ! just Henry's law (M/atm)
+ Integer, intent(in) :: SpeciesIndex
+ Real(r8),intent(in) :: T_water_K, Salinity_PartsPerThousand, u10_m_s, Cgas_ppt, P_atm, T_air_K
+
+ Real(r8) :: DiffusivityInWater, SchmidtNumberInWater
+ Real(r8) :: FracCoverage_WhiteCaps, OstwaldSolubilityCoefficient
+
+ DiffusivityInWater = DiffusivityInWater_cm2_s(SpeciesIndex, T_water_K, Salinity_PartsPerThousand)
+ SchmidtNumberInWater = DynamicViscosityWater_g_m_s(T_water_K, Salinity_PartsPerThousand) / 1000.0_r8 &
+ / DensityWater_kg_m3(T_water_K,Salinity_PartsPerThousand)/(DiffusivityInWater/10000.0_r8)
+ FracCoverage_WhiteCaps = 2.56e-6_r8 * (u10_m_s - 1.77_r8)**3.0_r8
+ OstwaldSolubilityCoefficient = Henry_M_atm(SpeciesIndex,T_water_K,Salinity_PartsPerThousand) ! just Henry's law (M/atm)
OstwaldSolubilityCoefficient = OstwaldSolubilityCoefficient * (Cgas_ppt*1.0E-12_r8*P_atm) ! mol / L
OstwaldSolubilityCoefficient = OstwaldSolubilityCoefficient * 0.082_r8 * T_air_K / P_atm ! L / L
k_water_m_s_bubble = ((47.0_r8*u10_m_s + FracCoverage_WhiteCaps*(115200.0_r8 - 47.0_r8* u10_m_s)) &
@@ -570,40 +581,46 @@ Function k_water_m_s_bubble(SpeciesIndex, T_water_K, Salinity_PartsPerThousand,
+ FracCoverage_WhiteCaps * (-37.0_r8/OstwaldSolubilityCoefficient &
+ 6120.0_r8*(OstwaldSolubilityCoefficient**(-0.37_r8)) *(SchmidtNumberInWater**(-0.18_r8)))) &
* 2.8e-6_r8
- End Function k_water_m_s_bubble
-
-
+ End Function k_water_m_s_bubble
- Function DiffusivityInAir_cm2_s(SpeciesIndex, T_air_K, P_atm, ncol)
+ !--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
+ Real(r8) Function DiffusivityInAir_cm2_s(SpeciesIndex, T_air_K, P_atm)
! ============================
! Ref: Johnson Ocean Sci. 2010
! ============================
- Integer :: ncol, SpeciesIndex
- Real(r8), Dimension(ncol) :: DiffusivityInAir_cm2_s, T_air_K, P_atm
+ Integer ,intent(in) :: SpeciesIndex
+ Real(r8),intent(in) :: T_air_K, P_atm
+
Real(r8), parameter :: MW_air = 28.97_r8 ! molecular weight for air
Real(r8), parameter :: Va = 20.1_r8 ! molar volume for air
Real(r8) :: Vb, MW_species
+
Vb = LiquidMolarVolume_cm3_mol(SpeciesIndex)
MW_species = MolecularWeight(SpeciesIndex)
DiffusivityInAir_cm2_s = 0.001_r8 * (T_air_K**1.75_r8) & ! oh f* me
* (((MW_air + MW_species)/(MW_air*MW_species))**0.5_r8) &
/ ((P_atm*(Va**(1.0_r8/3.0_r8)+Vb**(1.0_r8/3.0_r8)))**2.0_r8)
- End Function DiffusivityInAir_cm2_s
-
+ End Function DiffusivityInAir_cm2_s
- Function DiffusivityInWater_cm2_s(SpeciesIndex, T_water_K, Salinity_PartsPerThousand, ncol)
+ !--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
+ Real(r8) Function DiffusivityInWater_cm2_s(SpeciesIndex, T_water_K, Salinity_PartsPerThousand)
! =================================================
! Ref: Johnson Ocean Sci. 2010. Salinity considered
! =================================================
- Integer :: ncol, SpeciesIndex
- Real(r8), Dimension(ncol) :: DiffusivityInWater_cm2_s, DynamicViscosityWater, T_water_K, Salinity_PartsPerThousand
+ Integer, intent(in) :: SpeciesIndex
+ Real(r8),intent(in) :: T_water_K, Salinity_PartsPerThousand
+
Real(r8), parameter :: AssociationFactor = 2.6_r8 ! ... for water
- Real(r8) :: Vb, MW_species
+ Real(r8) :: DynamicViscosityWater, Vb, MW_species
+
Vb = LiquidMolarVolume_cm3_mol(SpeciesIndex)
MW_species = MolecularWeight(SpeciesIndex)
- DynamicViscosityWater = DynamicViscosityWater_g_m_s(T_water_K, Salinity_PartsPerThousand, ncol)
+
+ DynamicViscosityWater = DynamicViscosityWater_g_m_s(T_water_K, Salinity_PartsPerThousand)
! -------------------------------------------------
! Wilke and Chang 1955: this seems to be a bit high
! -------------------------------------------------
@@ -617,47 +634,51 @@ Function DiffusivityInWater_cm2_s(SpeciesIndex, T_water_K, Salinity_PartsPerThou
End Function DiffusivityInWater_cm2_s
-
- Function DynamicViscosityWater_g_m_s(T_water_K, Salinity_PartsPerThousand, ncol)
+ !--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
+ Real(r8) Function DynamicViscosityWater_g_m_s(T_water_K, Salinity_PartsPerThousand)
! =================================================
! Ref: Johnson Ocean Sci. 2010. Salinity considered
! =================================================
- Integer :: ncol
- Real(r8), Dimension(ncol) :: DynamicViscosityWater_g_m_s, T_water_K, Salinity_PartsPerThousand
- Real(r8), Dimension(ncol) :: MassFrac_water, DynamicViscosityPureWater_g_m_s, SaltViscosity, sum_w_ln_SaltViscosity
- Integer :: j, n
+ Real(r8),intent(in) :: T_water_K, Salinity_PartsPerThousand
+
+ Real(r8) :: MassFrac_water, DynamicViscosityPureWater_g_m_s, SaltViscosity, sum_w_ln_SaltViscosity
+ Integer :: n
+
sum_w_ln_SaltViscosity = 0.0_r8
MassFrac_water = 1.0_r8 - Salinity_PartsPerThousand / 1000.0_r8
DynamicViscosityPureWater_g_m_s = ((T_water_K-273.15_r8)+246.0_r8) &
- / (0.05594_r8*(T_water_K-273.15_r8)**2.0_r8+5.2842_r8*(T_water_K-273.15_r8)+137.37_r8)
- Do j = 1, ncol
- If (Salinity_PartsPerThousand(j) == 0.0_r8) Then ! pure water
- DynamicViscosityWater_g_m_s(j) = DynamicViscosityPureWater_g_m_s(j)
+ / (0.05594_r8*(T_water_K-273.15_r8)**2.0_r8+5.2842_r8*(T_water_K-273.15_r8)+137.37_r8)
+
+ If (Salinity_PartsPerThousand == 0.0_r8) Then ! pure water
+ DynamicViscosityWater_g_m_s = DynamicViscosityPureWater_g_m_s
Else ! salty water
Do n = 1, HowManySalts
- SaltViscosity(j) = exp((SaltList(n)%SaltProperties(2) * &
- (Salinity_PartsPerThousand(j)/1000.0_r8)**SaltList(n)%SaltProperties(3) &
+ SaltViscosity = exp((SaltList(n)%SaltProperties(2) * &
+ (Salinity_PartsPerThousand/1000.0_r8)**SaltList(n)%SaltProperties(3) &
+ SaltList(n)%SaltProperties(4)) &
- / (SaltList(n)%SaltProperties(5)*(T_water_K(j)-273.15_r8) + 1.0_r8)) &
- / (SaltList(n)%SaltProperties(6) * (Salinity_PartsPerThousand(j) / &
+ / (SaltList(n)%SaltProperties(5)*(T_water_K-273.15_r8) + 1.0_r8)) &
+ / (SaltList(n)%SaltProperties(6) * (Salinity_PartsPerThousand / &
1000.0_r8)**SaltList(n)%SaltProperties(7) + 1.0_r8)
- sum_w_ln_SaltViscosity(j) = sum_w_ln_SaltViscosity(j) + (Salinity_PartsPerThousand(j)/1000.0_r8) &
- * SaltList(n)%SaltProperties(1) * log(SaltViscosity(j))
+ sum_w_ln_SaltViscosity = sum_w_ln_SaltViscosity + (Salinity_PartsPerThousand/1000.0_r8) &
+ * SaltList(n)%SaltProperties(1) * log(SaltViscosity)
End Do
- DynamicViscosityWater_g_m_s(j) = exp(MassFrac_water(j) &
- * log(DynamicViscosityPureWater_g_m_s(j)) + sum_w_ln_SaltViscosity(j))
+ DynamicViscosityWater_g_m_s = exp(MassFrac_water &
+ * log(DynamicViscosityPureWater_g_m_s) + sum_w_ln_SaltViscosity)
Endif
- End Do
- End Function DynamicViscosityWater_g_m_s
+ End Function DynamicViscosityWater_g_m_s
- Function DensityWater_kg_m3(T_water_K, Salinity_PartsPerThousand, ncol)
+ !--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
+ Real(r8) Function DensityWater_kg_m3(T_water_K, Salinity_PartsPerThousand)
! ====================================================
! Ref: Millero and Poisson (1981). Salinity considered
! ====================================================
- Integer :: ncol
- Real(r8), Dimension(ncol) :: DensityWater_kg_m3, T_water_K, Salinity_PartsPerThousand
- Real(r8), Dimension(ncol) :: DensityPureWater_kg_m3, FactorA, FactorB, FactorC
+ Real(r8), intent(in) :: T_water_K, Salinity_PartsPerThousand
+
+ Real(r8) :: DensityPureWater_kg_m3, FactorA, FactorB, FactorC
+
DensityPureWater_kg_m3 = 999.842594_r8 + 0.06793952_r8*(T_water_K-273.15_r8) &
- 0.00909529_r8*((T_water_K-273.15_r8)**2.0_r8) &
+ 0.0001001685_r8*((T_water_K-273.15_r8)**3.0_r8) &
@@ -669,41 +690,46 @@ Function DensityWater_kg_m3(T_water_K, Salinity_PartsPerThousand, ncol)
FactorC = 0.00048314_r8
DensityWater_kg_m3 = DensityPureWater_kg_m3 + FactorA*Salinity_PartsPerThousand &
+ FactorB*(Salinity_PartsPerThousand**(2.0_r8/3.0_r8)) + FactorC*Salinity_PartsPerThousand
- End Function DensityWater_kg_m3
+ End Function DensityWater_kg_m3
- Function Henry_M_atm(SpeciesIndex, T_water_K, Salinity_PartsPerThousand, ncol)
+ !--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
+ Real(r8) Function Henry_M_atm(SpeciesIndex, T_water_K, Salinity_PartsPerThousand)
! =========================================================================================
! Ref: Sander compilation 2015. Salt-in or salt-out estimated based on Setschenow constants
! =========================================================================================
- Integer :: ncol, j
- Integer :: SpeciesIndex
- Real(r8), Dimension(ncol) :: Henry_M_atm, T_water_K, Salinity_PartsPerThousand
- Real(r8), Dimension(ncol) :: Heff_M_atm_PureWater, Setschenow, Heff_M_atm_SaltyWater
+ Integer, intent(in) :: SpeciesIndex
+ Real(r8), intent(in) :: T_water_K, Salinity_PartsPerThousand
+
+ Real(r8) :: Heff_M_atm_PureWater, Setschenow, Heff_M_atm_SaltyWater
+
Heff_M_atm_PureWater = GasList(SpeciesIndex)%CmpdProperties(15) * &
exp(GasList(SpeciesIndex)%CmpdProperties(16) * (1.0_r8/T_water_K - 1.0_r8/298.0_r8))
- Do j = 1, ncol
- If (Salinity_PartsPerThousand(j)==0.0_r8) Then
- Henry_M_atm(j) = Heff_M_atm_PureWater(j)
- Else
- Setschenow(j) = log(LiquidMolarVolume_cm3_mol(SpeciesIndex)) * &
- (7.33532E-4_r8 + 3.39615E-5_r8 * log(Heff_M_atm_PureWater(j)) &
- - 2.40888E-6_r8 * ((log(Heff_M_atm_PureWater(j)))**2.0_r8) &
- + 1.57114E-7_r8 * ((log(Heff_M_atm_PureWater(j)))**3.0_r8))
- Heff_M_atm_SaltyWater(j) = Heff_M_atm_PureWater(j) * 10.0_r8**(Setschenow(j)*Salinity_PartsPerThousand(j))
- Henry_M_atm(j) = Heff_M_atm_SaltyWater(j)
- Endif
- End Do
- End Function Henry_M_atm
+ If (Salinity_PartsPerThousand==0.0_r8) Then
+ Henry_M_atm = Heff_M_atm_PureWater
+ Else
+ Setschenow = log(LiquidMolarVolume_cm3_mol(SpeciesIndex)) * &
+ (7.33532E-4_r8 + 3.39615E-5_r8 * log(Heff_M_atm_PureWater) &
+ - 2.40888E-6_r8 * ((log(Heff_M_atm_PureWater))**2.0_r8) &
+ + 1.57114E-7_r8 * ((log(Heff_M_atm_PureWater))**3.0_r8))
+ Heff_M_atm_SaltyWater = Heff_M_atm_PureWater * 10.0_r8**(Setschenow*Salinity_PartsPerThousand)
+ Henry_M_atm = Heff_M_atm_SaltyWater
+ Endif
+
+ End Function Henry_M_atm
+ !--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
Function MolecularWeight(SpeciesIndex)
Real(r8) :: MolecularWeight
Integer :: SpeciesIndex
MolecularWeight = GasList(SpeciesIndex)%CmpdProperties(1)
End Function MolecularWeight
-
+ !--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
Function LiquidMolarVolume_cm3_mol(SpeciesIndex)
! ===========================================================================
! If no measurements available, i.e. GasList(SpeciesIndex)%CmpdProperties(14)
@@ -712,7 +738,7 @@ Function LiquidMolarVolume_cm3_mol(SpeciesIndex)
Real(r8) :: LiquidMolarVolume_cm3_mol
Integer :: SpeciesIndex
- If (GasList(SpeciesIndex)%CmpdProperties(14)/=0.0_r8) Then
+ If (GasList(SpeciesIndex)%CmpdProperties(14)/=0.0_r8) Then
LiquidMolarVolume_cm3_mol = GasList(SpeciesIndex)%CmpdProperties(14)
Else
LiquidMolarVolume_cm3_mol = 7.0_r8*GasList(SpeciesIndex)%CmpdProperties(2) ! C
@@ -731,18 +757,20 @@ Function LiquidMolarVolume_cm3_mol(SpeciesIndex)
End Function LiquidMolarVolume_cm3_mol
+ !--------------------------------------------------------------------------------
+ !--------------------------------------------------------------------------------
subroutine cseawater_ini()
- use mo_chem_utls, only : get_spc_ndx
- use tracer_data, only : trcdata_init
- use cam_pio_utils, only : cam_pio_openfile
+ use mo_chem_utls, only : get_spc_ndx
+ use tracer_data, only : trcdata_init
+ use cam_pio_utils, only : cam_pio_openfile
use pio, only : pio_inquire, pio_nowrite, pio_closefile, pio_inq_varndims
use pio, only : pio_inq_varname, file_desc_t, pio_get_att, PIO_NOERR, PIO_GLOBAL
- use pio, only : pio_seterrorhandling, PIO_BCAST_ERROR
- use string_utils, only : GLC
+ use pio, only : pio_seterrorhandling, PIO_BCAST_ERROR
+ use string_utils, only : GLC
integer :: i, j, l, m, n, nn, astat, vid, ierr, nvars, isec
- integer :: indx(gas_pcnst)
+ integer :: indx(gas_pcnst)
type(file_desc_t) :: ncid
character(len=16) :: csw_species(gas_pcnst)
character(len=256) :: csw_filenam(gas_pcnst)
@@ -766,7 +794,7 @@ subroutine cseawater_ini()
character(len=*), parameter :: subname = 'cseawater_ini'
- ! ========================================================
+ ! ========================================================
! Read sea water concentration specifier from the namelist
! ========================================================
@@ -827,7 +855,7 @@ subroutine cseawater_ini()
! -------------------------------------------
! Setup the seawater concentration type array
! -------------------------------------------
- do m=1,n_Csw_files
+ do m=1,n_Csw_files
Csw_nM(m)%spc_ndx = csw_indexes(indx(m))
Csw_nM(m)%units = 'nM'
Csw_nM(m)%species = csw_species(indx(m))
@@ -898,9 +926,9 @@ subroutine cseawater_ini()
deallocate(vndims)
! Global attribute 'input_method' overrides the srf_emis_type namelist setting on
- ! a file-by-file basis. If the emis file does not contain the 'input_method'
+ ! a file-by-file basis. If the emis file does not contain the 'input_method'
! attribute then the srf_emis_type namelist setting is used.
- ierr = pio_get_att(ncid, PIO_GLOBAL, 'input_method', file_interp_type)
+ ierr = pio_get_att(ncid, PIO_GLOBAL, 'input_method', file_interp_type)
if ( ierr == PIO_NOERR) then
l = GLC(file_interp_type)
csw_time_type(1:l) = file_interp_type(1:l)
@@ -932,5 +960,4 @@ subroutine cseawater_ini()
end subroutine cseawater_ini
-
end module ocean_emis
diff --git a/src/chemistry/mozart/tracer_cnst.F90 b/src/chemistry/mozart/tracer_cnst.F90
index 803e3e1061..9c51b6cec8 100644
--- a/src/chemistry/mozart/tracer_cnst.F90
+++ b/src/chemistry/mozart/tracer_cnst.F90
@@ -13,7 +13,7 @@ module tracer_cnst
implicit none
private ! all unless made public
- save
+ save
public :: tracer_cnst_init
public :: num_tracer_cnst
@@ -94,7 +94,7 @@ subroutine tracer_cnst_init()
call addfld(trim(fields(i)%fldnam), (/ 'lev' /), &
'I','mol/mol', 'prescribed tracer constituent' )
- enddo
+ enddo
allocate(data_q(pcols,pver,num_tracer_cnst,begchunk:endchunk), stat=istat)
call handle_err(istat, 'tracer_cnst_init: ERROR allocating data_q')
@@ -169,7 +169,7 @@ subroutine tracer_cnst_defaultopts( &
tracer_cnst_cycle_yr_out, &
tracer_cnst_fixed_ymd_out,&
tracer_cnst_fixed_tod_out &
- )
+ )
implicit none
@@ -231,7 +231,7 @@ subroutine tracer_cnst_adv( pbuf2d, state )
implicit none
- type(physics_state), intent(in):: state(begchunk:endchunk)
+ type(physics_state), intent(in):: state(begchunk:endchunk)
type(physics_buffer_desc), pointer :: pbuf2d(:,:)
integer :: i,ind,c,ncol
@@ -311,12 +311,13 @@ subroutine get_cnst_data_ptr(name, state, q, pbuf)
integer :: lchnk
integer :: ncol
integer :: inv_id, idx
+ character(len=80) :: error_str
lchnk = state%lchnk
ncol = state%ncol
! make sure the requested constituent can be provided
- inv_id = get_inv_ndx(name)
+ inv_id = get_inv_ndx(name)
if (.not. inv_id > 0) then
if (masterproc) then
write(iulog,*) 'get_cnst_data_ptr: '//name//' is not a prescribed tracer constituent'
@@ -326,6 +327,13 @@ subroutine get_cnst_data_ptr(name, state, q, pbuf)
call get_fld_ndx( fields, name, idx )
+ if (idx<1) then
+ write(error_str,*) 'get_cnst_data_ptr: ',trim(name),' not found ... idx : ',idx
+ if (masterproc) then
+ write(iulog,*) error_str
+ end if
+ call endrun(error_str)
+ end if
call get_fld_data( fields, name, data_q(:,:,idx,lchnk), ncol, lchnk, pbuf )
data_q(:ncol,:,idx,lchnk) = data_q(:ncol,:,idx,lchnk)*fix_mass(inv_id)/mwdry ! vmr->mmr
diff --git a/src/chemistry/pp_ghg_mam4/chem_mech.doc b/src/chemistry/pp_ghg_mam4/chem_mech.doc
new file mode 100644
index 0000000000..5c976202f5
--- /dev/null
+++ b/src/chemistry/pp_ghg_mam4/chem_mech.doc
@@ -0,0 +1,161 @@
+
+
+ Solution species
+ ( 1) bc_a1 (C)
+ ( 2) bc_a4 (C)
+ ( 3) CFC11 (CFCl3)
+ ( 4) CFC12 (CF2Cl2)
+ ( 5) CH4
+ ( 6) CO2
+ ( 7) DMS (CH3SCH3)
+ ( 8) dst_a1 (AlSiO5)
+ ( 9) dst_a2 (AlSiO5)
+ ( 10) dst_a3 (AlSiO5)
+ ( 11) H2O2
+ ( 12) H2SO4
+ ( 13) N2O
+ ( 14) ncl_a1 (NaCl)
+ ( 15) ncl_a2 (NaCl)
+ ( 16) ncl_a3 (NaCl)
+ ( 17) num_a1 (H)
+ ( 18) num_a2 (H)
+ ( 19) num_a3 (H)
+ ( 20) num_a4 (H)
+ ( 21) pom_a1 (C)
+ ( 22) pom_a4 (C)
+ ( 23) SO2
+ ( 24) so4_a1 (NH4HSO4)
+ ( 25) so4_a2 (NH4HSO4)
+ ( 26) so4_a3 (NH4HSO4)
+ ( 27) soa_a1 (C)
+ ( 28) soa_a2 (C)
+ ( 29) SOAE (C)
+ ( 30) SOAG (C)
+ ( 31) H2O
+
+
+ Invariant species
+ ( 1) M
+ ( 2) O2
+ ( 3) N2
+ ( 4) HO2
+ ( 5) OH
+ ( 6) NO3
+ ( 7) O3
+ ( 8) HALONS
+
+
+ Column integrals
+ ( 1) O3 - 0.000E+00
+ ( 2) O2 - 0.000E+00
+
+Class List
+==========
+ Explicit
+ --------
+ ( 1) CO2
+
+ Implicit
+ --------
+ ( 1) bc_a1
+ ( 2) bc_a4
+ ( 3) CFC11
+ ( 4) CFC12
+ ( 5) CH4
+ ( 6) DMS
+ ( 7) dst_a1
+ ( 8) dst_a2
+ ( 9) dst_a3
+ ( 10) H2O2
+ ( 11) H2SO4
+ ( 12) N2O
+ ( 13) ncl_a1
+ ( 14) ncl_a2
+ ( 15) ncl_a3
+ ( 16) num_a1
+ ( 17) num_a2
+ ( 18) num_a3
+ ( 19) num_a4
+ ( 20) pom_a1
+ ( 21) pom_a4
+ ( 22) SO2
+ ( 23) so4_a1
+ ( 24) so4_a2
+ ( 25) so4_a3
+ ( 26) soa_a1
+ ( 27) soa_a2
+ ( 28) SOAE
+ ( 29) SOAG
+ ( 30) H2O
+
+ Photolysis
+ jh2o2 ( 1) H2O2 + hv -> 2*OH rate = ** User defined ** ( 1)
+ jsoa_a1 ( 2) soa_a1 + hv -> (No products) rate = ** User defined ** ( 2)
+ jsoa_a2 ( 3) soa_a2 + hv -> (No products) rate = ** User defined ** ( 3)
+
+ Reactions
+ lyman_alpha ( 1) H2O -> (No products) rate = ** User defined ** ( 4)
+ OH_H2O2 ( 2) OH + H2O2 -> H2O + HO2 rate = 1.80E-12 ( 5)
+ usr_HO2_HO2 ( 3) HO2 + HO2 -> H2O2 + O2 rate = ** User defined ** ( 6)
+ n2o_loss ( 4) N2O -> (No products) rate = ** User defined ** ( 7)
+ cfc11_loss ( 5) CFC11 -> (No products) rate = ** User defined ** ( 8)
+ cfc12_loss ( 6) CFC12 -> (No products) rate = ** User defined ** ( 9)
+ ch4_loss ( 7) CH4 -> 2*H2O rate = ** User defined ** ( 10)
+ DMS_NO3 ( 8) DMS + NO3 -> SO2 + {HNO3} rate = 1.90E-13*exp( 520./t) ( 11)
+ DMS_OHa ( 9) DMS + OH -> SO2 rate = 1.10E-11*exp( -280./t) ( 12)
+ SO2_OH_M ( 10) SO2 + OH + M -> H2SO4 troe : ko=2.90E-31*(300/t)**4.10 ( 13)
+ ki=1.70E-12*(300/t)**-0.20
+ f=0.60
+ usr_DMS_OH ( 11) DMS + OH -> 0.5*SO2 + 0.5*HO2 rate = ** User defined ** ( 14)
+ SOAE_tau ( 12) SOAE -> SOAG rate = 1.16E-05 ( 15)
+
+Extraneous prod/loss species
+ ( 1) bc_a1 (dataset)
+ ( 2) bc_a4 (dataset)
+ ( 3) H2O (dataset)
+ ( 4) num_a1 (dataset)
+ ( 5) num_a2 (dataset)
+ ( 6) num_a4 (dataset)
+ ( 7) pom_a1 (dataset)
+ ( 8) pom_a4 (dataset)
+ ( 9) SO2 (dataset)
+ (10) so4_a1 (dataset)
+ (11) so4_a2 (dataset)
+
+
+ Equation Report
+
+ d(bc_a1)/dt = 0
+ d(bc_a4)/dt = 0
+ d(CFC11)/dt = - r5*CFC11
+ d(CFC12)/dt = - r6*CFC12
+ d(CH4)/dt = - r7*CH4
+ d(CO2)/dt = 0
+ d(DMS)/dt = - r8*NO3*DMS - r9*OH*DMS - r11*OH*DMS
+ d(dst_a1)/dt = 0
+ d(dst_a2)/dt = 0
+ d(dst_a3)/dt = 0
+ d(H2O2)/dt = r3
+ - j1*H2O2 - r2*OH*H2O2
+ d(H2SO4)/dt = r10*OH*M*SO2
+ d(N2O)/dt = - r4*N2O
+ d(ncl_a1)/dt = 0
+ d(ncl_a2)/dt = 0
+ d(ncl_a3)/dt = 0
+ d(num_a1)/dt = 0
+ d(num_a2)/dt = 0
+ d(num_a3)/dt = 0
+ d(num_a4)/dt = 0
+ d(pom_a1)/dt = 0
+ d(pom_a4)/dt = 0
+ d(SO2)/dt = r8*NO3*DMS + r9*OH*DMS + .5*r11*OH*DMS
+ - r10*OH*M*SO2
+ d(so4_a1)/dt = 0
+ d(so4_a2)/dt = 0
+ d(so4_a3)/dt = 0
+ d(soa_a1)/dt = - j2*soa_a1
+ d(soa_a2)/dt = - j3*soa_a2
+ d(SOAE)/dt = - r12*SOAE
+ d(SOAG)/dt = r12*SOAE
+ d(H2O)/dt = r2*OH*H2O2 + 2*r7*CH4
+ - r1*H2O
diff --git a/src/chemistry/pp_ghg_mam4/chem_mech.in b/src/chemistry/pp_ghg_mam4/chem_mech.in
new file mode 100644
index 0000000000..2d0365a8a5
--- /dev/null
+++ b/src/chemistry/pp_ghg_mam4/chem_mech.in
@@ -0,0 +1,179 @@
+* Comments
+* User-given Tag Description: WACCM_SC_MAM4
+* Tag database identifier : MZ312_WACCM_SC_MAM4_20221214
+* Tag created by : lke
+* Tag created from branch : WACCM_SC_MAM4
+* Tag created on : 2022-12-14 15:17:17.723566-07
+* Comments for this tag follow:
+* lke : 2022-12-14 : Specified chemistry (SC) WACCM mechanism, with updated simple SOA.
+* fvitt : 2023-03-17 : Copied from waccm_sc_mam4 to ghg_mam4 and add CO2 for CAM7 prognostic GHGs
+
+ SPECIES
+
+ Solution
+ bc_a1 -> C,
+ bc_a4 -> C,
+ CFC11 -> CFCl3,
+ CFC12 -> CF2Cl2,
+ CH4,
+ CO2,
+ DMS -> CH3SCH3,
+ dst_a1 -> AlSiO5,
+ dst_a2 -> AlSiO5,
+ dst_a3 -> AlSiO5,
+ H2O2,
+ H2SO4,
+ N2O,
+ ncl_a1 -> NaCl,
+ ncl_a2 -> NaCl,
+ ncl_a3 -> NaCl,
+ num_a1 -> H,
+ num_a2 -> H,
+ num_a3 -> H,
+ num_a4 -> H,
+ pom_a1 -> C,
+ pom_a4 -> C,
+ SO2,
+ so4_a1 -> NH4HSO4,
+ so4_a2 -> NH4HSO4,
+ so4_a3 -> NH4HSO4,
+ soa_a1 -> C,
+ soa_a2 -> C,
+ SOAE -> C,
+ SOAG -> C,
+ H2O
+ End Solution
+
+
+ Fixed
+ M, O2, N2, HO2, OH, NO3, O3, HALONS->CFCl3
+ End Fixed
+
+ Col-int
+ O3 = 0.
+ O2 = 0.
+ End Col-int
+
+ Not-Transported
+
+ End Not-Transported
+
+ END Species
+
+
+ Solution classes
+ Explicit
+ CO2
+ End Explicit
+
+ Implicit
+ bc_a1
+ bc_a4
+ CFC11
+ CFC12
+ CH4
+ DMS
+ dst_a1
+ dst_a2
+ dst_a3
+ H2O2
+ H2SO4
+ N2O
+ ncl_a1
+ ncl_a2
+ ncl_a3
+ num_a1
+ num_a2
+ num_a3
+ num_a4
+ pom_a1
+ pom_a4
+ SO2
+ so4_a1
+ so4_a2
+ so4_a3
+ soa_a1
+ soa_a2
+ SOAE
+ SOAG
+ H2O
+ End Implicit
+
+ End Solution classes
+
+
+ CHEMISTRY
+ Photolysis
+*********************************
+*** odd-oxygen
+*********************************
+[jh2o2] H2O2 + hv -> 2*OH
+*********************************
+*** soa
+*********************************
+[jsoa_a1->,.0004*jno2] soa_a1 + hv ->
+[jsoa_a2->,.0004*jno2] soa_a2 + hv ->
+ End Photolysis
+
+ Reactions
+*********************************
+*** odd-hydrogen
+*********************************
+[lyman_alpha] H2O ->
+[OH_H2O2] OH + H2O2 -> H2O + HO2 ; 1.8e-12
+[usr_HO2_HO2] HO2 + HO2 -> H2O2 + O2
+*********************************
+*** odd-nitrogen
+*********************************
+[n2o_loss] N2O ->
+*********************************
+*** odd-chlorine
+*********************************
+[cfc11_loss] CFC11 ->
+[cfc12_loss] CFC12 ->
+*********************************
+*** C1
+*********************************
+[ch4_loss] CH4 -> 2*H2O
+*********************************
+*** Sulfur
+*********************************
+[DMS_NO3] DMS + NO3 -> SO2 + HNO3 ; 1.9e-13, 520
+[DMS_OHa] DMS + OH -> SO2 ; 1.1e-11, -280
+[SO2_OH_M] SO2 + OH + M -> H2SO4 ; 2.9e-31, 4.1, 1.7e-12, -0.2, 0.6
+[usr_DMS_OH] DMS + OH -> 0.5*SO2 + 0.5*HO2
+*********************************
+*** SOA
+*********************************
+[SOAE_tau] SOAE -> SOAG ; 1.157e-05
+ End Reactions
+
+ Ext Forcing
+ bc_a1 <- dataset
+ bc_a4 <- dataset
+ H2O <- dataset
+ num_a1 <- dataset
+ num_a2 <- dataset
+ num_a4 <- dataset
+ pom_a1 <- dataset
+ pom_a4 <- dataset
+ SO2 <- dataset
+ so4_a1 <- dataset
+ so4_a2 <- 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
diff --git a/src/chemistry/pp_ghg_mam4/chem_mods.F90 b/src/chemistry/pp_ghg_mam4/chem_mods.F90
new file mode 100644
index 0000000000..a6f3071ca0
--- /dev/null
+++ b/src/chemistry/pp_ghg_mam4/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 = 3, & ! number of photolysis reactions
+ rxntot = 15, & ! number of total reactions
+ gascnt = 12, & ! number of gas phase reactions
+ nabscol = 2, & ! number of absorbing column densities
+ gas_pcnst = 31, & ! number of "gas phase" species
+ nfs = 8, & ! number of "fixed" species
+ relcnt = 0, & ! number of relationship species
+ grpcnt = 0, & ! number of group members
+ nzcnt = 35, & ! number of non-zero matrix entries
+ extcnt = 11, & ! number of species with external forcing
+ clscnt1 = 1, & ! 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 = 15, &
+ 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_ghg_mam4/m_rxt_id.F90 b/src/chemistry/pp_ghg_mam4/m_rxt_id.F90
new file mode 100644
index 0000000000..2c6a0ed8db
--- /dev/null
+++ b/src/chemistry/pp_ghg_mam4/m_rxt_id.F90
@@ -0,0 +1,18 @@
+ module m_rxt_id
+ implicit none
+ integer, parameter :: rid_jh2o2 = 1
+ integer, parameter :: rid_jsoa_a1 = 2
+ integer, parameter :: rid_jsoa_a2 = 3
+ integer, parameter :: rid_lyman_alpha = 4
+ integer, parameter :: rid_OH_H2O2 = 5
+ integer, parameter :: rid_usr_HO2_HO2 = 6
+ integer, parameter :: rid_n2o_loss = 7
+ integer, parameter :: rid_cfc11_loss = 8
+ integer, parameter :: rid_cfc12_loss = 9
+ integer, parameter :: rid_ch4_loss = 10
+ integer, parameter :: rid_DMS_NO3 = 11
+ integer, parameter :: rid_DMS_OHa = 12
+ integer, parameter :: rid_SO2_OH_M = 13
+ integer, parameter :: rid_usr_DMS_OH = 14
+ integer, parameter :: rid_SOAE_tau = 15
+ end module m_rxt_id
diff --git a/src/chemistry/pp_ghg_mam4/m_spc_id.F90 b/src/chemistry/pp_ghg_mam4/m_spc_id.F90
new file mode 100644
index 0000000000..c4bfbe7ef3
--- /dev/null
+++ b/src/chemistry/pp_ghg_mam4/m_spc_id.F90
@@ -0,0 +1,34 @@
+ module m_spc_id
+ implicit none
+ integer, parameter :: id_bc_a1 = 1
+ integer, parameter :: id_bc_a4 = 2
+ integer, parameter :: id_CFC11 = 3
+ integer, parameter :: id_CFC12 = 4
+ integer, parameter :: id_CH4 = 5
+ integer, parameter :: id_CO2 = 6
+ integer, parameter :: id_DMS = 7
+ integer, parameter :: id_dst_a1 = 8
+ integer, parameter :: id_dst_a2 = 9
+ integer, parameter :: id_dst_a3 = 10
+ integer, parameter :: id_H2O2 = 11
+ integer, parameter :: id_H2SO4 = 12
+ integer, parameter :: id_N2O = 13
+ integer, parameter :: id_ncl_a1 = 14
+ integer, parameter :: id_ncl_a2 = 15
+ integer, parameter :: id_ncl_a3 = 16
+ integer, parameter :: id_num_a1 = 17
+ integer, parameter :: id_num_a2 = 18
+ integer, parameter :: id_num_a3 = 19
+ integer, parameter :: id_num_a4 = 20
+ integer, parameter :: id_pom_a1 = 21
+ integer, parameter :: id_pom_a4 = 22
+ integer, parameter :: id_SO2 = 23
+ integer, parameter :: id_so4_a1 = 24
+ integer, parameter :: id_so4_a2 = 25
+ integer, parameter :: id_so4_a3 = 26
+ integer, parameter :: id_soa_a1 = 27
+ integer, parameter :: id_soa_a2 = 28
+ integer, parameter :: id_SOAE = 29
+ integer, parameter :: id_SOAG = 30
+ integer, parameter :: id_H2O = 31
+ end module m_spc_id
diff --git a/src/chemistry/pp_ghg_mam4/mo_adjrxt.F90 b/src/chemistry/pp_ghg_mam4/mo_adjrxt.F90
new file mode 100644
index 0000000000..09ad314f66
--- /dev/null
+++ b/src/chemistry/pp_ghg_mam4/mo_adjrxt.F90
@@ -0,0 +1,28 @@
+ 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(:,:, 5) = rate(:,:, 5) * inv(:,:, 5)
+ rate(:,:, 11) = rate(:,:, 11) * inv(:,:, 6)
+ rate(:,:, 12) = rate(:,:, 12) * inv(:,:, 5)
+ rate(:,:, 14) = rate(:,:, 14) * inv(:,:, 5)
+ rate(:,:, 6) = rate(:,:, 6) * inv(:,:, 4) * inv(:,:, 4) * im(:,:)
+ rate(:,:, 13) = rate(:,:, 13) * inv(:,:, 5) * inv(:,:, 1)
+ end subroutine adjrxt
+ end module mo_adjrxt
diff --git a/src/chemistry/pp_ghg_mam4/mo_exp_sol.F90 b/src/chemistry/pp_ghg_mam4/mo_exp_sol.F90
new file mode 100644
index 0000000000..cfde22391a
--- /dev/null
+++ b/src/chemistry/pp_ghg_mam4/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_ghg_mam4/mo_imp_sol.F90 b/src/chemistry/pp_ghg_mam4/mo_imp_sol.F90
new file mode 100644
index 0000000000..d885728ba4
--- /dev/null
+++ b/src/chemistry/pp_ghg_mam4/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_ghg_mam4/mo_indprd.F90 b/src/chemistry/pp_ghg_mam4/mo_indprd.F90
new file mode 100644
index 0000000000..6906fcf304
--- /dev/null
+++ b/src/chemistry/pp_ghg_mam4/mo_indprd.F90
@@ -0,0 +1,61 @@
+ 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 Explicit species
+!--------------------------------------------------------------------
+ if( class == 1 ) then
+ prod(:,:,1) = 0._r8
+!--------------------------------------------------------------------
+! ... "independent" production for Implicit species
+!--------------------------------------------------------------------
+ else if( class == 4 ) then
+ prod(:,:,1) = + extfrc(:,:,1)
+ prod(:,:,2) = + extfrc(:,:,2)
+ prod(:,:,3) = 0._r8
+ prod(:,:,4) = 0._r8
+ prod(:,:,5) = 0._r8
+ prod(:,:,6) = 0._r8
+ prod(:,:,7) = 0._r8
+ prod(:,:,8) = 0._r8
+ prod(:,:,9) = 0._r8
+ prod(:,:,10) =rxt(:,:,6)
+ prod(:,:,11) = 0._r8
+ prod(:,:,12) = 0._r8
+ prod(:,:,13) = 0._r8
+ prod(:,:,14) = 0._r8
+ prod(:,:,15) = 0._r8
+ prod(:,:,16) = + extfrc(:,:,4)
+ prod(:,:,17) = + extfrc(:,:,5)
+ prod(:,:,18) = 0._r8
+ prod(:,:,19) = + extfrc(:,:,6)
+ prod(:,:,20) = + extfrc(:,:,7)
+ prod(:,:,21) = + extfrc(:,:,8)
+ prod(:,:,22) = + extfrc(:,:,9)
+ prod(:,:,23) = + extfrc(:,:,10)
+ prod(:,:,24) = + extfrc(:,:,11)
+ prod(:,:,25) = 0._r8
+ prod(:,:,26) = 0._r8
+ prod(:,:,27) = 0._r8
+ prod(:,:,28) = 0._r8
+ prod(:,:,29) = 0._r8
+ prod(:,:,30) = + extfrc(:,:,3)
+ end if
+ end subroutine indprd
+ end module mo_indprd
diff --git a/src/chemistry/pp_ghg_mam4/mo_lin_matrix.F90 b/src/chemistry/pp_ghg_mam4/mo_lin_matrix.F90
new file mode 100644
index 0000000000..7b32b664f5
--- /dev/null
+++ b/src/chemistry/pp_ghg_mam4/mo_lin_matrix.F90
@@ -0,0 +1,71 @@
+ 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) = -( het_rates(1) )
+ mat(2) = -( het_rates(2) )
+ mat(3) = -( rxt(8) + het_rates(3) )
+ mat(4) = -( rxt(9) + het_rates(4) )
+ mat(5) = -( rxt(10) + het_rates(5) )
+ mat(7) = -( rxt(11) + rxt(12) + rxt(14) + het_rates(7) )
+ mat(9) = -( het_rates(8) )
+ mat(10) = -( het_rates(9) )
+ mat(11) = -( het_rates(10) )
+ mat(12) = -( rxt(1) + rxt(5) + het_rates(11) )
+ mat(14) = -( het_rates(12) )
+ mat(25) = rxt(13)
+ mat(15) = -( rxt(7) + het_rates(13) )
+ mat(16) = -( het_rates(14) )
+ mat(17) = -( het_rates(15) )
+ mat(18) = -( het_rates(16) )
+ mat(19) = -( het_rates(17) )
+ mat(20) = -( het_rates(18) )
+ mat(21) = -( het_rates(19) )
+ mat(22) = -( het_rates(20) )
+ mat(23) = -( het_rates(21) )
+ mat(24) = -( het_rates(22) )
+ mat(26) = -( rxt(13) + het_rates(23) )
+ mat(8) = rxt(11) + rxt(12) + .500_r8*rxt(14)
+ mat(27) = -( het_rates(24) )
+ mat(28) = -( het_rates(25) )
+ mat(29) = -( het_rates(26) )
+ mat(30) = -( rxt(2) + het_rates(27) )
+ mat(31) = -( rxt(3) + het_rates(28) )
+ mat(32) = -( rxt(15) + het_rates(29) )
+ mat(34) = -( het_rates(30) )
+ mat(33) = rxt(15)
+ mat(35) = -( rxt(4) + het_rates(31) )
+ mat(13) = rxt(5)
+ mat(6) = 2.000_r8*rxt(10)
+ 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_ghg_mam4/mo_lu_factor.F90 b/src/chemistry/pp_ghg_mam4/mo_lu_factor.F90
new file mode 100644
index 0000000000..d981e77137
--- /dev/null
+++ b/src/chemistry/pp_ghg_mam4/mo_lu_factor.F90
@@ -0,0 +1,56 @@
+ 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) = 1._r8 / lu(2)
+ lu(3) = 1._r8 / lu(3)
+ lu(4) = 1._r8 / lu(4)
+ 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) = lu(13) * lu(12)
+ 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(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(33) = lu(33) * lu(32)
+ lu(34) = 1._r8 / lu(34)
+ lu(35) = 1._r8 / lu(35)
+ 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_ghg_mam4/mo_lu_solve.F90 b/src/chemistry/pp_ghg_mam4/mo_lu_solve.F90
new file mode 100644
index 0000000000..574861e9b1
--- /dev/null
+++ b/src/chemistry/pp_ghg_mam4/mo_lu_solve.F90
@@ -0,0 +1,87 @@
+ 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(30) = b(30) - lu(6) * b(5)
+ b(22) = b(22) - lu(8) * b(6)
+ b(30) = b(30) - lu(13) * b(10)
+ b(29) = b(29) - lu(33) * b(28)
+ 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(35)
+ b(29) = b(29) * lu(34)
+ b(28) = b(28) * lu(32)
+ b(27) = b(27) * lu(31)
+ b(26) = b(26) * lu(30)
+ b(25) = b(25) * lu(29)
+ b(24) = b(24) * lu(28)
+ b(23) = b(23) * lu(27)
+ b(22) = b(22) * lu(26)
+ b(11) = b(11) - lu(25) * b(22)
+ b(21) = b(21) * lu(24)
+ b(20) = b(20) * lu(23)
+ b(19) = b(19) * lu(22)
+ b(18) = b(18) * lu(21)
+ b(17) = b(17) * lu(20)
+ b(16) = b(16) * lu(19)
+ b(15) = b(15) * lu(18)
+ b(14) = b(14) * lu(17)
+ b(13) = b(13) * lu(16)
+ b(12) = b(12) * lu(15)
+ b(11) = b(11) * lu(14)
+ b(10) = b(10) * lu(12)
+ b(9) = b(9) * lu(11)
+ b(8) = b(8) * lu(10)
+ b(7) = b(7) * lu(9)
+ b(6) = b(6) * lu(7)
+ b(5) = b(5) * lu(5)
+ b(4) = b(4) * lu(4)
+ b(3) = b(3) * lu(3)
+ b(2) = b(2) * lu(2)
+ 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_ghg_mam4/mo_nln_matrix.F90 b/src/chemistry/pp_ghg_mam4/mo_nln_matrix.F90
new file mode 100644
index 0000000000..c48389b422
--- /dev/null
+++ b/src/chemistry/pp_ghg_mam4/mo_nln_matrix.F90
@@ -0,0 +1,100 @@
+ 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( 1) = mat( 1) - dti
+ mat( 2) = mat( 2) - dti
+ mat( 3) = mat( 3) - dti
+ mat( 4) = mat( 4) - 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( 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( 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( 34) = mat( 34) - dti
+ mat( 35) = mat( 35) - dti
+ end subroutine nlnmat_finit
+ end module mo_nln_matrix
diff --git a/src/chemistry/pp_ghg_mam4/mo_phtadj.F90 b/src/chemistry/pp_ghg_mam4/mo_phtadj.F90
new file mode 100644
index 0000000000..aaa43829fe
--- /dev/null
+++ b/src/chemistry/pp_ghg_mam4/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_ghg_mam4/mo_prod_loss.F90 b/src/chemistry/pp_ghg_mam4/mo_prod_loss.F90
new file mode 100644
index 0000000000..d502e216a3
--- /dev/null
+++ b/src/chemistry/pp_ghg_mam4/mo_prod_loss.F90
@@ -0,0 +1,101 @@
+ 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(:,:,:)
+!--------------------------------------------------------------------
+! ... loss and production for Explicit method
+!--------------------------------------------------------------------
+ loss(:,:,1) = ( + het_rates(:,:,6))* y(:,:,6)
+ prod(:,:,1) = 0._r8
+ 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) = ( + het_rates(1))* y(1)
+ prod(1) = 0._r8
+ loss(2) = ( + het_rates(2))* y(2)
+ prod(2) = 0._r8
+ loss(3) = ( + rxt(8) + het_rates(3))* y(3)
+ prod(3) = 0._r8
+ loss(4) = ( + rxt(9) + het_rates(4))* y(4)
+ prod(4) = 0._r8
+ loss(5) = ( + rxt(10) + het_rates(5))* y(5)
+ prod(5) = 0._r8
+ loss(6) = ( + rxt(11) + rxt(12) + rxt(14) + 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) = ( + rxt(1) + rxt(5) + het_rates(11))* y(11)
+ prod(10) = 0._r8
+ loss(11) = ( + het_rates(12))* y(12)
+ prod(11) =rxt(13)*y(23)
+ loss(12) = ( + rxt(7) + 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) = ( + rxt(13) + het_rates(23))* y(23)
+ prod(22) = (rxt(11) +rxt(12) +.500_r8*rxt(14))*y(7)
+ loss(23) = ( + het_rates(24))* y(24)
+ prod(23) = 0._r8
+ loss(24) = ( + het_rates(25))* y(25)
+ prod(24) = 0._r8
+ loss(25) = ( + het_rates(26))* y(26)
+ prod(25) = 0._r8
+ loss(26) = ( + rxt(2) + het_rates(27))* y(27)
+ prod(26) = 0._r8
+ loss(27) = ( + rxt(3) + het_rates(28))* y(28)
+ prod(27) = 0._r8
+ loss(28) = ( + rxt(15) + het_rates(29))* y(29)
+ prod(28) = 0._r8
+ loss(29) = ( + het_rates(30))* y(30)
+ prod(29) =rxt(15)*y(29)
+ loss(30) = ( + rxt(4) + het_rates(31))* y(31)
+ prod(30) =2.000_r8*rxt(10)*y(5) +rxt(5)*y(11)
+ end subroutine imp_prod_loss
+ end module mo_prod_loss
diff --git a/src/chemistry/pp_ghg_mam4/mo_rxt_rates_conv.F90 b/src/chemistry/pp_ghg_mam4/mo_rxt_rates_conv.F90
new file mode 100644
index 0000000000..0030b06714
--- /dev/null
+++ b/src/chemistry/pp_ghg_mam4/mo_rxt_rates_conv.F90
@@ -0,0 +1,27 @@
+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,:, 11) ! rate_const*H2O2
+ rxt_rates(:ncol,:, 2) = rxt_rates(:ncol,:, 2)*sol(:ncol,:, 27) ! rate_const*soa_a1
+ rxt_rates(:ncol,:, 3) = rxt_rates(:ncol,:, 3)*sol(:ncol,:, 28) ! rate_const*soa_a2
+ rxt_rates(:ncol,:, 4) = rxt_rates(:ncol,:, 4)*sol(:ncol,:, 31) ! rate_const*H2O
+ rxt_rates(:ncol,:, 5) = rxt_rates(:ncol,:, 5)*sol(:ncol,:, 11) ! rate_const*OH*H2O2
+ ! rate_const
+ rxt_rates(:ncol,:, 7) = rxt_rates(:ncol,:, 7)*sol(:ncol,:, 13) ! rate_const*N2O
+ rxt_rates(:ncol,:, 8) = rxt_rates(:ncol,:, 8)*sol(:ncol,:, 3) ! rate_const*CFC11
+ rxt_rates(:ncol,:, 9) = rxt_rates(:ncol,:, 9)*sol(:ncol,:, 4) ! rate_const*CFC12
+ rxt_rates(:ncol,:, 10) = rxt_rates(:ncol,:, 10)*sol(:ncol,:, 5) ! rate_const*CH4
+ rxt_rates(:ncol,:, 11) = rxt_rates(:ncol,:, 11)*sol(:ncol,:, 7) ! rate_const*NO3*DMS
+ rxt_rates(:ncol,:, 12) = rxt_rates(:ncol,:, 12)*sol(:ncol,:, 7) ! rate_const*OH*DMS
+ rxt_rates(:ncol,:, 13) = rxt_rates(:ncol,:, 13)*sol(:ncol,:, 23) ! rate_const*OH*M*SO2
+ rxt_rates(:ncol,:, 14) = rxt_rates(:ncol,:, 14)*sol(:ncol,:, 7) ! rate_const*OH*DMS
+ rxt_rates(:ncol,:, 15) = rxt_rates(:ncol,:, 15)*sol(:ncol,:, 29) ! rate_const*SOAE
+ end subroutine set_rates
+end module mo_rxt_rates_conv
diff --git a/src/chemistry/pp_ghg_mam4/mo_setrxt.F90 b/src/chemistry/pp_ghg_mam4/mo_setrxt.F90
new file mode 100644
index 0000000000..6b94705faa
--- /dev/null
+++ b/src/chemistry/pp_ghg_mam4/mo_setrxt.F90
@@ -0,0 +1,85 @@
+
+ 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)
+
+ rate(:,:,5) = 1.8e-12_r8
+ rate(:,:,15) = 1.157e-05_r8
+ itemp(:ncol,:) = 1._r8 / temp(:ncol,:)
+ n = ncol*pver
+ rate(:,:,11) = 1.9e-13_r8 * exp( 520._r8 * itemp(:,:) )
+ rate(:,:,12) = 1.1e-11_r8 * exp( -280._r8 * itemp(:,:) )
+
+ itemp(:,:) = 300._r8 * itemp(:,:)
+
+ ko(:,:) = 2.9e-31_r8 * itemp(:,:)**4.1_r8
+ kinf(:,:) = 1.7e-12_r8 * itemp(:,:)**(-0.2_r8)
+ call jpl( rate(1,1,13), 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_ghg_mam4/mo_sim_dat.F90 b/src/chemistry/pp_ghg_mam4/mo_sim_dat.F90
new file mode 100644
index 0000000000..04177a1f6e
--- /dev/null
+++ b/src/chemistry/pp_ghg_mam4/mo_sim_dat.F90
@@ -0,0 +1,146 @@
+
+ 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(:) = (/ 1, 0, 0, 30, 0 /)
+
+ cls_rxt_cnt(:,1) = (/ 0, 0, 0, 1 /)
+ cls_rxt_cnt(:,4) = (/ 1, 14, 0, 30 /)
+
+ solsym(: 31) = (/ 'bc_a1 ','bc_a4 ','CFC11 ','CFC12 ','CH4 ', &
+ 'CO2 ','DMS ','dst_a1 ','dst_a2 ','dst_a3 ', &
+ 'H2O2 ','H2SO4 ','N2O ','ncl_a1 ','ncl_a2 ', &
+ 'ncl_a3 ','num_a1 ','num_a2 ','num_a3 ','num_a4 ', &
+ 'pom_a1 ','pom_a4 ','SO2 ','so4_a1 ','so4_a2 ', &
+ 'so4_a3 ','soa_a1 ','soa_a2 ','SOAE ','SOAG ', &
+ 'H2O ' /)
+
+ adv_mass(: 31) = (/ 12.011000_r8, 12.011000_r8, 137.367503_r8, 120.913206_r8, 16.040600_r8, &
+ 44.009800_r8, 62.132400_r8, 135.064039_r8, 135.064039_r8, 135.064039_r8, &
+ 34.013600_r8, 98.078400_r8, 44.012880_r8, 58.442468_r8, 58.442468_r8, &
+ 58.442468_r8, 1.007400_r8, 1.007400_r8, 1.007400_r8, 1.007400_r8, &
+ 12.011000_r8, 12.011000_r8, 64.064800_r8, 115.107340_r8, 115.107340_r8, &
+ 115.107340_r8, 12.011000_r8, 12.011000_r8, 12.011000_r8, 12.011000_r8, &
+ 18.014200_r8 /)
+
+ crb_mass(: 31) = (/ 12.011000_r8, 12.011000_r8, 12.011000_r8, 12.011000_r8, 12.011000_r8, &
+ 12.011000_r8, 24.022000_r8, 0.000000_r8, 0.000000_r8, 0.000000_r8, &
+ 0.000000_r8, 0.000000_r8, 0.000000_r8, 0.000000_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, 0.000000_r8, 0.000000_r8, 0.000000_r8, &
+ 0.000000_r8, 12.011000_r8, 12.011000_r8, 12.011000_r8, 12.011000_r8, &
+ 0.000000_r8 /)
+
+ fix_mass(: 8) = (/ 0.00000000_r8, 31.9988000_r8, 28.0134800_r8, 33.0062000_r8, 17.0068000_r8, &
+ 62.0049400_r8, 47.9982000_r8, 137.367503_r8 /)
+
+ clsmap(: 1,1) = (/ 6 /)
+ clsmap(: 30,4) = (/ 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, &
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, &
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 /)
+
+ 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, 2, 3, 4, 5, 7, 9, 10, 11, 12, &
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, &
+ 24, 26, 27, 28, 29, 30, 31, 32, 34, 35 /)
+
+ extfrc_lst(: 11) = (/ 'bc_a1 ','bc_a4 ','H2O ','num_a1 ','num_a2 ', &
+ 'num_a4 ','pom_a1 ','pom_a4 ','SO2 ','so4_a1 ', &
+ 'so4_a2 ' /)
+
+ frc_from_dataset(: 11) = (/ .true., .true., .true., .true., .true., &
+ .true., .true., .true., .true., .true., &
+ .true. /)
+
+ inv_lst(: 8) = (/ 'M ', 'O2 ', 'N2 ', 'HO2 ', 'OH ', &
+ 'NO3 ', 'O3 ', 'HALONS ' /)
+
+ 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: 15) = (/ 'jh2o2 ', 'jsoa_a1 ', &
+ 'jsoa_a2 ', 'lyman_alpha ', &
+ 'OH_H2O2 ', 'usr_HO2_HO2 ', &
+ 'n2o_loss ', 'cfc11_loss ', &
+ 'cfc12_loss ', 'ch4_loss ', &
+ 'DMS_NO3 ', 'DMS_OHa ', &
+ 'SO2_OH_M ', 'usr_DMS_OH ', &
+ 'SOAE_tau ' /)
+ rxt_tag_map(:rxt_tag_cnt) = (/ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, &
+ 11, 12, 13, 14, 15 /)
+ 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) = (/ ' ', 'jno2 ', 'jno2 ' /)
+ pht_alias_mult(:,1) = (/ 1._r8, 1._r8, 1._r8 /)
+ pht_alias_mult(:,2) = (/ 1._r8, .0004_r8, .0004_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(:) = (/ 1, 2, 2, 1, 1, 1, 1, 2, 2, 3, &
+ 2, 1 /)
+
+ end subroutine set_sim_dat
+
+ end module mo_sim_dat
diff --git a/src/control/cam_budget.F90 b/src/control/cam_budget.F90
new file mode 100644
index 0000000000..1ae7fd20f4
--- /dev/null
+++ b/src/control/cam_budget.F90
@@ -0,0 +1,398 @@
+module cam_budget
+ !----------------------------------------------------------------------------
+ !
+ ! Adds support for energy and mass snapshots and budgets using cam_history api.
+ !
+ ! Public functions/subroutines:
+ !
+ ! cam_budget_init
+ ! cam_budget_em_snapshot
+ ! cam_budget_em_register
+ ! cam_budget_get_global
+ ! cam_budget_readnl
+ ! budget_ind_byname
+ ! is_cam_budget
+ !-----------------------------------------------------------------------
+
+ use cam_abortutils, only: endrun
+ use cam_history, only: addfld, add_default, horiz_only
+ use cam_history_support, only: max_fieldname_len
+ use cam_logfile, only: iulog
+ use cam_thermo, only: thermo_budget_vars, thermo_budget_vars_descriptor, &
+ thermo_budget_vars_unit, thermo_budget_vars_massv, thermo_budget_num_vars,teidx,wvidx,wlidx,wiidx
+ use shr_kind_mod, only: r8 => shr_kind_r8
+ use shr_kind_mod, only: cl => shr_kind_cl
+ use spmd_utils, only: masterproc, masterprocid, mpicom
+
+ implicit none
+ private
+ save
+
+ ! Public interfaces
+ public :: &
+ cam_budget_init, &! initialize budget variables
+ cam_budget_em_snapshot, &! define a snapshot and add to history buffer
+ cam_budget_em_register, &! define a budget and add to history buffer
+ cam_budget_get_global, &! get global budget from history buffer
+ cam_budget_readnl, &! read budget namelist setting
+ is_cam_budget ! return logical if budget_defined
+
+ ! Private
+ real(r8) :: dstepsize
+ integer, parameter :: budget_array_max = 500 ! max number of budgets
+ character*3 :: budget_optype(budget_array_max) = '' ! allows 'dif' or 'sum'
+ character*3 :: budget_pkgtype(budget_array_max) = '' ! allows 'phy' or 'dyn'
+
+ ! Public data
+ integer, public, protected :: budget_num = 0 ! current number of defined budgets.
+ character(cl), public, protected :: budget_name(budget_array_max) = '' ! budget names
+ character(cl), public, protected :: budget_longname(budget_array_max) = '' ! descriptive name of budget
+ character(cl), public, protected :: budget_stagename(budget_array_max)= '' ! shortname of both of the 3 char snapshot components
+ character(cl), public, protected :: budget_stg1name(budget_array_max) = '' ! The 1st of 2 snapshots used to calculate a budget
+ character(cl), public, protected :: budget_stg2name(budget_array_max) = '' ! The 2nd of 2 snapshots used to calculate a budget
+
+ integer, public, protected :: thermo_budget_histfile_num = 1 ! The history tape number for budget fields
+ logical, public, protected :: thermo_budget_history = .false. ! Turn budgeting on or off
+
+
+ !==============================================================================================
+CONTAINS
+ !==============================================================================================
+ !
+ ! Read namelist variables.
+ subroutine cam_budget_readnl(nlfile)
+ use dycore, only: dycore_is
+ use namelist_utils, only: find_group_name
+ use spmd_utils, only: mpi_character, mpi_logical, mpi_integer, mpi_success
+ use shr_string_mod, only: shr_string_toUpper
+ use string_utils, only: int2str
+
+ ! Dummy argument: filepath for file containing namelist input
+ character(len=*), intent(in) :: nlfile
+
+ ! Local variables
+ integer :: unitn, ierr
+ character(len=*), parameter :: subname = 'cam_budget_readnl :: '
+
+ namelist /thermo_budget_nl/ thermo_budget_history, thermo_budget_histfile_num
+ !-----------------------------------------------------------------------
+
+ if (masterproc) then
+ open(newunit=unitn, file=trim(nlfile), status='old')
+ call find_group_name(unitn, 'thermo_budget_nl', status=ierr)
+ if (ierr == 0) then
+ read(unitn, thermo_budget_nl, iostat=ierr)
+ if (ierr /= 0) then
+ call endrun(subname//'ERROR reading namelist, thermo_budget_nl, errcode = '//int2str(ierr))
+ end if
+ end if
+ close(unitn)
+ end if
+
+ ! Broadcast namelist variables
+ call mpi_bcast(thermo_budget_history , 1 , mpi_logical , masterprocid, mpicom, ierr)
+ if (ierr /= mpi_success) call endrun(subname//": FATAL: mpi_bcast: thermo_budget_history")
+ call mpi_bcast(thermo_budget_histfile_num , 1 , mpi_integer , masterprocid, mpicom, ierr)
+ if (ierr /= mpi_success) call endrun(subname//": FATAL: mpi_bcast: thermo_budget_histfile_num")
+
+ ! Write out thermo_budget options
+ if (masterproc) then
+ if (thermo_budget_history) then
+ if (dycore_is('EUL').or.dycore_is('FV').or.dycore_is('FV3')) then
+ call endrun(subname//'ERROR thermodynamic budgets not implemented for this dycore')
+ else
+ write(iulog,*)'Thermo budgets will be written to the log file and diagnostics saved to history file:',&
+ thermo_budget_histfile_num
+ end if
+ end if
+ end if
+ end subroutine cam_budget_readnl
+
+ !==============================================================================================
+
+ subroutine cam_budget_init()
+ use time_manager, only: get_step_size
+
+ dstepsize=get_step_size()
+
+ end subroutine cam_budget_init
+
+ !==============================================================================================
+
+ subroutine cam_budget_em_snapshot (name, pkgtype, longname)
+ use dycore, only: dycore_is
+ use cam_grid_support, only: cam_grid_id
+
+ character(len=*), intent(in) :: &
+ name ! budget name used as variable name in history file output (8 char max)
+ character(len=*), intent(in) :: &
+ pkgtype ! budget type either phy or dyn
+ character(len=*), intent(in) :: &
+ longname ! value for long_name attribute in netcdf output (128 char max, defaults to name)
+
+ character (cl) :: errmsg
+ character (len=max_fieldname_len) :: name_str
+ character (cl) :: desc_str, units_str
+ character (cl) :: gridname
+ integer :: ivars
+ character(len=*), parameter :: sub='cam_budget_em_snapshot'
+ logical :: use_cslam ! using cslam transport for mass tracers
+ !-----------------------------------------------------------------------
+
+ if (thermo_budget_history) then
+ ! FVM grid is only registered when using cslam
+ use_cslam=cam_grid_id('FVM')>0
+
+ do ivars=1, thermo_budget_num_vars
+ write(name_str,*) TRIM(ADJUSTL(thermo_budget_vars(ivars))),"_",TRIM(ADJUSTL(name))
+ write(desc_str,*) TRIM(ADJUSTL(thermo_budget_vars_descriptor(ivars)))," ", &
+ TRIM(ADJUSTL(longname))
+ write(units_str,*) TRIM(ADJUSTL(thermo_budget_vars_unit(ivars)))
+
+ if (budget_num < budget_array_max) then
+ budget_num = budget_num + 1
+ else
+ write(errmsg, *) sub, ': Maximum number of budgets reached - increase budget_array_max parameter '
+ call endrun(errmsg)
+ end if
+ ! set budget name and constants
+ budget_name(budget_num) = trim(name_str)
+ budget_longname(budget_num) = trim(desc_str)
+
+ budget_pkgtype(budget_num)=pkgtype
+ budget_stagename(budget_num)= trim(name)
+
+ if (pkgtype=='phy') then
+ gridname='physgrid'
+ else
+ if (dycore_is('SE')) then
+ if (use_cslam .and. thermo_budget_vars_massv(ivars)) then
+ gridname='FVM'
+ else
+ gridname='GLL'
+ end if
+ else if (dycore_is('MPAS')) then
+ gridname='mpas_cell'
+ else
+ write(errmsg, *) sub, ': budget_add is only supported for MPAS and SE dycores'
+ call endrun(errmsg)
+ end if
+ end if
+ call addfld (TRIM(ADJUSTL(name_str)), horiz_only, 'N', TRIM(ADJUSTL(units_str)), &
+ TRIM(ADJUSTL(desc_str)), gridname=trim(gridname))
+ call add_default(TRIM(ADJUSTL(name_str)), thermo_budget_histfile_num, 'N')
+ end do
+ end if
+ end subroutine cam_budget_em_snapshot
+
+ !==============================================================================
+
+ subroutine cam_budget_em_register (name, stg1name, stg2name, pkgtype, optype, longname)
+ use dycore, only: dycore_is
+ use cam_grid_support, only: cam_grid_id
+
+ ! Register a budget.
+
+ character(len=*), intent(in) :: &
+ name,stg1name,stg2name ! budget name used as variable name in history file output (8 char max)
+
+ character(len=*), intent(in) :: &
+ pkgtype ! budget type either phy or dyn
+
+ character(len=*), intent(in) :: &
+ optype ! dif (difference) or sum
+
+ character(len=*), intent(in) :: &
+ longname ! value for long_name attribute in netcdf output (128 char max, defaults to name)
+
+ character(len=*), parameter :: sub='cam_budget_em_register'
+ character(cl) :: errmsg
+ character(len=1) :: opchar
+ character (len=max_fieldname_len) :: name_str
+ character (cl) :: desc_str, units_str
+ character (cl) :: gridname
+ character (cl) :: strstg1, strstg2
+ integer :: ivars
+ logical :: use_cslam ! true => use cslam to transport mass variables
+ !-----------------------------------------------------------------------
+
+ if (thermo_budget_history) then
+ ! the FVM gridname is only defined when use_cslam is true.
+ use_cslam=cam_grid_id('FVM')>0
+
+ ! register history budget variables
+ do ivars=1, thermo_budget_num_vars
+ write(name_str,*) TRIM(ADJUSTL(thermo_budget_vars(ivars))),"_",TRIM(ADJUSTL(name))
+ write(strstg1,*) TRIM(ADJUSTL(thermo_budget_vars(ivars))),"_",TRIM(ADJUSTL(stg1name))
+ write(strstg2,*) TRIM(ADJUSTL(thermo_budget_vars(ivars))),"_",TRIM(ADJUSTL(stg2name))
+ write(desc_str,*) TRIM(ADJUSTL(thermo_budget_vars_descriptor(ivars)))," ", &
+ TRIM(ADJUSTL(longname))
+ write(units_str,*) TRIM(ADJUSTL(thermo_budget_vars_unit(ivars)))
+
+ if (budget_num < budget_array_max) then
+ budget_num = budget_num + 1
+ else
+ write(errmsg, *) sub, ': Maximum number of budgets reached - increase budget_array_max parameter '
+ call endrun(errmsg)
+ end if
+ budget_pkgtype(budget_num)=pkgtype
+
+ ! set budget name and constants
+ budget_name(budget_num) = trim(name_str)
+ budget_longname(budget_num) = trim(desc_str)
+
+ if (optype=='dif') then
+ opchar='-'
+ else if (optype=='sum') then
+ opchar='+'
+ else
+ write(errmsg,*) sub, ': FATAL: unknown operation type, expecting "sum" or "dif":', optype
+ call endrun(errmsg)
+ end if
+ budget_stg1name(budget_num) = trim(adjustl(strstg1))
+ budget_stg2name(budget_num) = trim(adjustl(strstg2))
+ budget_stagename(budget_num)= trim(adjustl(strstg1))//trim(opchar)//trim(adjustl(strstg2))
+ budget_optype(budget_num)=optype
+
+ if (pkgtype=='phy') then
+ gridname='physgrid'
+ else
+ if (dycore_is('SE')) then
+ if (use_cslam .and. thermo_budget_vars_massv(ivars)) then
+ gridname='FVM'
+ else
+ gridname='GLL'
+ end if
+ else if (dycore_is('MPAS')) then
+ gridname='mpas_cell'
+ else
+ write(errmsg, *) sub, ': budget_add is only supported for MPAS and SE dycores'
+ call endrun(errmsg)
+ end if
+ end if
+ call addfld (TRIM(ADJUSTL(name_str)), horiz_only, 'N', TRIM(ADJUSTL(units_str)),TRIM(ADJUSTL(desc_str)), &
+ gridname=gridname,optype=optype,op_f1name=TRIM(ADJUSTL(strstg1)),op_f2name=TRIM(ADJUSTL(strstg2)))
+ call add_default(TRIM(ADJUSTL(name_str)), thermo_budget_histfile_num, 'N')
+ end do
+ end if
+ end subroutine cam_budget_em_register
+
+ !==============================================================================
+
+ subroutine cam_budget_get_global (name, me_idx, global)
+
+ use cam_history, only: get_field_properties
+ use cam_history_support, only: active_entry,ptapes
+ use cam_thermo, only: thermo_budget_vars_massv
+
+ ! Get the global integral of a budget. Endrun will be called
+ ! when name is not found.
+ !-----------------------------Arguments---------------------------------
+ character(len=*), intent(in) :: name ! budget name
+ integer, intent(in) :: me_idx ! mass energy variable index
+ real(r8), intent(out) :: global ! global integral of the budget field
+
+ !---------------------------Local workspace-----------------------------
+ type (active_entry), pointer :: tape(:) ! history tapes
+ character (len=max_fieldname_len) :: name_str
+ character(cl) :: errmsg
+ integer :: b_ind ! budget index
+ integer :: h_ind(ptapes) ! hentry index
+ integer :: m_ind ! masterlist index
+ integer :: idx,pidx,midx,uidx ! substring index for sum dif char
+ integer :: m ! budget index
+ logical :: found ! true if global integral found
+
+ character(len=*), parameter :: sub='cam_budget_get_global'
+ !-----------------------------------------------------------------------
+ ! Initialize tape pointer here to avoid initialization only on first invocation
+ nullify(tape)
+
+ name_str=''
+ write(name_str,*) TRIM(ADJUSTL(name))
+
+ midx=index(name_str, '-')
+ pidx=index(name_str, '+')
+ idx=midx+pidx
+
+ ! check for budget using stagename short format (stg1//op//stg2) where stg1 is name without thermo string appended
+ if (idx /= 0 .and. (midx==0 .or. pidx==0)) then
+ write(name_str,*) TRIM(ADJUSTL(thermo_budget_vars(me_idx)))//"_"//trim(adjustl(name_str(1:idx)))// &
+ TRIM(ADJUSTL(thermo_budget_vars(me_idx)))//"_"//TRIM(ADJUSTL(name_str(idx+1:)))
+ end if
+
+ uidx=index(name_str, '_')
+ if (uidx == 0) then
+ !This is a stage name need to append the type of thermo variable using input index
+ write(name_str,*) TRIM(ADJUSTL(thermo_budget_vars(me_idx)))//"_"//trim(adjustl(name_str(1:)))
+ end if
+
+ b_ind=budget_ind_byname(trim(adjustl(name_str)))
+
+ if (b_ind < 0) call endrun(sub//': FATAL field name '//name//' not found'//' looked for '//trim(adjustl(name_str)))
+
+ write(name_str,*) TRIM(ADJUSTL(budget_name(b_ind)))
+
+ ! Find budget name in list and return global value
+ call get_field_properties(trim(adjustl(name_str)), found, tape_out=tape, ff_out=m_ind, f_out=h_ind)
+
+ if (found.and.h_ind(thermo_budget_histfile_num)>0) then
+ call tape(thermo_budget_histfile_num)%hlist(h_ind(thermo_budget_histfile_num))%get_global(global)
+ if (.not. thermo_budget_vars_massv(me_idx)) &
+ global=global/dstepsize
+ else
+ write(errmsg,*) sub, ': FATAL: name not found: ', trim(name)
+ call endrun(errmsg)
+ end if
+
+ CONTAINS
+ pure function budget_ind_byname (name)
+ !
+ ! Get the index of a budget. Ret -1 for not found
+ !-----------------------------Arguments---------------------------------
+ character(len=*), intent(in) :: name ! budget name
+
+ !---------------------------Local workspace-----------------------------
+ integer :: budget_ind_byname ! function return
+ integer :: m ! budget index
+ !-----------------------------------------------------------------------
+ ! Find budget name in list
+ budget_ind_byname = -1
+ do m = 1, budget_num
+ if (trim(adjustl(name)) == trim(adjustl(budget_name(m))).or. &
+ trim(adjustl(name)) == trim(adjustl(budget_stagename(m)))) then
+ budget_ind_byname = m
+ return
+ end if
+ end do
+ end function budget_ind_byname
+ end subroutine cam_budget_get_global
+ !==============================================================================
+
+ pure function is_cam_budget(name)
+
+ ! Get the index of a budget.
+
+ !-----------------------------Arguments---------------------------------
+ character(len=*), intent(in) :: name ! budget name
+
+ !---------------------------Local workspace-----------------------------
+ logical :: is_cam_budget ! function return
+ integer :: m ! budget index
+ !-----------------------------------------------------------------------
+
+ ! Find budget name in list of defined budgets
+
+ is_cam_budget = .false.
+ do m = 1, budget_num
+ if (trim(adjustl(name)) == trim(adjustl(budget_name(m))).or. &
+ trim(adjustl(name)) == trim(adjustl(budget_stagename(m)))) then
+ is_cam_budget = .true.
+ return
+ end if
+ end do
+ end function is_cam_budget
+
+ !===========================================================================
+
+end module cam_budget
diff --git a/src/control/cam_comp.F90 b/src/control/cam_comp.F90
index b92e02b000..f4091fda1a 100644
--- a/src/control/cam_comp.F90
+++ b/src/control/cam_comp.F90
@@ -16,9 +16,7 @@ module cam_comp
use spmd_utils, only: masterproc, mpicom
use cam_control_mod, only: cam_ctrl_init, cam_ctrl_set_orbit
use runtime_opts, only: read_namelist
-use time_manager, only: timemgr_init, get_step_size, &
- get_nstep, is_first_step, is_first_restart_step
-
+use time_manager, only: timemgr_init, get_nstep
use camsrfexch, only: cam_out_t, cam_in_t
use ppgrid, only: begchunk, endchunk
use physics_types, only: physics_state, physics_tend
@@ -393,7 +391,8 @@ subroutine cam_run4( cam_out, cam_in, rstwr, nlend, &
! file output.
!
!-----------------------------------------------------------------------
- use cam_history, only: wshist, wrapup
+ use dycore_budget, only: print_budget
+ use cam_history, only: wshist, wrapup, hstwr
use cam_restart, only: cam_write_restart
use qneg_module, only: qneg_print_summary
use time_manager, only: is_last_step
@@ -436,6 +435,8 @@ subroutine cam_run4( cam_out, cam_in, rstwr, nlend, &
call qneg_print_summary(is_last_step())
+ call print_budget(hstwr)
+
call shr_sys_flush(iulog)
end subroutine cam_run4
diff --git a/src/control/cam_history.F90 b/src/control/cam_history.F90
index 5b0e6f47f2..677544bdc3 100644
--- a/src/control/cam_history.F90
+++ b/src/control/cam_history.F90
@@ -49,7 +49,8 @@ module cam_history
field_info, active_entry, hentry, &
horiz_only, write_hist_coord_attrs, &
write_hist_coord_vars, interp_info_t, &
- lookup_hist_coord_indices, get_hist_coord_index
+ lookup_hist_coord_indices, get_hist_coord_index, &
+ field_op_len
use string_utils, only: date2yyyymmdd, sec2hms
use sat_hist, only: is_satfile
use solar_parms_data, only: solar_parms_on, kp=>solar_parms_kp, ap=>solar_parms_ap
@@ -68,19 +69,28 @@ module cam_history
public :: cam_history_snapshot_deactivate
public :: cam_history_snapshot_activate
+ type grid_area_entry
+ integer :: decomp_type = -1 ! type of decomposition (e.g., physics or dynamics)
+ real(r8), allocatable :: wbuf(:,:) ! for area weights
+ end type grid_area_entry
+ type (grid_area_entry), target, allocatable:: grid_wts(:) ! area wts for each decomp type
+ type (grid_area_entry), pointer :: allgrids_wt(:) => null() ! area wts for each decomp type
!
! master_entry: elements of an entry in the master field list
!
type master_entry
- type (field_info) :: field ! field information
+ type (field_info) :: field ! field information
character(len=max_fieldname_len) :: meridional_field = '' ! for vector fields
character(len=max_fieldname_len) :: zonal_field = '' ! for vector fields
- character(len=1) :: avgflag(ptapes) ! averaging flag
- character(len=max_chars) :: time_op(ptapes) ! time operator (e.g. max, min, avg)
- logical :: act_sometape ! Field is active on some tape
- logical :: actflag(ptapes) ! Per tape active/inactive flag
- integer :: htapeindx(ptapes)! This field's index on particular history tape
- type(master_entry), pointer :: next_entry => null() ! The next master entry
+ character(len=1) :: avgflag(ptapes) ! averaging flag
+ character(len=max_chars) :: time_op(ptapes) ! time operator (e.g. max, min, avg)
+ character(len=field_op_len) :: field_op = '' ! field derived from sum or dif of field1 and field2
+ character(len=max_fieldname_len) :: op_field1 = '' ! first field name to be operated on
+ character(len=max_fieldname_len) :: op_field2 = '' ! second field name to be operated on
+ logical :: act_sometape ! Field is active on some tape
+ logical :: actflag(ptapes) ! Per tape active/inactive flag
+ integer :: htapeindx(ptapes)! This field's index on particular history tape
+ type(master_entry), pointer :: next_entry => null() ! The next master entry
end type master_entry
type (master_entry), pointer :: masterlinkedlist => null() ! master field linkedlist top
@@ -115,7 +125,7 @@ module cam_history
!
! The size of these parameters should match the assignments in restart_vars_setnames and restart_dims_setnames below
!
- integer, parameter :: restartvarcnt = 38
+ integer, parameter :: restartvarcnt = 45
integer, parameter :: restartdimcnt = 10
type(rvar_id) :: restartvars(restartvarcnt)
type(rdim_id) :: restartdims(restartdimcnt)
@@ -177,8 +187,7 @@ module cam_history
! Allowed history averaging flags
! This should match namelist_definition.xml => avgflag_pertape (+ ' ')
- ! The presence of 'ABI' and 'XML' in this string is a coincidence
- character(len=7), parameter :: HIST_AVG_FLAGS = ' ABIXML'
+ character(len=9), parameter :: HIST_AVG_FLAGS = ' ABILMNSX'
character(len=22) ,parameter :: LT_DESC = 'mean (over local time)' ! local time description
logical :: collect_column_output(ptapes)
@@ -349,6 +358,8 @@ subroutine intht (model_doi_url_in)
use cam_control_mod, only: restart_run, branch_run
use sat_hist, only: sat_hist_init
use spmd_utils, only: mpicom, masterprocid, mpi_character
+ use cam_grid_support, only: cam_grid_get_areawt
+ use cam_history_support, only: dim_index_2d
!
!-----------------------------------------------------------------------
!
@@ -367,8 +378,13 @@ subroutine intht (model_doi_url_in)
integer :: enddim3 ! on-node chunk or lat end index
integer :: day, sec ! day and seconds from base date
integer :: rcode ! shr_sys_getenv return code
+ integer :: wtidx(1) ! area weight index
+ integer :: i,k,c,ib,ie,jb,je,count ! index
+ integer :: fdecomp ! field decomp
+ type(dim_index_2d) :: dimind ! 2-D dimension index
+ real(r8), pointer :: areawt(:) ! pointer to areawt values for attribute
type(master_entry), pointer :: listentry
- character(len=32) :: fldname ! temp variable used to produce a left justified field name
+ character(len=32) :: fldname ! temp variable used to produce a left justified field name
! in the formatted logfile output
!
@@ -466,12 +482,43 @@ subroutine intht (model_doi_url_in)
allocate(tape(t)%hlist(f)%sbuf(begdim1:enddim1,begdim2:enddim2,begdim3:enddim3))
tape(t)%hlist(f)%sbuf = 0._r8
endif
+ if (tape(t)%hlist(f)%avgflag .eq. 'N') then ! set up areawt weight buffer
+ fdecomp = tape(t)%hlist(f)%field%decomp_type
+ if (any(allgrids_wt(:)%decomp_type == fdecomp)) then
+ wtidx=MAXLOC(allgrids_wt(:)%decomp_type, MASK = allgrids_wt(:)%decomp_type .EQ. fdecomp)
+ tape(t)%hlist(f)%wbuf => allgrids_wt(wtidx(1))%wbuf
+ else
+ ! area weights not found for this grid, then create them
+ ! first check for an available spot in the array
+ if (any(allgrids_wt(:)%decomp_type == -1)) then
+ wtidx=MINLOC(allgrids_wt(:)%decomp_type)
+ else
+ call endrun('cam_history:intht: Error initializing allgrids_wt with area weights')
+ end if
+ allgrids_wt(wtidx)%decomp_type=fdecomp
+ areawt => cam_grid_get_areawt(fdecomp)
+ allocate(allgrids_wt(wtidx(1))%wbuf(begdim1:enddim1,begdim3:enddim3))
+ allgrids_wt(wtidx(1))%wbuf(begdim1:enddim1,begdim3:enddim3)=0._r8
+ count=0
+ do c=begdim3,enddim3
+ dimind = tape(t)%hlist(f)%field%get_dims(c)
+ ib=dimind%beg1
+ ie=dimind%end1
+ do i=ib,ie
+ count=count+1
+ allgrids_wt(wtidx(1))%wbuf(i,c)=areawt(count)
+ end do
+ end do
+ tape(t)%hlist(f)%wbuf => allgrids_wt(wtidx(1))%wbuf
+ endif
+ endif
if(tape(t)%hlist(f)%field%flag_xyfill .or. (avgflag_pertape(t) .eq. 'L')) then
allocate (tape(t)%hlist(f)%nacs(begdim1:enddim1,begdim3:enddim3))
else
allocate (tape(t)%hlist(f)%nacs(1,begdim3:enddim3))
end if
tape(t)%hlist(f)%nacs(:,:) = 0
+ tape(t)%hlist(f)%beg_nstep = 0
tape(t)%hlist(f)%field%meridional_complement = -1
tape(t)%hlist(f)%field%zonal_complement = -1
end do
@@ -937,6 +984,47 @@ subroutine setup_interpolation_and_define_vector_complements()
end if
end subroutine setup_interpolation_and_define_vector_complements
+ subroutine define_composed_field_ids(t)
+
+ ! Dummy arguments
+ integer, intent(in) :: t ! Current tape
+
+ ! Local variables
+ integer :: f, ff
+ character(len=max_fieldname_len) :: field1
+ character(len=max_fieldname_len) :: field2
+ character(len=*), parameter :: subname='define_composed_field_ids'
+ logical :: is_composed
+
+ do f = 1, nflds(t)
+ call composed_field_info(tape(t)%hlist(f)%field%name,is_composed,fname1=field1,fname2=field2)
+ if (is_composed) then
+ if (len_trim(field1) > 0 .and. len_trim(field2) > 0) then
+ ! set field1/field2 names for htape from the masterfield list
+ tape(t)%hlist(f)%op_field1=trim(field1)
+ tape(t)%hlist(f)%op_field2=trim(field2)
+ ! find ids for field1/2
+ do ff = 1, nflds(t)
+ if (trim(field1) == trim(tape(t)%hlist(ff)%field%name)) then
+ tape(t)%hlist(f)%field%op_field1_id = ff
+ end if
+ if (trim(field2) == trim(tape(t)%hlist(ff)%field%name)) then
+ tape(t)%hlist(f)%field%op_field2_id = ff
+ end if
+ end do
+ if (tape(t)%hlist(f)%field%op_field1_id == -1) then
+ call endrun(trim(subname)//': No op_field1 match for '//trim(tape(t)%hlist(f)%field%name))
+ end if
+ if (tape(t)%hlist(f)%field%op_field2_id == -1) then
+ call endrun(trim(subname)//': No op_field2 match for '//trim(tape(t)%hlist(f)%field%name))
+ end if
+ else
+ call endrun(trim(subname)//': Component fields not found for composed field')
+ end if
+ end if
+ end do
+ end subroutine define_composed_field_ids
+
subroutine restart_vars_setnames()
! Local variable
@@ -1077,6 +1165,25 @@ subroutine restart_vars_setnames()
restartvars(rvindex)%fillset = .true.
restartvars(rvindex)%ifill = 0
+ rvindex = rvindex + 1
+ restartvars(rvindex)%name = 'beg_nstep'
+ restartvars(rvindex)%type = pio_int
+ restartvars(rvindex)%ndims = 2
+ restartvars(rvindex)%dims(1) = maxnflds_dim_ind
+ restartvars(rvindex)%dims(2) = ptapes_dim_ind
+ restartvars(rvindex)%fillset = .true.
+ restartvars(rvindex)%ifill = 0
+
+ rvindex = rvindex + 1
+ restartvars(rvindex)%name = 'hbuf_integral'
+ restartvars(rvindex)%type = pio_double
+ restartvars(rvindex)%ndims = 2
+ restartvars(rvindex)%dims(1) = maxnflds_dim_ind
+ restartvars(rvindex)%dims(2) = ptapes_dim_ind
+ restartvars(rvindex)%fillset = .true.
+ restartvars(rvindex)%ifill = 0
+
+
rvindex = rvindex + 1
restartvars(rvindex)%name = 'avgflag'
restartvars(rvindex)%type = pio_char
@@ -1217,6 +1324,48 @@ subroutine restart_vars_setnames()
restartvars(rvindex)%fillset = .true.
restartvars(rvindex)%ifill = 0
+ rvindex = rvindex + 1
+ restartvars(rvindex)%name = 'field_op'
+ restartvars(rvindex)%type = pio_char
+ restartvars(rvindex)%ndims = 3
+ restartvars(rvindex)%dims(1) = max_chars_dim_ind
+ restartvars(rvindex)%dims(2) = maxnflds_dim_ind
+ restartvars(rvindex)%dims(3) = ptapes_dim_ind
+
+ rvindex = rvindex + 1
+ restartvars(rvindex)%name = 'op_field1_id'
+ restartvars(rvindex)%type = pio_int
+ restartvars(rvindex)%ndims = 2
+ restartvars(rvindex)%dims(1) = maxnflds_dim_ind
+ restartvars(rvindex)%dims(2) = ptapes_dim_ind
+ restartvars(rvindex)%fillset = .true.
+ restartvars(rvindex)%ifill = 0
+
+ rvindex = rvindex + 1
+ restartvars(rvindex)%name = 'op_field2_id'
+ restartvars(rvindex)%type = pio_int
+ restartvars(rvindex)%ndims = 2
+ restartvars(rvindex)%dims(1) = maxnflds_dim_ind
+ restartvars(rvindex)%dims(2) = ptapes_dim_ind
+ restartvars(rvindex)%fillset = .true.
+ restartvars(rvindex)%ifill = 0
+
+ rvindex = rvindex + 1
+ restartvars(rvindex)%name = 'op_field1'
+ restartvars(rvindex)%type = pio_char
+ restartvars(rvindex)%ndims = 3
+ restartvars(rvindex)%dims(1) = max_fieldname_len_dim_ind
+ restartvars(rvindex)%dims(2) = maxnflds_dim_ind
+ restartvars(rvindex)%dims(3) = ptapes_dim_ind
+
+ rvindex = rvindex + 1
+ restartvars(rvindex)%name = 'op_field2'
+ restartvars(rvindex)%type = pio_char
+ restartvars(rvindex)%ndims = 3
+ restartvars(rvindex)%dims(1) = max_fieldname_len_dim_ind
+ restartvars(rvindex)%dims(2) = maxnflds_dim_ind
+ restartvars(rvindex)%dims(3) = ptapes_dim_ind
+
end subroutine restart_vars_setnames
subroutine restart_dims_setnames()
@@ -1366,6 +1515,8 @@ subroutine write_restart_history ( File, &
type(var_desc_t), pointer :: longname_desc
type(var_desc_t), pointer :: units_desc
type(var_desc_t), pointer :: hwrt_prec_desc
+ type(var_desc_t), pointer :: hbuf_integral_desc
+ type(var_desc_t), pointer :: beg_nstep_desc
type(var_desc_t), pointer :: xyfill_desc
type(var_desc_t), pointer :: mdims_desc ! mdim name indices
type(var_desc_t), pointer :: mdimname_desc ! mdim names
@@ -1378,6 +1529,11 @@ subroutine write_restart_history ( File, &
type(var_desc_t), pointer :: interpolate_nlon_desc
type(var_desc_t), pointer :: meridional_complement_desc
type(var_desc_t), pointer :: zonal_complement_desc
+ type(var_desc_t), pointer :: field_op_desc
+ type(var_desc_t), pointer :: op_field1_id_desc
+ type(var_desc_t), pointer :: op_field2_id_desc
+ type(var_desc_t), pointer :: op_field1_desc
+ type(var_desc_t), pointer :: op_field2_desc
integer, allocatable :: allmdims(:,:,:)
integer, allocatable :: xyfill(:,:)
@@ -1385,7 +1541,7 @@ subroutine write_restart_history ( File, &
integer, allocatable :: interp_output(:)
integer :: maxnflds
-
+ real(r8) :: integral ! hbuf area weighted integral
maxnflds = maxval(nflds)
allocate(xyfill(maxnflds, ptapes))
@@ -1479,6 +1635,8 @@ subroutine write_restart_history ( File, &
decomp_type_desc => restartvar_getdesc('decomp_type')
numlev_desc => restartvar_getdesc('numlev')
hwrt_prec_desc => restartvar_getdesc('hwrt_prec')
+ hbuf_integral_desc => restartvar_getdesc('hbuf_integral')
+ beg_nstep_desc => restartvar_getdesc('beg_nstep')
sseq_desc => restartvar_getdesc('sampling_seq')
cm_desc => restartvar_getdesc('cell_methods')
@@ -1497,6 +1655,12 @@ subroutine write_restart_history ( File, &
meridional_complement_desc => restartvar_getdesc('meridional_complement')
zonal_complement_desc => restartvar_getdesc('zonal_complement')
+ field_op_desc => restartvar_getdesc('field_op')
+ op_field1_id_desc => restartvar_getdesc('op_field1_id')
+ op_field2_id_desc => restartvar_getdesc('op_field2_id')
+ op_field1_desc => restartvar_getdesc('op_field1')
+ op_field2_desc => restartvar_getdesc('op_field2')
+
mdims_desc => restartvar_getdesc('mdims')
mdimname_desc => restartvar_getdesc('mdimnames')
fillval_desc => restartvar_getdesc('fillvalue')
@@ -1519,6 +1683,9 @@ subroutine write_restart_history ( File, &
ierr = pio_put_var(File, numlev_desc,start,tape(t)%hlist(f)%field%numlev)
ierr = pio_put_var(File, hwrt_prec_desc,start,tape(t)%hlist(f)%hwrt_prec)
+ call tape(t)%hlist(f)%get_global(integral)
+ ierr = pio_put_var(File, hbuf_integral_desc,start,integral)
+ ierr = pio_put_var(File, beg_nstep_desc,start,tape(t)%hlist(f)%beg_nstep)
ierr = pio_put_var(File, sseq_desc,startc,tape(t)%hlist(f)%field%sampling_seq)
ierr = pio_put_var(File, cm_desc,startc,tape(t)%hlist(f)%field%cell_methods)
ierr = pio_put_var(File, longname_desc,startc,tape(t)%hlist(f)%field%long_name)
@@ -1528,6 +1695,11 @@ subroutine write_restart_history ( File, &
ierr = pio_put_var(File, fillval_desc,start, tape(t)%hlist(f)%field%fillvalue)
ierr = pio_put_var(File, meridional_complement_desc,start, tape(t)%hlist(f)%field%meridional_complement)
ierr = pio_put_var(File, zonal_complement_desc,start, tape(t)%hlist(f)%field%zonal_complement)
+ ierr = pio_put_var(File, field_op_desc,startc, tape(t)%hlist(f)%field%field_op)
+ ierr = pio_put_var(File, op_field1_id_desc,start, tape(t)%hlist(f)%field%op_field1_id)
+ ierr = pio_put_var(File, op_field2_id_desc,start, tape(t)%hlist(f)%field%op_field2_id)
+ ierr = pio_put_var(File, op_field1_desc,startc, tape(t)%hlist(f)%op_field1)
+ ierr = pio_put_var(File, op_field2_desc,startc, tape(t)%hlist(f)%op_field2)
if(associated(tape(t)%hlist(f)%field%mdims)) then
allmdims(1:size(tape(t)%hlist(f)%field%mdims),f,t) = tape(t)%hlist(f)%field%mdims
else
@@ -1591,11 +1763,13 @@ subroutine read_restart_history (File)
use ioFileMod, only: getfil
use sat_hist, only: sat_hist_define, sat_hist_init
use cam_grid_support, only: cam_grid_read_dist_array, cam_grid_num_grids
- use cam_history_support, only: get_hist_coord_index, add_hist_coord
+ use cam_history_support, only: get_hist_coord_index, add_hist_coord, dim_index_2d
use constituents, only: cnst_get_ind, cnst_get_type_byind
+ use cam_grid_support, only: cam_grid_get_areawt
use shr_sys_mod, only: shr_sys_getenv
use spmd_utils, only: mpicom, mpi_character, masterprocid
+ use time_manager, only: get_nstep
!
!-----------------------------------------------------------------------
!
@@ -1619,8 +1793,11 @@ subroutine read_restart_history (File)
character(len=max_string_len) :: locfn ! Local filename
character(len=max_fieldname_len), allocatable :: tmpname(:,:)
+ character(len=max_fieldname_len), allocatable :: tmpf1name(:,:)
+ character(len=max_fieldname_len), allocatable :: tmpf2name(:,:)
integer, allocatable :: decomp(:,:), tmpnumlev(:,:)
- integer, pointer :: nacs(:,:) ! accumulation counter
+ integer, pointer :: nacs(:,:) ! outfld accumulation counter
+ integer :: beg_nstep ! start timestep of this slice for nstep accumulation counter
character(len=max_fieldname_len) :: fname_tmp ! local copy of field name
character(len=max_fieldname_len) :: dname_tmp ! local copy of dim name
@@ -1635,7 +1812,15 @@ subroutine read_restart_history (File)
type(var_desc_t) :: fillval_desc
type(var_desc_t) :: meridional_complement_desc
type(var_desc_t) :: zonal_complement_desc
+ type(var_desc_t) :: field_op_desc
+ type(var_desc_t) :: op_field1_id_desc
+ type(var_desc_t) :: op_field2_id_desc
+ type(var_desc_t) :: op_field1_desc
+ type(var_desc_t) :: op_field2_desc
+ type(dim_index_2d) :: dimind ! 2-D dimension index
integer, allocatable :: tmpprec(:,:)
+ real(r8), allocatable :: tmpintegral(:,:)
+ integer, allocatable :: tmpbeg_nstep(:,:)
integer, allocatable :: xyfill(:,:)
integer, allocatable :: allmdims(:,:,:)
integer, allocatable :: is_subcol(:,:)
@@ -1658,6 +1843,8 @@ subroutine read_restart_history (File)
integer :: fdecomp ! Grid ID for field
integer :: idx
character(len=3) :: mixing_ratio
+ integer :: c,ib,ie,jb,je,k,cnt,wtidx(1)
+ real(r8), pointer :: areawt(:) ! pointer to areawt values for attribute
!
! Get users logname and machine hostname
@@ -1735,33 +1922,38 @@ subroutine read_restart_history (File)
ierr = pio_inq_varid(File, 'lcltod_stop', vdesc)
ierr = pio_get_var(File, vdesc, lcltod_stop(1:mtapes))
-
-
-
allocate(tmpname(maxnflds, mtapes), decomp(maxnflds, mtapes), tmpnumlev(maxnflds,mtapes))
ierr = pio_inq_varid(File, 'field_name', vdesc)
ierr = pio_get_var(File, vdesc, tmpname)
-
ierr = pio_inq_varid(File, 'decomp_type', vdesc)
ierr = pio_get_var(File, vdesc, decomp)
ierr = pio_inq_varid(File, 'numlev', vdesc)
ierr = pio_get_var(File, vdesc, tmpnumlev)
- allocate(tmpprec(maxnflds,mtapes))
+ ierr = pio_inq_varid(File, 'hbuf_integral',vdesc)
+ allocate(tmpintegral(maxnflds,mtapes))
+ ierr = pio_get_var(File, vdesc, tmpintegral(:,:))
+
+
ierr = pio_inq_varid(File, 'hwrt_prec',vdesc)
+ allocate(tmpprec(maxnflds,mtapes))
ierr = pio_get_var(File, vdesc, tmpprec(:,:))
- allocate(xyfill(maxnflds,mtapes))
+ ierr = pio_inq_varid(File, 'beg_nstep',vdesc)
+ allocate(tmpbeg_nstep(maxnflds,mtapes))
+ ierr = pio_get_var(File, vdesc, tmpbeg_nstep(:,:))
+
ierr = pio_inq_varid(File, 'xyfill', vdesc)
+ allocate(xyfill(maxnflds,mtapes))
ierr = pio_get_var(File, vdesc, xyfill)
- allocate(is_subcol(maxnflds,mtapes))
ierr = pio_inq_varid(File, 'is_subcol', vdesc)
+ allocate(is_subcol(maxnflds,mtapes))
ierr = pio_get_var(File, vdesc, is_subcol)
!! interpolated output
- allocate(interp_output(mtapes))
ierr = pio_inq_varid(File, 'interpolate_output', vdesc)
+ allocate(interp_output(mtapes))
ierr = pio_get_var(File, vdesc, interp_output)
interpolate_output(1:mtapes) = interp_output(1:mtapes) > 0
if (ptapes > mtapes) then
@@ -1816,6 +2008,13 @@ subroutine read_restart_history (File)
end if
end do
+ allocate(tmpf1name(maxnflds, mtapes), tmpf2name(maxnflds, mtapes))
+ ierr = pio_inq_varid(File, 'op_field1', vdesc)
+ ierr = pio_get_var(File, vdesc, tmpf1name)
+ ierr = pio_inq_varid(File, 'op_field2', vdesc)
+ ierr = pio_get_var(File, vdesc, tmpf2name)
+
+
ierr = pio_inq_varid(File, 'avgflag', avgflag_desc)
ierr = pio_inq_varid(File, 'long_name', longname_desc)
@@ -1826,6 +2025,9 @@ subroutine read_restart_history (File)
ierr = pio_inq_varid(File, 'fillvalue', fillval_desc)
ierr = pio_inq_varid(File, 'meridional_complement', meridional_complement_desc)
ierr = pio_inq_varid(File, 'zonal_complement', zonal_complement_desc)
+ ierr = pio_inq_varid(File, 'field_op', field_op_desc)
+ ierr = pio_inq_varid(File, 'op_field1_id', op_field1_id_desc)
+ ierr = pio_inq_varid(File, 'op_field2_id', op_field2_id_desc)
rgnht(:)=.false.
@@ -1851,6 +2053,11 @@ subroutine read_restart_history (File)
ierr = pio_get_var(File,fillval_desc, (/f,t/), tape(t)%hlist(f)%field%fillvalue)
ierr = pio_get_var(File,meridional_complement_desc, (/f,t/), tape(t)%hlist(f)%field%meridional_complement)
ierr = pio_get_var(File,zonal_complement_desc, (/f,t/), tape(t)%hlist(f)%field%zonal_complement)
+ tape(t)%hlist(f)%field%field_op(1:field_op_len) = ' '
+ ierr = pio_get_var(File,field_op_desc, (/1,f,t/), tape(t)%hlist(f)%field%field_op)
+ call strip_null(tape(t)%hlist(f)%field%field_op)
+ ierr = pio_get_var(File,op_field1_id_desc, (/f,t/), tape(t)%hlist(f)%field%op_field1_id)
+ ierr = pio_get_var(File,op_field2_id_desc, (/f,t/), tape(t)%hlist(f)%field%op_field2_id)
ierr = pio_get_var(File,avgflag_desc, (/f,t/), tape(t)%hlist(f)%avgflag)
ierr = pio_get_var(File,longname_desc, (/1,f,t/), tape(t)%hlist(f)%field%long_name)
ierr = pio_get_var(File,units_desc, (/1,f,t/), tape(t)%hlist(f)%field%units)
@@ -1871,11 +2078,16 @@ subroutine read_restart_history (File)
tape(t)%hlist(f)%field%is_subcol=.false.
end if
call strip_null(tmpname(f,t))
+ call strip_null(tmpf1name(f,t))
+ call strip_null(tmpf2name(f,t))
tape(t)%hlist(f)%field%name = tmpname(f,t)
+ tape(t)%hlist(f)%op_field1 = tmpf1name(f,t)
+ tape(t)%hlist(f)%op_field2 = tmpf2name(f,t)
tape(t)%hlist(f)%field%decomp_type = decomp(f,t)
tape(t)%hlist(f)%field%numlev = tmpnumlev(f,t)
tape(t)%hlist(f)%hwrt_prec = tmpprec(f,t)
-
+ tape(t)%hlist(f)%beg_nstep = tmpbeg_nstep(f,t)
+ call tape(t)%hlist(f)%put_global(tmpintegral(f,t))
! If the field is an advected constituent set the mixing_ratio attribute
fname_tmp = strip_suffix(tape(t)%hlist(f)%field%name)
call cnst_get_ind(fname_tmp, idx, abort=.false.)
@@ -1892,11 +2104,14 @@ subroutine read_restart_history (File)
tape(t)%hlist(f)%field%mdims(i) = get_hist_coord_index(mdimnames(allmdims(i,f,t)))
end do
end if
-
end do
end do
- deallocate(tmpname, tmpnumlev, tmpprec, decomp, xyfill, is_subcol)
+ deallocate(tmpname, tmpnumlev, tmpprec, tmpbeg_nstep, decomp, xyfill, is_subcol, tmpintegral)
deallocate(mdimnames)
+ deallocate(tmpf1name,tmpf2name)
+
+ allocate(grid_wts(cam_grid_num_grids() + 1))
+ allgrids_wt => grid_wts
allocate(gridsontape(cam_grid_num_grids() + 1, ptapes))
gridsontape = -1
@@ -1943,7 +2158,39 @@ subroutine read_restart_history (File)
exit
end if
end do
+ !
+ !rebuild area wt array and set field wbuf pointer
+ !
+ if (tape(t)%hlist(f)%avgflag .eq. 'N') then ! set up area weight buffer
+ nullify(tape(t)%hlist(f)%wbuf)
+ if (any(allgrids_wt(:)%decomp_type == tape(t)%hlist(f)%field%decomp_type)) then
+ wtidx=MAXLOC(allgrids_wt(:)%decomp_type, MASK = allgrids_wt(:)%decomp_type .EQ. fdecomp)
+ tape(t)%hlist(f)%wbuf => allgrids_wt(wtidx(1))%wbuf
+ else
+ ! area weights not found for this grid, then create them
+ ! first check for an available spot in the array
+ if (any(allgrids_wt(:)%decomp_type == -1)) then
+ wtidx=MINLOC(allgrids_wt(:)%decomp_type)
+ else
+ call endrun('cam_history.F90:read_restart_history: Error initializing allgrids_wt with area weights')
+ end if
+ allgrids_wt(wtidx)%decomp_type=fdecomp
+ areawt => cam_grid_get_areawt(fdecomp)
+ allocate(allgrids_wt(wtidx(1))%wbuf(begdim1:enddim1,begdim3:enddim3))
+ cnt=0
+ do c=begdim3,enddim3
+ dimind = tape(t)%hlist(f)%field%get_dims(c)
+ ib=dimind%beg1
+ ie=dimind%end1
+ do i=ib,ie
+ cnt=cnt+1
+ allgrids_wt(wtidx(1))%wbuf(i,c)=areawt(cnt)
+ end do
+ end do
+ tape(t)%hlist(f)%wbuf => allgrids_wt(wtidx(1))%wbuf
+ endif
+ endif
end do
end do
!
@@ -2050,6 +2297,9 @@ subroutine read_restart_history (File)
tape(t)%hlist(f)%nacs(1,:)= nacsval
end if
+ ierr = pio_inq_varid(tape(t)%File, trim(fname_tmp)//'_nacs', vdesc)
+ call cam_pio_var_info(tape(t)%File, vdesc, nacsdimcnt, dimids, dimlens)
+
end do
!
! Done reading this history restart file
@@ -2210,6 +2460,8 @@ subroutine AvgflagToString(avgflag, time_op)
time_op(:) = 'mean'
case ('B')
time_op(:) = 'mean00z'
+ case ('N')
+ time_op(:) = 'mean_over_nsteps'
case ('I')
time_op(:) = ' '
case ('X')
@@ -2430,6 +2682,8 @@ subroutine fldlst ()
end if
+ allocate(grid_wts(cam_grid_num_grids() + 1))
+ allgrids_wt => grid_wts
allocate(gridsontape(cam_grid_num_grids() + 1, ptapes))
gridsontape = -1
@@ -2510,6 +2764,7 @@ subroutine fldlst ()
do ff=1,nflds(t)
nullify(tape(t)%hlist(ff)%hbuf)
nullify(tape(t)%hlist(ff)%sbuf)
+ nullify(tape(t)%hlist(ff)%wbuf)
nullify(tape(t)%hlist(ff)%nacs)
nullify(tape(t)%hlist(ff)%varid)
end do
@@ -2580,6 +2835,9 @@ subroutine fldlst ()
end do
end do
+ ! Initialize the field names/ids for each composed field on tapes
+ call define_composed_field_ids(t)
+
end do ! do t=1,ptapes
deallocate(gridsontape)
@@ -3283,6 +3541,7 @@ end subroutine subcol_field_avg_handler
type (active_entry), pointer :: otape(:) ! Local history_tape pointer
real(r8),pointer :: hbuf(:,:) ! history buffer
+ real(r8),pointer :: wbuf(:) ! area weights for field
real(r8),pointer :: sbuf(:,:) ! variance buffer
integer, pointer :: nacs(:) ! accumulation counter
integer :: begdim2, enddim2, endi
@@ -3322,6 +3581,9 @@ end subroutine subcol_field_avg_handler
avgflag = otape(t)%hlist(f)%avgflag
nacs => otape(t)%hlist(f)%nacs(:,c)
hbuf => otape(t)%hlist(f)%hbuf(:,:,c)
+ if (associated(tape(t)%hlist(f)%wbuf)) then
+ wbuf => otape(t)%hlist(f)%wbuf(:,c)
+ endif
if (associated(tape(t)%hlist(f)%sbuf)) then
sbuf => otape(t)%hlist(f)%sbuf(:,:,c)
endif
@@ -3395,6 +3657,10 @@ end subroutine subcol_field_avg_handler
call hbuf_accum_add00z(hbuf, ufield, nacs, dimind, pcols, &
flag_xyfill, fillvalue)
+ case ('N') ! Time average over nsteps
+ call hbuf_accum_add(hbuf, ufield, nacs, dimind, pcols, &
+ flag_xyfill, fillvalue)
+
case ('X') ! Maximum over time
call hbuf_accum_max (hbuf, ufield, nacs, dimind, pcols, &
flag_xyfill, fillvalue)
@@ -3433,6 +3699,10 @@ end subroutine subcol_field_avg_handler
call hbuf_accum_add00z(hbuf, field, nacs, dimind, idim, &
flag_xyfill, fillvalue)
+ case ('N') ! Time average over nsteps
+ call hbuf_accum_add (hbuf, field, nacs, dimind, idim, &
+ flag_xyfill, fillvalue)
+
case ('X') ! Maximum over time
call hbuf_accum_max (hbuf, field, nacs, dimind, idim, &
flag_xyfill, fillvalue)
@@ -3464,7 +3734,7 @@ end subroutine outfld
!#######################################################################
- subroutine get_field_properties(fname, found, tape_out, ff_out, no_tape_check_in)
+ subroutine get_field_properties(fname, found, tape_out, ff_out, no_tape_check_in, f_out)
implicit none
!
@@ -3487,6 +3757,7 @@ subroutine get_field_properties(fname, found, tape_out, ff_out, no_tape_check_in
type(active_entry), pointer, optional :: tape_out(:)
integer, intent(out), optional :: ff_out
logical, intent(in), optional :: no_tape_check_in
+ integer, intent(out), optional :: f_out(:)
!
! Local variables
@@ -3515,6 +3786,9 @@ subroutine get_field_properties(fname, found, tape_out, ff_out, no_tape_check_in
if (present(ff_out)) then
ff_out = -1
end if
+ if (present(f_out)) then
+ f_out = -1
+ end if
!
! If ( ff < 0 ), the field is not defined on the masterlist. This check
@@ -3548,8 +3822,12 @@ subroutine get_field_properties(fname, found, tape_out, ff_out, no_tape_check_in
if (present(ff_out)) then
ff_out = ff
end if
- ! We found the info so we are done with the loop
- exit
+ if (present(f_out)) then
+ f_out(t) = masterlist(ff)%thisentry%htapeindx(t)
+ else
+ ! only need to loop through all ptapes if f_out present
+ exit
+ end if
end if
end do
@@ -3834,15 +4112,16 @@ subroutine h_override (t)
type(master_entry), pointer :: listentry
-
avgflg = avgflag_pertape(t)
-
listentry=>masterlinkedlist
do while(associated(listentry))
- call AvgflagToString(avgflg, listentry%time_op(t))
- listentry%avgflag(t) = avgflag_pertape(t)
- listentry=>listentry%next_entry
+ ! Budgets require flag to be N, dont override
+ if (listentry%avgflag(t) /= 'N' ) then
+ call AvgflagToString(avgflg, listentry%time_op(t))
+ listentry%avgflag(t) = avgflag_pertape(t)
+ end if
+ listentry=>listentry%next_entry
end do
end subroutine h_override
@@ -4547,6 +4826,7 @@ end subroutine h_define
subroutine h_normalize (f, t)
use cam_history_support, only: dim_index_2d
+ use time_manager, only: get_nstep
!
!-----------------------------------------------------------------------
@@ -4572,10 +4852,13 @@ subroutine h_normalize (f, t)
integer :: begdim3, enddim3 ! Chunk or block bounds
integer :: k ! level
integer :: i, ii
+ integer :: currstep, nsteps
real(r8) :: variance, tmpfill
logical :: flag_xyfill ! non-applicable xy points flagged with fillvalue
character*1 :: avgflag ! averaging flag
+ character(len=max_chars) :: errmsg
+ character(len=*), parameter :: sub='H_NORMALIZE:'
call t_startf ('h_normalize')
@@ -4620,6 +4903,20 @@ subroutine h_normalize (f, t)
end do
end if
end if
+ currstep=get_nstep()
+ if (avgflag == 'N' .and. currstep > 0) then
+ if( currstep > tape(t)%hlist(f)%beg_nstep) then
+ nsteps=currstep-tape(t)%hlist(f)%beg_nstep
+ do k=jb,je
+ tape(t)%hlist(f)%hbuf(ib:ie,k,c) = &
+ tape(t)%hlist(f)%hbuf(ib:ie,k,c) &
+ / nsteps
+ end do
+ else
+ write(errmsg,*) sub,'FATAL: bad nstep normalization, currstep, beg_nstep=',currstep,',',tape(t)%hlist(f)%beg_nstep
+ call endrun(trim(errmsg))
+ end if
+ end if
if (avgflag == 'S') then
! standard deviation ...
! from http://www.johndcook.com/blog/standard_deviation/
@@ -4647,6 +4944,7 @@ end subroutine h_normalize
subroutine h_zero (f, t)
use cam_history_support, only: dim_index_2d
+ use time_manager, only: get_nstep, is_first_restart_step
!
!-----------------------------------------------------------------------
!
@@ -4679,6 +4977,9 @@ subroutine h_zero (f, t)
end do
tape(t)%hlist(f)%nacs(:,:) = 0
+ !Don't reset beg_nstep if this is a restart
+ if (.not. is_first_restart_step()) tape(t)%hlist(f)%beg_nstep = get_nstep()
+
call t_stopf ('h_zero')
return
@@ -4686,6 +4987,127 @@ end subroutine h_zero
!#######################################################################
+ subroutine h_global (f, t)
+
+ use cam_history_support, only: dim_index_2d
+ use shr_reprosum_mod, only: shr_reprosum_calc
+ use spmd_utils, only: mpicom
+ use shr_const_mod, only: PI => SHR_CONST_PI
+ !
+ !-----------------------------------------------------------------------
+ !
+ ! Purpose: compute globals of field
+ !
+ ! Method: Loop through fields on the tape
+ !
+ !-----------------------------------------------------------------------
+ !
+ integer, intent(in) :: f ! field index
+ integer, intent(in) :: t ! tape index
+ !
+ ! Local workspace
+ !
+ type (dim_index_2d) :: dimind ! 2-D dimension index
+ integer :: ie ! dim3 index
+ integer :: count ! tmp index
+ integer :: i1 ! dim1 index
+ integer :: j1 ! dim2 index
+ integer :: fdims(3) ! array shape
+ integer :: begdim1,enddim1,begdim2,enddim2,begdim3,enddim3 !
+ real(r8) :: globalsum(1) ! globalsum
+ real(r8), allocatable :: globalarr(:) ! globalarr values for this pe
+
+ call t_startf ('h_global')
+
+ ! wbuf contains the area weighting for this field decomposition
+ if (associated(tape(t)%hlist(f)%wbuf) ) then
+
+ begdim1 = tape(t)%hlist(f)%field%begdim1
+ enddim1 = tape(t)%hlist(f)%field%enddim1
+ fdims(1) = enddim1 - begdim1 + 1
+ begdim2 = tape(t)%hlist(f)%field%begdim2
+ enddim2 = tape(t)%hlist(f)%field%enddim2
+ fdims(2) = enddim2 - begdim2 + 1
+ begdim3 = tape(t)%hlist(f)%field%begdim3
+ enddim3 = tape(t)%hlist(f)%field%enddim3
+ fdims(3) = enddim3 - begdim3 + 1
+
+ allocate(globalarr(fdims(1)*fdims(2)*fdims(3)))
+ count=0
+ globalarr=0._r8
+ do ie = begdim3, enddim3
+ dimind = tape(t)%hlist(f)%field%get_dims(ie)
+ do j1 = dimind%beg2, dimind%end2
+ do i1 = dimind%beg1, dimind%end1
+ count=count+1
+ globalarr(count)=globalarr(count)+tape(t)%hlist(f)%hbuf(i1,j1,ie)*tape(t)%hlist(f)%wbuf(i1,ie)
+ end do
+ end do
+ end do
+ ! call fixed-point algorithm
+ call shr_reprosum_calc (globalarr, globalsum, count, count, 1, commid=mpicom)
+ if (masterproc) write(iulog,*)'h_global:field:',trim(tape(t)%hlist(f)%field%name),' global integral=',globalsum(1)
+ ! store global entry for this history tape entry
+ call tape(t)%hlist(f)%put_global(globalsum(1))
+ ! deallocate temp array
+ deallocate(globalarr)
+ end if
+ call t_stopf ('h_global')
+ end subroutine h_global
+
+ subroutine h_field_op (f, t)
+ use cam_history_support, only: dim_index_2d
+ !
+ !-----------------------------------------------------------------------
+ !
+ ! Purpose: run field sum or dif opperation on all contructed fields
+ !
+ ! Method: Loop through fields on the tape
+ !
+ !-----------------------------------------------------------------------
+ !
+ integer, intent(in) :: f ! field index
+ integer, intent(in) :: t ! tape index
+ !
+ ! Local workspace
+ !
+ type (dim_index_2d) :: dimind ! 2-D dimension index
+ integer :: c ! chunk index
+ integer :: f1,f2 ! fields to be operated on
+ integer :: begdim1, begdim2, begdim3 ! on-node chunk or lat start index
+ integer :: enddim1, enddim2, enddim3 ! on-node chunk or lat end index
+ character(len=field_op_len) :: optype ! field operation only sum or diff supported
+
+ call t_startf ('h_field_op')
+ f1 = tape(t)%hlist(f)%field%op_field1_id
+ f2 = tape(t)%hlist(f)%field%op_field2_id
+ optype = trim(adjustl(tape(t)%hlist(f)%field%field_op))
+
+ begdim3 = tape(t)%hlist(f)%field%begdim3
+ enddim3 = tape(t)%hlist(f)%field%enddim3
+
+ do c = begdim3, enddim3
+ dimind = tape(t)%hlist(f)%field%get_dims(c)
+ if (trim(optype) == 'dif') then
+ tape(t)%hlist(f)%hbuf(dimind%beg1:dimind%end1,dimind%beg2:dimind%end2,c) = &
+ tape(t)%hlist(f1)%hbuf(dimind%beg1:dimind%end1,dimind%beg2:dimind%end2,c) - &
+ tape(t)%hlist(f2)%hbuf(dimind%beg1:dimind%end1,dimind%beg2:dimind%end2,c)
+ else if (trim(optype) == 'sum') then
+ tape(t)%hlist(f)%hbuf(dimind%beg1:dimind%end1,dimind%beg2:dimind%end2,c) = &
+ tape(t)%hlist(f1)%hbuf(dimind%beg1:dimind%end1,dimind%beg2:dimind%end2,c) + &
+ tape(t)%hlist(f2)%hbuf(dimind%beg1:dimind%end1,dimind%beg2:dimind%end2,c)
+ else
+ call endrun('h_field_op: ERROR: composed field operation type unknown:'//trim(optype))
+ end if
+ end do
+ ! Set nsteps for composed fields using value of one of the component fields
+ tape(t)%hlist(f)%beg_nstep=tape(t)%hlist(f1)%beg_nstep
+ tape(t)%hlist(f)%nacs(:,:)=tape(t)%hlist(f1)%nacs(:,:)
+ call t_stopf ('h_field_op')
+ end subroutine h_field_op
+
+ !#######################################################################
+
subroutine dump_field (f, t, restart)
use cam_history_support, only: history_patch_t, dim_index_2d, dim_index_3d
use cam_grid_support, only: cam_grid_write_dist_array, cam_grid_dimensions
@@ -5158,13 +5580,23 @@ subroutine wshist (rgnht_in)
ierr = pio_put_var (tape(t)%File, tape(t)%time_writtenid, startc, countc, (/ctime/))
if(.not. restart) then
- !$OMP PARALLEL DO PRIVATE (F)
- do f=1,nflds(t)
- ! Normalized averaged fields
- if (tape(t)%hlist(f)%avgflag /= 'I') then
- call h_normalize (f, t)
- end if
- end do
+ !$OMP PARALLEL DO PRIVATE (F)
+ do f=1,nflds(t)
+ ! Normalize all non composed fields, composed fields are calculated next using the normalized components
+ if (tape(t)%hlist(f)%avgflag /= 'I'.and..not.tape(t)%hlist(f)%field%is_composed()) then
+ call h_normalize (f, t)
+ end if
+ end do
+ end if
+
+ if(.not. restart) then
+ !$OMP PARALLEL DO PRIVATE (F)
+ do f=1,nflds(t)
+ ! calculate composed fields from normalized components
+ if (tape(t)%hlist(f)%field%is_composed()) then
+ call h_field_op (f, t)
+ end if
+ end do
end if
!
! Write field to history tape. Note that this is NOT threaded due to netcdf limitations
@@ -5175,11 +5607,14 @@ subroutine wshist (rgnht_in)
end do
call t_stopf ('dump_field')
!
+ ! Calculate globals
+ !
+ do f=1,nflds(t)
+ call h_global(f, t)
+ end do
+ !
! Zero history buffers and accumulators now that the fields have been written.
!
-
-
-
if(restart) then
do f=1,nflds(t)
if(associated(tape(t)%hlist(f)%varid)) then
@@ -5205,7 +5640,8 @@ end subroutine wshist
!#######################################################################
subroutine addfld_1d(fname, vdim_name, avgflag, units, long_name, &
- gridname, flag_xyfill, sampling_seq, standard_name, fill_value)
+ gridname, flag_xyfill, sampling_seq, standard_name, fill_value, &
+ optype, op_f1name, op_f2name)
!
!-----------------------------------------------------------------------
@@ -5234,7 +5670,9 @@ subroutine addfld_1d(fname, vdim_name, avgflag, units, long_name, &
! every other; only during LW/SW radiation calcs, etc.
character(len=*), intent(in), optional :: standard_name ! CF standard name (max_chars)
real(r8), intent(in), optional :: fill_value
-
+ character(len=*), intent(in), optional :: optype ! currently 'dif' or 'sum' is supported
+ character(len=*), intent(in), optional :: op_f1name ! first field to be operated on
+ character(len=*), intent(in), optional :: op_f2name ! second field which is subtracted from or added to first field
!
! Local workspace
!
@@ -5252,12 +5690,14 @@ subroutine addfld_1d(fname, vdim_name, avgflag, units, long_name, &
dimnames(1) = trim(vdim_name)
end if
call addfld(fname, dimnames, avgflag, units, long_name, gridname, &
- flag_xyfill, sampling_seq, standard_name, fill_value)
+ flag_xyfill, sampling_seq, standard_name, fill_value, optype, op_f1name, &
+ op_f2name)
end subroutine addfld_1d
subroutine addfld_nd(fname, dimnames, avgflag, units, long_name, &
- gridname, flag_xyfill, sampling_seq, standard_name, fill_value)
+ gridname, flag_xyfill, sampling_seq, standard_name, fill_value, optype, &
+ op_f1name, op_f2name)
!
!-----------------------------------------------------------------------
@@ -5272,7 +5712,7 @@ subroutine addfld_nd(fname, dimnames, avgflag, units, long_name, &
use cam_history_support, only: fillvalue, hist_coord_find_levels
use cam_grid_support, only: cam_grid_id, cam_grid_is_zonal
use cam_grid_support, only: cam_grid_get_coord_names
- use constituents, only: pcnst, cnst_get_ind, cnst_get_type_byind
+ use constituents, only: cnst_get_ind, cnst_get_type_byind
!
! Arguments
@@ -5290,6 +5730,9 @@ subroutine addfld_nd(fname, dimnames, avgflag, units, long_name, &
! every other; only during LW/SW radiation calcs, etc.
character(len=*), intent(in), optional :: standard_name ! CF standard name (max_chars)
real(r8), intent(in), optional :: fill_value
+ character(len=*), intent(in), optional :: optype ! currently 'dif' or 'sum' supported
+ character(len=*), intent(in), optional :: op_f1name ! first field to be operated on
+ character(len=*), intent(in), optional :: op_f2name ! second field which is subtracted from or added to first field
!
! Local workspace
@@ -5299,10 +5742,13 @@ subroutine addfld_nd(fname, dimnames, avgflag, units, long_name, &
character(len=128) :: errormsg
character(len=3) :: mixing_ratio
type(master_entry), pointer :: listentry
+ type(master_entry), pointer :: f1listentry,f2listentry
integer :: dimcnt
integer :: idx
+ character(len=*), parameter :: subname='ADDFLD_ND'
+
if (htapes_defined) then
call endrun ('ADDFLD: Attempt to add field '//trim(fname)//' after history files set')
end if
@@ -5352,6 +5798,11 @@ subroutine addfld_nd(fname, dimnames, avgflag, units, long_name, &
listentry%field%mixing_ratio = mixing_ratio
listentry%field%meridional_complement = -1
listentry%field%zonal_complement = -1
+ listentry%field%field_op = ''
+ listentry%field%op_field1_id = -1
+ listentry%field%op_field2_id = -1
+ listentry%op_field1 = ''
+ listentry%op_field2 = ''
listentry%htapeindx(:) = -1
listentry%act_sometape = .false.
listentry%actflag(:) = .false.
@@ -5453,6 +5904,45 @@ subroutine addfld_nd(fname, dimnames, avgflag, units, long_name, &
call AvgflagToString(avgflag, listentry%time_op(dimcnt))
end do
+ if (present(optype)) then
+ ! make sure optype is "sum" or "dif"
+ if (.not.(trim(optype) == 'dif' .or. trim(optype) == 'sum')) then
+ write(errormsg, '(2a)')': Fatal : optype must be "sum" or "dif" not ',trim(optype)
+ call endrun (trim(subname)//errormsg)
+ end if
+ listentry%field%field_op = optype
+ if (present(op_f1name).and.present(op_f2name)) then
+ ! Look for the field IDs
+ f1listentry => get_entry_by_name(masterlinkedlist, trim(op_f1name))
+ f2listentry => get_entry_by_name(masterlinkedlist, trim(op_f2name))
+ if (associated(f1listentry).and.associated(f2listentry)) then
+ listentry%op_field1=trim(op_f1name)
+ listentry%op_field2=trim(op_f2name)
+ else
+ write(errormsg, '(5a)') ': Attempt to create a composed field using (', &
+ trim(op_f1name), ', ', trim(op_f2name), &
+ ') but both fields have not been added to masterlist via addfld first'
+ call endrun (trim(subname)//errormsg)
+ end if
+ else
+ write(errormsg, *) ': Attempt to create a composed field but no component fields have been specified'
+ call endrun (trim(subname)//errormsg)
+ end if
+
+ else
+ if (present(op_f1name)) then
+ write(errormsg, '(3a)') ': creating a composed field using component field 1:',&
+ trim(op_f1name),' but no field operation (optype=sum or dif) has been defined'
+ call endrun (trim(subname)//errormsg)
+ end if
+ if (present(op_f2name)) then
+ write(errormsg, '(3a)') ': creating a composed field using component field 2:',&
+ trim(op_f2name),' but no field operation (optype=sum or dif) has been defined'
+ call endrun (trim(subname)//errormsg)
+ end if
+ end if
+
+
nullify(listentry%next_entry)
call add_entry_to_master(listentry)
@@ -5461,7 +5951,7 @@ end subroutine addfld_nd
!#######################################################################
- ! field_part_of_vector: Determinie if fname is part of a vector set
+ ! field_part_of_vector: Determine if fname is part of a vector set
! Optionally fill in the names of the vector set fields
logical function field_part_of_vector(fname, meridional_name, zonal_name)
@@ -5501,6 +5991,53 @@ logical function field_part_of_vector(fname, meridional_name, zonal_name)
end function field_part_of_vector
+ !#######################################################################
+ ! composed field_info: Determine if a field is derived from a mathematical
+ ! operation using 2 other defined fields. Optionally,
+ ! retrieve names of the composing fields
+ subroutine composed_field_info(fname, is_composed, fname1, fname2)
+
+ ! Dummy arguments
+ character(len=*), intent(in) :: fname
+ logical, intent(out) :: is_composed
+ character(len=*), optional, intent(out) :: fname1
+ character(len=*), optional, intent(out) :: fname2
+
+ ! Local variables
+ type(master_entry), pointer :: listentry
+ character(len=128) :: errormsg
+ character(len=*), parameter :: subname='composed_field_info'
+
+ listentry => get_entry_by_name(masterlinkedlist, fname)
+ if (associated(listentry)) then
+ if ( (len_trim(listentry%op_field1) > 0) .or. &
+ (len_trim(listentry%op_field2) > 0)) then
+ is_composed = .true.
+ else
+ is_composed = .false.
+ end if
+ if (is_composed) then
+ if (present(fname1)) then
+ fname1=trim(listentry%op_field1)
+ end if
+ if (present(fname2)) then
+ fname2=trim(listentry%op_field2)
+ end if
+ else
+ if (present(fname1)) then
+ fname1 = ''
+ end if
+ if (present(fname2)) then
+ fname2 = ''
+ end if
+ end if
+ else
+ write(errormsg, '(3a)') ': Field:',trim(fname),' not defined in masterlist'
+ call endrun (trim(subname)//errormsg)
+ end if
+
+ end subroutine composed_field_info
+
! register_vector_field: Register a pair of history field names as
! being a vector complement set.
diff --git a/src/control/cam_history_buffers.F90 b/src/control/cam_history_buffers.F90
index f9a141247a..b26162753c 100644
--- a/src/control/cam_history_buffers.F90
+++ b/src/control/cam_history_buffers.F90
@@ -111,6 +111,7 @@ subroutine hbuf_accum_add (buf8, field, nacs, dimind, idim, flag_xyfill, fillval
end subroutine hbuf_accum_add
!#######################################################################
+
subroutine hbuf_accum_variance (hbuf, sbuf, field, nacs, dimind, idim, flag_xyfill, fillvalue)
!
!-----------------------------------------------------------------------
diff --git a/src/control/cam_history_support.F90 b/src/control/cam_history_support.F90
index 8251ebde95..495ce7b519 100644
--- a/src/control/cam_history_support.F90
+++ b/src/control/cam_history_support.F90
@@ -10,7 +10,6 @@ module cam_history_support
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
use shr_kind_mod, only: r8=>shr_kind_r8, shr_kind_cl, shr_kind_cxx
- use shr_sys_mod, only: shr_sys_flush
use pio, only: var_desc_t, file_desc_t
use cam_abortutils, only: endrun
use cam_logfile, only: iulog
@@ -25,9 +24,10 @@ module cam_history_support
integer, parameter, public :: max_string_len = shr_kind_cxx
integer, parameter, public :: max_chars = shr_kind_cl ! max chars for char variables
- integer, parameter, public :: fieldname_len = 32 ! max chars for field name
- integer, parameter, public :: fieldname_suffix_len = 3 ! length of field name suffix ("&IC")
- integer, parameter, public :: fieldname_lenp2 = fieldname_len + 2 ! allow for extra characters
+ integer, parameter, public :: field_op_len = 3 ! max chars for field operation string (sum/dif)
+ integer, parameter, public :: fieldname_len = 32 ! max chars for field name
+ integer, parameter, public :: fieldname_suffix_len = 3 ! length of field name suffix ("&IC")
+ integer, parameter, public :: fieldname_lenp2 = fieldname_len + 2 ! allow for extra characters
! max_fieldname_len = max chars for field name (including suffix)
integer, parameter, public :: max_fieldname_len = fieldname_len + fieldname_suffix_len
@@ -118,6 +118,10 @@ module cam_history_support
integer :: meridional_complement ! meridional field id or -1
integer :: zonal_complement ! zonal field id or -1
+ character(len=field_op_len) :: field_op = '' ! 'sum' or 'dif'
+ integer :: op_field1_id ! first field id or -1
+ integer :: op_field2_id ! second field id or -1
+
character(len=max_fieldname_len) :: name ! field name
character(len=max_chars) :: long_name ! long name
character(len=max_chars) :: units ! units
@@ -127,6 +131,7 @@ module cam_history_support
! radiation calcs; etc.
character(len=max_chars) :: cell_methods ! optional cell_methods attribute
contains
+ procedure :: is_composed => field_info_is_composed
procedure :: get_shape => field_info_get_shape
procedure :: get_bounds => field_info_get_bounds
procedure :: get_dims_2d => field_info_get_dims_2d
@@ -153,17 +158,27 @@ module cam_history_support
!
!---------------------------------------------------------------------------
type, public:: hentry
- type (field_info) :: field ! field information
- character(len=1) :: avgflag ! averaging flag
- character(len=max_chars) :: time_op ! time operator (e.g. max, min, avg)
+ type (field_info) :: field ! field information
+ character(len=1) :: avgflag ! averaging flag
+ character(len=max_chars) :: time_op ! time operator (e.g. max, min, avg)
+ character(len=max_fieldname_len) :: op_field1 ! field1 name for sum or dif operation
+ character(len=max_fieldname_len) :: op_field2 ! field2 name for sum or dif operation
- integer :: hwrt_prec ! history output precision
+ integer :: hwrt_prec ! history output precision
real(r8), pointer :: hbuf(:,:,:) => NULL()
+ real(r8), private :: hbuf_integral ! area weighted integral of active field
real(r8), pointer :: sbuf(:,:,:) => NULL() ! for standard deviation
+ real(r8), pointer :: wbuf(:,:) => NULL() ! pointer to area weights
type(var_desc_t), pointer :: varid(:) => NULL() ! variable ids
integer, pointer :: nacs(:,:) => NULL() ! accumulation counter
type(var_desc_t), pointer :: nacs_varid => NULL()
+ integer :: beg_nstep ! starting time step for nstep normalization
+ type(var_desc_t), pointer :: beg_nstep_varid=> NULL()
type(var_desc_t), pointer :: sbuf_varid => NULL()
+ type(var_desc_t), pointer :: wbuf_varid => NULL()
+ contains
+ procedure :: get_global => hentry_get_global
+ procedure :: put_global => hentry_put_global
end type hentry
!---------------------------------------------------------------------------
@@ -435,6 +450,14 @@ type(dim_index_3d) function field_info_get_dims_3d(this) result(dims)
end function field_info_get_dims_3d
+ ! field_info_is_composed: Return whether this field is composed of two other fields
+ pure logical function field_info_is_composed(this)
+ class(field_info), intent(IN) :: this
+
+ field_info_is_composed = ((trim(adjustl(this%field_op))=='sum' .or. trim(adjustl(this%field_op))=='dif') .and. &
+ this%op_field1_id /= -1 .and. this%op_field2_id /= -1)
+ end function field_info_is_composed
+
! field_info_get_shape: Return a pointer to the field's global shape.
! Calculate it first if necessary
subroutine field_info_get_shape(this, shape_out, rank_out)
@@ -503,6 +526,26 @@ subroutine field_info_get_bounds(this, dim, beg, end)
end subroutine field_info_get_bounds
+ subroutine hentry_get_global(this, gval)
+
+ ! Dummy arguments
+ class(hentry) :: this
+ real(r8), intent(out) :: gval
+
+ gval=this%hbuf_integral
+
+ end subroutine hentry_get_global
+
+ subroutine hentry_put_global(this, gval)
+
+ ! Dummy arguments
+ class(hentry) :: this
+ real(r8), intent(in) :: gval
+
+ this%hbuf_integral=gval
+
+ end subroutine hentry_put_global
+
! history_patch_write_attrs: Define coordinate variables and attributes
! for a patch
subroutine history_patch_write_attrs(this, File)
@@ -651,16 +694,8 @@ subroutine history_patch_write_vals(this, File)
type(cam_grid_patch_t), pointer :: patchptr
type(var_desc_t), pointer :: vardesc => NULL() ! PIO var desc
character(len=128) :: errormsg
- character(len=max_chars) :: lat_name
- character(len=max_chars) :: lon_name
- character(len=max_chars) :: col_name
- character(len=max_chars) :: temp_str
- integer :: dimid ! PIO dimension ID
integer :: num_patches
- integer :: temp1, temp2
- integer :: latid, lonid ! Coordinate dims
integer :: i
- logical :: col_only
num_patches = size(this%patches)
if (.not. associated(this%header_info)) then
@@ -957,6 +992,9 @@ subroutine field_copy(f_out, f_in)
f_out%meridional_complement = f_in%meridional_complement ! id or -1
f_out%zonal_complement = f_in%zonal_complement ! id or -1
+ f_out%field_op = f_in%field_op ! sum,dif, or ''
+ f_out%op_field1_id = f_in%op_field1_id ! id or -1
+ f_out%op_field2_id = f_in%op_field2_id ! id or -1
f_out%name = f_in%name ! field name
f_out%long_name = f_in%long_name ! long name
diff --git a/src/control/camsrfexch.F90 b/src/control/camsrfexch.F90
index 6715b6f4cd..de1ea4ce6e 100644
--- a/src/control/camsrfexch.F90
+++ b/src/control/camsrfexch.F90
@@ -61,6 +61,7 @@ module camsrfexch
real(r8) :: co2prog(pcols) ! prognostic co2
real(r8) :: co2diag(pcols) ! diagnostic co2
real(r8) :: ozone(pcols) ! surface ozone concentration (mole/mole)
+ real(r8) :: lightning_flash_freq(pcols) ! cloud-to-ground lightning flash frequency (/min)
real(r8) :: psl(pcols)
real(r8) :: bcphiwet(pcols) ! wet deposition of hydrophilic black carbon
real(r8) :: bcphidry(pcols) ! dry deposition of hydrophilic black carbon
@@ -302,6 +303,7 @@ subroutine atm2hub_alloc( cam_out )
cam_out(c)%co2prog(:) = 0._r8
cam_out(c)%co2diag(:) = 0._r8
cam_out(c)%ozone(:) = 0._r8
+ cam_out(c)%lightning_flash_freq(:) = 0._r8
cam_out(c)%psl(:) = 0._r8
cam_out(c)%bcphidry(:) = 0._r8
cam_out(c)%bcphodry(:) = 0._r8
@@ -319,18 +321,14 @@ subroutine atm2hub_alloc( cam_out )
cam_out(c)%dstwet4(:) = 0._r8
nullify(cam_out(c)%nhx_nitrogen_flx)
- nullify(cam_out(c)%noy_nitrogen_flx)
+ allocate (cam_out(c)%nhx_nitrogen_flx(pcols), stat=ierror)
+ if ( ierror /= 0 ) call endrun(sub//': allocation error nhx_nitrogen_flx')
+ cam_out(c)%nhx_nitrogen_flx(:) = 0._r8
- if (active_Faxa_nhx) then
- allocate (cam_out(c)%nhx_nitrogen_flx(pcols), stat=ierror)
- if ( ierror /= 0 ) call endrun(sub//': allocation error nhx_nitrogen_flx')
- cam_out(c)%nhx_nitrogen_flx(:) = 0._r8
- endif
- if (active_Faxa_noy) then
- allocate (cam_out(c)%noy_nitrogen_flx(pcols), stat=ierror)
- if ( ierror /= 0 ) call endrun(sub//': allocation error noy_nitrogen_flx')
- cam_out(c)%noy_nitrogen_flx(:) = 0._r8
- endif
+ nullify(cam_out(c)%noy_nitrogen_flx)
+ allocate (cam_out(c)%noy_nitrogen_flx(pcols), stat=ierror)
+ if ( ierror /= 0 ) call endrun(sub//': allocation error noy_nitrogen_flx')
+ cam_out(c)%noy_nitrogen_flx(:) = 0._r8
end do
end subroutine atm2hub_alloc
@@ -427,7 +425,7 @@ subroutine cam_export(state,cam_out,pbuf)
integer :: psl_idx
integer :: prec_dp_idx, snow_dp_idx, prec_sh_idx, snow_sh_idx
integer :: prec_sed_idx,snow_sed_idx,prec_pcw_idx,snow_pcw_idx
- integer :: srf_ozone_idx
+ integer :: srf_ozone_idx, lightning_idx
real(r8), pointer :: psl(:)
@@ -440,6 +438,7 @@ subroutine cam_export(state,cam_out,pbuf)
real(r8), pointer :: prec_pcw(:) ! total precipitation from Hack convection
real(r8), pointer :: snow_pcw(:) ! snow from Hack convection
real(r8), pointer :: o3_ptr(:,:), srf_o3_ptr(:)
+ real(r8), pointer :: lightning_ptr(:)
!-----------------------------------------------------------------------
lchnk = state%lchnk
@@ -457,6 +456,7 @@ subroutine cam_export(state,cam_out,pbuf)
prec_pcw_idx = pbuf_get_index('PREC_PCW', errcode=i)
snow_pcw_idx = pbuf_get_index('SNOW_PCW', errcode=i)
srf_ozone_idx = pbuf_get_index('SRFOZONE', errcode=i)
+ lightning_idx = pbuf_get_index('LGHT_FLASH_FREQ', errcode=i)
if (prec_dp_idx > 0) then
call pbuf_get_field(pbuf, prec_dp_idx, prec_dp)
@@ -516,6 +516,12 @@ subroutine cam_export(state,cam_out,pbuf)
cam_out%ozone(:ncol) = o3_ptr(:ncol,pver) * mwdry/mwo3 ! mole/mole
endif
+ ! get cloud to ground lightning flash freq (/min) to export to surface models
+ if (lightning_idx>0) then
+ call pbuf_get_field(pbuf, lightning_idx, lightning_ptr)
+ cam_out%lightning_flash_freq(:ncol) = lightning_ptr(:ncol)
+ end if
+
!
! Precipation and snow rates from shallow convection, deep convection and stratiform processes.
! Compute total convective and stratiform precipitation and snow rates
diff --git a/src/control/runtime_opts.F90 b/src/control/runtime_opts.F90
index 24d096c07c..cc2f4fd4a2 100644
--- a/src/control/runtime_opts.F90
+++ b/src/control/runtime_opts.F90
@@ -97,7 +97,9 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon)
use qneg_module, only: qneg_readnl
use lunar_tides, only: lunar_tides_readnl
use upper_bc, only: ubc_readnl
+ use cam_budget, only: cam_budget_readnl
use phys_grid_ctem, only: phys_grid_ctem_readnl
+ use mo_lightning, only: lightning_readnl
#if (defined HEMCO_CESM)
use hemco_interface, only: hemco_readnl
@@ -169,6 +171,7 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon)
call rad_data_readnl(nlfilename)
call modal_aer_opt_readnl(nlfilename)
call chem_readnl(nlfilename)
+ call lightning_readnl(nlfilename)
call prescribed_volcaero_readnl(nlfilename)
call prescribed_strataero_readnl(nlfilename)
call solar_data_readnl(nlfilename)
@@ -200,6 +203,7 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon)
call dyn_readnl(nlfilename)
call ionosphere_readnl(nlfilename)
call qneg_readnl(nlfilename)
+ call cam_budget_readnl(nlfilename)
call phys_grid_ctem_readnl(nlfilename)
#if (defined HEMCO_CESM)
call hemco_readnl(nlfilename)
diff --git a/src/cpl/nuopc/atm_comp_nuopc.F90 b/src/cpl/nuopc/atm_comp_nuopc.F90
index a85accd837..8b2ba903d0 100644
--- a/src/cpl/nuopc/atm_comp_nuopc.F90
+++ b/src/cpl/nuopc/atm_comp_nuopc.F90
@@ -4,60 +4,79 @@ module atm_comp_nuopc
! This is the NUOPC cap for CAM
!----------------------------------------------------------------------------
- use ESMF
- use NUOPC , only : NUOPC_CompDerive, NUOPC_CompSetEntryPoint, NUOPC_CompSpecialize
- use NUOPC , only : NUOPC_CompFilterPhaseMap, NUOPC_IsUpdated, NUOPC_IsAtTime
- use NUOPC , only : NUOPC_CompAttributeGet, NUOPC_Advertise
- use NUOPC , only : NUOPC_SetAttribute, NUOPC_CompAttributeGet, NUOPC_CompAttributeSet
- use NUOPC_Model , only : model_routine_SS => SetServices
- use NUOPC_Model , only : SetVM
- use NUOPC_Model , only : model_label_Advance => label_Advance
- use NUOPC_Model , only : model_label_DataInitialize => label_DataInitialize
- use NUOPC_Model , only : model_label_SetRunClock => label_SetRunClock
- use NUOPC_Model , only : model_label_Finalize => label_Finalize
- use NUOPC_Model , only : NUOPC_ModelGet
- use shr_kind_mod , only : r8=>shr_kind_r8, i8=>shr_kind_i8, cl=>shr_kind_cl, cs=>shr_kind_cs
- use shr_sys_mod , only : shr_sys_abort
- use shr_log_mod , only : shr_log_getlogunit, shr_log_setlogunit
- use shr_cal_mod , only : shr_cal_noleap, shr_cal_gregorian, shr_cal_ymd2date
- use shr_const_mod , only : shr_const_pi
- use shr_orb_mod , only : shr_orb_decl, shr_orb_params, SHR_ORB_UNDEF_REAL, SHR_ORB_UNDEF_INT
- use cam_instance , only : cam_instance_init, inst_suffix, inst_index
- use cam_comp , only : cam_init, cam_run1, cam_run2, cam_run3, cam_run4, cam_final
- use camsrfexch , only : cam_out_t, cam_in_t
- use radiation , only : nextsw_cday
- use cam_logfile , only : iulog
- use spmd_utils , only : spmdinit, masterproc, iam, mpicom
- use time_manager , only : get_curr_calday, advance_timestep, get_curr_date, get_nstep, get_step_size
- use atm_import_export , only : read_surface_fields_namelists, advertise_fields, realize_fields
- use atm_import_export , only : import_fields, export_fields
- use nuopc_shr_methods , only : chkerr, state_setscalar, state_getscalar, state_diagnose, alarmInit
- use nuopc_shr_methods , only : set_component_logging, get_component_instance, log_clock_advance
- use perf_mod , only : t_startf, t_stopf
- use ppgrid , only : pcols, begchunk, endchunk
- use dyn_grid , only : get_horiz_grid_dim_d
- use phys_grid , only : get_ncols_p, get_gcol_p, get_rlon_all_p, get_rlat_all_p
- use phys_grid , only : ngcols=>num_global_phys_cols
- use cam_control_mod , only : cam_ctrl_set_orbit
- use cam_pio_utils , only : cam_pio_createfile, cam_pio_openfile, cam_pio_closefile, pio_subsystem
- use cam_initfiles , only : cam_initfiles_get_caseid, cam_initfiles_get_restdir
- use cam_history_support , only : fillvalue
- use filenames , only : interpret_filename_spec
- use pio , only : file_desc_t, io_desc_t, var_desc_t, pio_double, pio_def_dim, PIO_MAX_NAME
- use pio , only : pio_closefile, pio_put_att, pio_enddef, pio_nowrite
- use pio , only : pio_inq_dimid, pio_inq_varid, pio_inquire_dimension, pio_def_var
- use pio , only : pio_initdecomp, pio_freedecomp
- use pio , only : pio_read_darray, pio_write_darray
- use pio , only : pio_noerr, pio_bcast_error, pio_internal_error, pio_seterrorhandling
- use pio , only : pio_def_var, pio_get_var, pio_put_var, PIO_INT
- use ioFileMod
-!$use omp_lib , only : omp_set_num_threads
+ use ESMF , only : operator(<=), operator(>), operator(==), operator(+)
+ use ESMF , only : ESMF_MethodRemove
+ use ESMF , only : ESMF_GridComp, ESMF_GridCompGet, ESMF_State, ESMF_StateGet
+ use ESMF , only : ESMF_Grid, ESMF_GridCreateNoPeriDimUfrm, ESMF_Field, ESMF_FieldGet
+ use ESMF , only : ESMF_DistGrid, ESMF_DistGridCreate
+ use ESMF , only : ESMF_Mesh, ESMF_MeshCreate, ESMF_MeshGet, ESMF_FILEFORMAT_ESMFMESH
+ use ESMF , only : ESMF_Clock, ESMF_ClockGet, ESMF_ClockSet, ESMF_ClockGetNextTime, ESMF_ClockAdvance
+ use ESMF , only : ESMF_Time, ESMF_TimeGet
+ use ESMF , only : ESMF_Alarm, ESMF_ClockGetAlarm, ESMF_AlarmRingerOff, ESMF_AlarmIsRinging
+ use ESMF , only : ESMF_ClockGetAlarmList, ESMF_ALARMLIST_ALL, ESMF_AlarmSet
+ use ESMF , only : ESMF_TimeInterval, ESMF_TimeIntervalGet
+ use ESMF , only : ESMF_CalKind_Flag, ESMF_MAXSTR, ESMF_KIND_I8
+ use ESMF , only : ESMF_CALKIND_NOLEAP, ESMF_CALKIND_GREGORIAN
+ use ESMF , only : ESMF_GridCompSetEntryPoint
+ use ESMF , only : ESMF_VM, ESMF_VMGetCurrent, ESMF_VMGet
+ use ESMF , only : ESMF_LOGMSG_INFO, ESMF_LOGERR_PASSTHRU
+ use ESMF , only : ESMF_LogWrite, ESMF_LogSetError, ESMF_LogFoundError
+ use ESMF , only : ESMF_SUCCESS, ESMF_METHOD_INITIALIZE, ESMF_FAILURE, ESMF_RC_NOT_VALID
+ use ESMF , only : ESMF_STAGGERLOC_CENTER, ESMF_STAGGERLOC_CORNER
+ use NUOPC , only : NUOPC_CompDerive, NUOPC_CompSetEntryPoint, NUOPC_CompSpecialize
+ use NUOPC , only : NUOPC_CompFilterPhaseMap, NUOPC_IsUpdated, NUOPC_IsAtTime
+ use NUOPC , only : NUOPC_CompAttributeGet, NUOPC_Advertise
+ use NUOPC , only : NUOPC_SetAttribute, NUOPC_CompAttributeGet, NUOPC_CompAttributeSet
+ use NUOPC_Model , only : model_routine_SS => SetServices
+ use NUOPC_Model , only : SetVM
+ use NUOPC_Model , only : model_label_Advance => label_Advance
+ use NUOPC_Model , only : model_label_DataInitialize => label_DataInitialize
+ use NUOPC_Model , only : model_label_SetRunClock => label_SetRunClock
+ use NUOPC_Model , only : model_label_Finalize => label_Finalize
+ use NUOPC_Model , only : NUOPC_ModelGet
+ use shr_kind_mod , only : r8=>shr_kind_r8, i8=>shr_kind_i8, cl=>shr_kind_cl, cs=>shr_kind_cs
+ use shr_sys_mod , only : shr_sys_abort
+ use shr_log_mod , only : shr_log_getlogunit, shr_log_setlogunit
+ use shr_cal_mod , only : shr_cal_noleap, shr_cal_gregorian, shr_cal_ymd2date
+ use shr_const_mod , only : shr_const_pi
+ use shr_orb_mod , only : shr_orb_decl, shr_orb_params, SHR_ORB_UNDEF_REAL, SHR_ORB_UNDEF_INT
+ use cam_instance , only : cam_instance_init, inst_suffix, inst_index
+ use cam_comp , only : cam_init, cam_run1, cam_run2, cam_run3, cam_run4, cam_final
+ use camsrfexch , only : cam_out_t, cam_in_t
+ use radiation , only : nextsw_cday
+ use cam_logfile , only : iulog
+ use spmd_utils , only : spmdinit, masterproc, iam, mpicom
+ use time_manager , only : get_curr_calday, advance_timestep, get_curr_date, get_nstep, get_step_size
+ use atm_import_export , only : read_surface_fields_namelists, advertise_fields, realize_fields
+ use atm_import_export , only : import_fields, export_fields
+ use nuopc_shr_methods , only : chkerr, state_setscalar, state_getscalar, state_diagnose, alarmInit
+ use nuopc_shr_methods , only : set_component_logging, get_component_instance, log_clock_advance
+ use perf_mod , only : t_startf, t_stopf
+ use ppgrid , only : pcols, begchunk, endchunk
+ use dyn_grid , only : get_horiz_grid_dim_d
+ use phys_grid , only : get_ncols_p, get_gcol_p, get_rlon_all_p, get_rlat_all_p
+ use phys_grid , only : ngcols=>num_global_phys_cols
+ use cam_control_mod , only : cam_ctrl_set_orbit
+ use cam_pio_utils , only : cam_pio_createfile, cam_pio_openfile, cam_pio_closefile, pio_subsystem
+ use cam_initfiles , only : cam_initfiles_get_caseid, cam_initfiles_get_restdir
+ use cam_history_support , only : fillvalue
+ use filenames , only : interpret_filename_spec
+ use pio , only : file_desc_t, io_desc_t, var_desc_t, pio_double, pio_def_dim, PIO_MAX_NAME
+ use pio , only : pio_closefile, pio_put_att, pio_enddef, pio_nowrite
+ use pio , only : pio_inq_dimid, pio_inq_varid, pio_inquire_dimension, pio_def_var
+ use pio , only : pio_initdecomp, pio_freedecomp
+ use pio , only : pio_read_darray, pio_write_darray
+ use pio , only : pio_noerr, pio_bcast_error, pio_internal_error, pio_seterrorhandling
+ use pio , only : pio_def_var, pio_get_var, pio_put_var, PIO_INT
+ use ioFileMod
+ !$use omp_lib , only : omp_set_num_threads
implicit none
private ! except
public :: SetServices
public :: SetVM
+
!--------------------------------------------------------------------------
! Private interfaces
!--------------------------------------------------------------------------
@@ -109,6 +128,10 @@ module atm_comp_nuopc
character(len=*) , parameter :: orb_fixed_parameters = 'fixed_parameters'
real(R8) , parameter :: grid_tol = 1.e-2_r8 ! tolerance for calculated lat/lon vs read in
+
+ type(ESMF_Mesh) :: model_mesh ! model_mesh
+ type(ESMF_Clock) :: model_clock ! model_clock
+
!===============================================================================
contains
!===============================================================================
@@ -319,7 +342,6 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc)
type(ESMF_TimeInterval) :: timeStep
type(ESMF_CalKind_Flag) :: esmf_caltype ! esmf calendar type
type(ESMF_DistGrid) :: distGrid
- type(ESMF_Mesh) :: mesh
integer :: spatialDim
integer :: numOwnedElements
real(R8), pointer :: ownedElemCoords(:)
@@ -626,7 +648,7 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc)
if (single_column) then
- call cam_set_mesh_for_single_column(scol_lon, scol_lat, mesh, rc)
+ call cam_set_mesh_for_single_column(scol_lon, scol_lat, model_mesh, rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
allocate(dof(1))
dof(1) = 1
@@ -657,7 +679,7 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc)
call NUOPC_CompAttributeGet(gcomp, name='mesh_atm', value=cvalue, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
- mesh = ESMF_MeshCreate(filename=trim(cvalue), fileformat=ESMF_FILEFORMAT_ESMFMESH, &
+ model_mesh = ESMF_MeshCreate(filename=trim(cvalue), fileformat=ESMF_FILEFORMAT_ESMFMESH, &
elementDistgrid=Distgrid, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
if (masterproc) then
@@ -665,7 +687,7 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc)
end if
! obtain mesh lats and lons
- call ESMF_MeshGet(mesh, spatialDim=spatialDim, numOwnedElements=numOwnedElements, rc=rc)
+ call ESMF_MeshGet(model_mesh, spatialDim=spatialDim, numOwnedElements=numOwnedElements, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
if (numOwnedElements /= lsize) then
write(tempc1,'(i10)') numOwnedElements
@@ -677,7 +699,7 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc)
end if
allocate(ownedElemCoords(spatialDim*numOwnedElements))
allocate(lonMesh(lsize), latMesh(lsize))
- call ESMF_MeshGet(mesh, ownedElemCoords=ownedElemCoords)
+ call ESMF_MeshGet(model_mesh, ownedElemCoords=ownedElemCoords)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
do n = 1,lsize
lonMesh(n) = ownedElemCoords(2*n-1)
@@ -702,7 +724,8 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc)
! error check differences between internally generated lons and those read in
do n = 1,lsize
- if (abs(lonMesh(n) - lon(n)) > grid_tol .and. abs(lonMesh(n) - lon(n)) /= 360._r8) then
+ if (abs(lonMesh(n) - lon(n)) > grid_tol .and. .not. &
+ abs(abs(lonMesh(n) - lon(n))- 360._r8) < grid_tol) then
write(6,100)n,lon(n),lonMesh(n), abs(lonMesh(n)-lon(n))
100 format('ERROR: CAM n, lonmesh(n), lon(n), diff_lon = ',i6,2(f21.13,3x),d21.5)
call shr_sys_abort()
@@ -722,11 +745,14 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc)
end if ! end of if single_column
! realize the actively coupled fields
- call realize_fields(gcomp, mesh, flds_scalar_name, flds_scalar_num, single_column, rc)
+ call realize_fields(gcomp, model_mesh, flds_scalar_name, flds_scalar_num, single_column, rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ ! Create model_clock as a module variable - needed for generating streams
+ model_clock = clock
+
! Create cam export array and set the state scalars
- call export_fields( gcomp, cam_out, rc=rc )
+ call export_fields( gcomp, model_mesh, model_clock, cam_out, rc=rc )
if (ChkErr(rc,__LINE__,u_FILE_u)) return
call get_horiz_grid_dim_d(hdim1_d, hdim2_d)
@@ -881,7 +907,7 @@ subroutine DataInitialize(gcomp, rc)
call import_fields( gcomp, cam_in, rc=rc )
if (ChkErr(rc,__LINE__,u_FILE_u)) return
call cam_run1 ( cam_in, cam_out )
- call export_fields( gcomp, cam_out, rc=rc )
+ call export_fields( gcomp, model_mesh, model_clock, cam_out, rc=rc )
if (ChkErr(rc,__LINE__,u_FILE_u)) return
else
call cam_read_srfrest( gcomp, clock, rc=rc )
@@ -889,7 +915,7 @@ subroutine DataInitialize(gcomp, rc)
call import_fields( gcomp, cam_in, restart_init=.true., rc=rc )
if (ChkErr(rc,__LINE__,u_FILE_u)) return
call cam_run1 ( cam_in, cam_out )
- call export_fields( gcomp, cam_out, rc=rc )
+ call export_fields( gcomp, model_mesh, model_clock, cam_out, rc=rc )
if (ChkErr(rc,__LINE__,u_FILE_u)) return
end if
@@ -1136,7 +1162,7 @@ subroutine ModelAdvance(gcomp, rc)
if (mediator_present) then
! Set export fields
call t_startf ('CAM_export')
- call export_fields( gcomp, cam_out, rc )
+ call export_fields( gcomp, model_mesh, model_clock, cam_out, rc )
if (ChkErr(rc,__LINE__,u_FILE_u)) return
call t_stopf ('CAM_export')
@@ -1503,7 +1529,7 @@ subroutine cam_orbital_update(clock, logunit, mastertask, eccen, obliqr, lambm0
if(.not. (logprint .and. mastertask)) then
logprint = .false.
endif
-
+
eccen = orb_eccen
call shr_orb_params(orb_year, eccen, orb_obliq, orb_mvelp, obliqr, lambm0, mvelpp, logprint)
diff --git a/src/cpl/nuopc/atm_import_export.F90 b/src/cpl/nuopc/atm_import_export.F90
index bdce379f69..baadd00865 100644
--- a/src/cpl/nuopc/atm_import_export.F90
+++ b/src/cpl/nuopc/atm_import_export.F90
@@ -3,6 +3,7 @@ module atm_import_export
use NUOPC , only : NUOPC_CompAttributeGet, NUOPC_Advertise, NUOPC_IsConnected
use NUOPC_Model , only : NUOPC_ModelGet
use ESMF , only : ESMF_GridComp, ESMF_State, ESMF_Mesh, ESMF_StateGet, ESMF_Field
+ use ESMF , only : ESMF_Clock
use ESMF , only : ESMF_KIND_R8, ESMF_SUCCESS, ESMF_MAXSTR, ESMF_LOGMSG_INFO
use ESMF , only : ESMF_LogWrite, ESMF_LOGMSG_ERROR, ESMF_LogFoundError
use ESMF , only : ESMF_STATEITEM_NOTFOUND, ESMF_StateItem_Flag
@@ -23,6 +24,8 @@ module atm_import_export
use srf_field_check , only : set_active_Faoo_fco2_ocn
use srf_field_check , only : set_active_Faxa_nhx
use srf_field_check , only : set_active_Faxa_noy
+ use srf_field_check , only : active_Faxa_nhx, active_Faxa_noy
+ use atm_stream_ndep , only : stream_ndep_init, stream_ndep_interp, stream_ndep_is_initialized
implicit none
private ! except
@@ -57,7 +60,8 @@ module atm_import_export
integer :: drydep_nflds = -huge(1) ! number of dry deposition velocity fields lnd-> atm
integer :: megan_nflds = -huge(1) ! number of MEGAN voc fields from lnd-> atm
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
+ 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)
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__
@@ -76,6 +80,7 @@ subroutine read_surface_fields_namelists()
use shr_fire_emis_mod , only : shr_fire_emis_readnl
use shr_carma_mod , only : shr_carma_readnl
use shr_ndep_mod , only : shr_ndep_readnl
+ use shr_lightning_coupling_mod, only : shr_lightning_coupling_readnl
character(len=*), parameter :: nl_file_name = 'drv_flds_in'
@@ -85,9 +90,13 @@ subroutine read_surface_fields_namelists()
call shr_megan_readnl(nl_file_name, megan_nflds)
call shr_fire_emis_readnl(nl_file_name, emis_nflds)
call shr_carma_readnl(nl_file_name, carma_fields)
+ call shr_lightning_coupling_readnl(nl_file_name, atm_provides_lightning)
end subroutine read_surface_fields_namelists
+ !-----------------------------------------------------------
+ ! advertise fields
+ !-----------------------------------------------------------
subroutine advertise_fields(gcomp, flds_scalar_name, rc)
! input/output variables
@@ -100,7 +109,6 @@ subroutine advertise_fields(gcomp, flds_scalar_name, rc)
type(ESMF_State) :: exportState
character(ESMF_MAXSTR) :: stdname
character(ESMF_MAXSTR) :: cvalue
- character(len=2) :: nec_str
integer :: n, num
logical :: flds_co2a ! use case
logical :: flds_co2b ! use case
@@ -186,11 +194,21 @@ subroutine advertise_fields(gcomp, flds_scalar_name, rc)
call fldlist_add(fldsFrAtm_num, fldsFrAtm, 'Sa_co2diag' )
end if
- ! from atm - nitrogen deposition
if (ndep_nflds > 0) then
- call fldlist_add(fldsFrAtm_num, fldsFrAtm, 'Faxa_ndep', ungridded_lbound=1, ungridded_ubound=ndep_nflds)
+ ! The following is when CAM/WACCM computes ndep
call set_active_Faxa_nhx(.true.)
call set_active_Faxa_noy(.true.)
+ else
+ ! The following is used for reading in stream data
+ call set_active_Faxa_nhx(.false.)
+ call set_active_Faxa_noy(.false.)
+ end if
+ ! Assume that 2 fields are always sent as part of Faxa_ndep
+ call fldlist_add(fldsFrAtm_num, fldsFrAtm, 'Faxa_ndep', ungridded_lbound=1, ungridded_ubound=2)
+
+ ! lightning flash freq
+ if (atm_provides_lightning) then
+ call fldlist_add(fldsFrAtm_num, fldsFrAtm, 'Sa_lightning')
end if
! Now advertise above export fields
@@ -859,7 +877,7 @@ end subroutine import_fields
!===============================================================================
- subroutine export_fields( gcomp, cam_out, rc)
+ subroutine export_fields( gcomp, model_mesh, model_clock, cam_out, rc)
! -----------------------------------------------------
! Set field pointers in export set
@@ -877,16 +895,20 @@ subroutine export_fields( gcomp, cam_out, rc)
!-------------------------------
! input/output variables
- type(ESMF_GridComp) :: gcomp
- type(cam_out_t) , intent(in) :: cam_out(begchunk:endchunk)
- integer , intent(out) :: rc
+ type(ESMF_GridComp) :: gcomp
+ type(ESMF_Mesh) , intent(in) :: model_mesh
+ type(ESMF_Clock), intent(in) :: model_clock
+ type(cam_out_t) , intent(inout) :: cam_out(begchunk:endchunk)
+ integer , intent(out) :: rc
! local variables
type(ESMF_State) :: exportState
+ type(ESMF_Clock) :: clock
integer :: i,m,c,n,g ! indices
integer :: ncols ! Number of columns
integer :: nstep
logical :: exists
+ real(r8) :: scale_ndep
! 2d pointers
real(r8), pointer :: fldptr_ndep(:,:)
real(r8), pointer :: fldptr_bcph(:,:) , fldptr_ocph(:,:)
@@ -904,6 +926,7 @@ subroutine export_fields( gcomp, cam_out, rc)
real(r8), pointer :: fldptr_ptem(:) , fldptr_pslv(:)
real(r8), pointer :: fldptr_co2prog(:) , fldptr_co2diag(:)
real(r8), pointer :: fldptr_ozone(:)
+ real(r8), pointer :: fldptr_lght(:)
character(len=*), parameter :: subname='(atm_import_export:export_fields)'
!---------------------------------------------------------------------------
@@ -1033,44 +1056,70 @@ subroutine export_fields( gcomp, cam_out, rc)
end do
end if
- call state_getfldptr(exportState, 'Sa_co2prog', fldptr=fldptr_co2prog, exists=exists, rc=rc)
+ call state_getfldptr(exportState, 'Sa_lightning', fldptr=fldptr_lght, exists=exists, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
if (exists) then
g = 1
do c = begchunk,endchunk
do i = 1,get_ncols_p(c)
- fldptr_co2prog(g) = cam_out(c)%co2prog(i) ! atm prognostic co2
+ fldptr_lght(g) = cam_out(c)%lightning_flash_freq(i) ! cloud-to-ground lightning flash frequency (/min)
g = g + 1
end do
end do
end if
- call state_getfldptr(exportState, 'Sa_co2diag', fldptr=fldptr_co2diag, exists=exists, rc=rc)
+ call state_getfldptr(exportState, 'Sa_co2prog', fldptr=fldptr_co2prog, exists=exists, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
if (exists) then
g = 1
do c = begchunk,endchunk
do i = 1,get_ncols_p(c)
- fldptr_co2diag(g) = cam_out(c)%co2diag(i) ! atm diagnostic co2
+ fldptr_co2prog(g) = cam_out(c)%co2prog(i) ! atm prognostic co2
g = g + 1
end do
end do
end if
- call state_getfldptr(exportState, 'Faxa_ndep', fldptr2d=fldptr_ndep, exists=exists, rc=rc)
+ call state_getfldptr(exportState, 'Sa_co2diag', fldptr=fldptr_co2diag, exists=exists, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
if (exists) then
- ! (1) => nhx, (2) => noy
g = 1
do c = begchunk,endchunk
do i = 1,get_ncols_p(c)
- fldptr_ndep(1,g) = cam_out(c)%nhx_nitrogen_flx(i) * mod2med_areacor(g)
- fldptr_ndep(2,g) = cam_out(c)%noy_nitrogen_flx(i) * mod2med_areacor(g)
+ fldptr_co2diag(g) = cam_out(c)%co2diag(i) ! atm diagnostic co2
g = g + 1
end do
end do
end if
+ ! If ndep fields are not computed in cam and must be obtained from the ndep input stream
+ call state_getfldptr(exportState, 'Faxa_ndep', fldptr2d=fldptr_ndep, rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ if (.not. active_Faxa_nhx .and. .not. active_Faxa_noy) then
+ if (.not. stream_ndep_is_initialized) then
+ call stream_ndep_init(model_mesh, model_clock, rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ stream_ndep_is_initialized = .true.
+ end if
+ call stream_ndep_interp(cam_out, rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ ! NDEP read from forcing is expected to be in units of gN/m2/sec - but the mediator
+ ! expects units of kgN/m2/sec
+ scale_ndep = .001_r8
+ else
+ ! If waccm computes ndep, then its in units of kgN/m2/s - and the mediator expects
+ ! units of kgN/m2/sec, so the following conversion needs to happen
+ scale_ndep = 1._r8
+ end if
+ g = 1
+ do c = begchunk,endchunk
+ do i = 1,get_ncols_p(c)
+ fldptr_ndep(1,g) = cam_out(c)%nhx_nitrogen_flx(i) * scale_ndep * mod2med_areacor(g)
+ fldptr_ndep(2,g) = cam_out(c)%noy_nitrogen_flx(i) * scale_ndep * mod2med_areacor(g)
+ g = g + 1
+ end do
+ end do
+
end subroutine export_fields
!===============================================================================
diff --git a/src/cpl/nuopc/atm_stream_ndep.F90 b/src/cpl/nuopc/atm_stream_ndep.F90
new file mode 100644
index 0000000000..394808a529
--- /dev/null
+++ b/src/cpl/nuopc/atm_stream_ndep.F90
@@ -0,0 +1,256 @@
+module atm_stream_ndep
+
+ !-----------------------------------------------------------------------
+ ! Contains methods for reading in nitrogen deposition data file
+ ! Also includes functions for dynamic ndep file handling and
+ ! interpolation.
+ !-----------------------------------------------------------------------
+ !
+ use ESMF , only : ESMF_Clock, ESMF_Mesh
+ use ESMF , only : ESMF_SUCCESS, ESMF_LOGERR_PASSTHRU, ESMF_END_ABORT
+ use ESMF , only : ESMF_Finalize, ESMF_LogFoundError
+ use nuopc_shr_methods , only : chkerr
+ use dshr_strdata_mod , only : shr_strdata_type
+ use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_cl, CS => shr_kind_cs
+ use shr_log_mod , only : errMsg => shr_log_errMsg
+ use spmd_utils , only : mpicom, masterproc, iam
+ use spmd_utils , only : mpi_character, mpi_integer
+ use cam_logfile , only : iulog
+ use cam_abortutils , only : endrun
+
+ implicit none
+ private
+
+ public :: stream_ndep_init ! position datasets for dynamic ndep
+ public :: stream_ndep_interp ! interpolates between two years of ndep file data
+
+ private :: stream_ndep_check_units ! Check the units and make sure they can be used
+
+ type(shr_strdata_type) :: sdat_ndep ! input data stream
+ logical, public :: stream_ndep_is_initialized = .false.
+ character(len=CS) :: stream_varlist_ndep(2)
+ type(ESMF_Clock) :: model_clock
+
+ character(len=*), parameter :: sourcefile = &
+ __FILE__
+
+!==============================================================================
+contains
+!==============================================================================
+
+ subroutine stream_ndep_init(model_mesh, model_clock, rc)
+ !
+ ! Initialize data stream information.
+
+ ! Uses:
+ use cam_instance , only: inst_suffix
+ use shr_nl_mod , only: shr_nl_find_group_name
+ use dshr_strdata_mod , only: shr_strdata_init_from_inline
+
+ ! input/output variables
+ type(ESMF_CLock), intent(in) :: model_clock
+ type(ESMF_Mesh) , intent(in) :: model_mesh
+ integer , intent(out) :: rc
+
+ ! local variables
+ integer :: nu_nml ! unit for namelist file
+ integer :: nml_error ! namelist i/o error flag
+ character(len=CL) :: stream_ndep_data_filename
+ character(len=CL) :: stream_ndep_mesh_filename
+ character(len=CL) :: filein ! atm namelist file
+ integer :: stream_ndep_year_first ! first year in stream to use
+ integer :: stream_ndep_year_last ! last year in stream to use
+ integer :: stream_ndep_year_align ! align stream_year_firstndep with
+ integer :: ierr
+ character(*), parameter :: subName = "('stream_ndep_init')"
+ !-----------------------------------------------------------------------
+
+ namelist /ndep_stream_nl/ &
+ stream_ndep_data_filename, &
+ stream_ndep_mesh_filename, &
+ stream_ndep_year_first, &
+ stream_ndep_year_last, &
+ stream_ndep_year_align
+
+ rc = ESMF_SUCCESS
+
+ ! Default values for namelist
+ stream_ndep_data_filename = ' '
+ stream_ndep_mesh_filename = ' '
+ stream_ndep_year_first = 1 ! first year in stream to use
+ stream_ndep_year_last = 1 ! last year in stream to use
+ stream_ndep_year_align = 1 ! align stream_ndep_year_first with this model year
+
+ ! For now variable list in stream data file is hard-wired
+ stream_varlist_ndep = (/'NDEP_NHx_month', 'NDEP_NOy_month'/)
+
+ ! Read ndep_stream namelist
+ if (masterproc) then
+ filein = "atm_in" // trim(inst_suffix)
+ open( newunit=nu_nml, file=trim(filein), status='old', iostat=nml_error )
+ if (nml_error /= 0) then
+ call endrun(subName//': ERROR opening '//trim(filein)//errMsg(sourcefile, __LINE__))
+ end if
+ call shr_nl_find_group_name(nu_nml, 'ndep_stream_nl', status=nml_error)
+ if (nml_error == 0) then
+ read(nu_nml, nml=ndep_stream_nl, iostat=nml_error)
+ if (nml_error /= 0) then
+ call endrun(' ERROR reading ndep_stream_nl namelist'//errMsg(sourcefile, __LINE__))
+ end if
+ else
+ call endrun(' ERROR finding ndep_stream_nl namelist'//errMsg(sourcefile, __LINE__))
+ end if
+ close(nu_nml)
+ endif
+ call mpi_bcast(stream_ndep_mesh_filename, len(stream_ndep_mesh_filename), mpi_character, 0, mpicom, ierr)
+ if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_mesh_filename")
+ call mpi_bcast(stream_ndep_data_filename, len(stream_ndep_data_filename), mpi_character, 0, mpicom, ierr)
+ if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_data_filename")
+ call mpi_bcast(stream_ndep_year_first, 1, mpi_integer, 0, mpicom, ierr)
+ if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_year_first")
+ call mpi_bcast(stream_ndep_year_last, 1, mpi_integer, 0, mpicom, ierr)
+ if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_year_last")
+ call mpi_bcast(stream_ndep_year_align, 1, mpi_integer, 0, mpicom, ierr)
+ if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_year_align")
+
+ if (masterproc) then
+ write(iulog,'(a)' ) ' '
+ write(iulog,'(a,i8)') 'stream ndep settings:'
+ write(iulog,'(a,a)' ) ' stream_ndep_data_filename = ',trim(stream_ndep_data_filename)
+ write(iulog,'(a,a)' ) ' stream_ndep_mesh_filename = ',trim(stream_ndep_mesh_filename)
+ write(iulog,'(a,a,a)') ' stream_varlist_ndep = ',trim(stream_varlist_ndep(1)), trim(stream_varlist_ndep(2))
+ write(iulog,'(a,i8)') ' stream_ndep_year_first = ',stream_ndep_year_first
+ write(iulog,'(a,i8)') ' stream_ndep_year_last = ',stream_ndep_year_last
+ write(iulog,'(a,i8)') ' stream_ndep_year_align = ',stream_ndep_year_align
+ write(iulog,'(a)' ) ' '
+ endif
+
+ ! Read in units
+ call stream_ndep_check_units(stream_ndep_data_filename)
+
+ ! Initialize the cdeps data type sdat_ndep
+ call shr_strdata_init_from_inline(sdat_ndep, &
+ my_task = iam, &
+ logunit = iulog, &
+ compname = 'ATM', &
+ model_clock = model_clock, &
+ model_mesh = model_mesh, &
+ stream_meshfile = trim(stream_ndep_mesh_filename), &
+ stream_filenames = (/trim(stream_ndep_data_filename)/), &
+ stream_yearFirst = stream_ndep_year_first, &
+ stream_yearLast = stream_ndep_year_last, &
+ stream_yearAlign = stream_ndep_year_align, &
+ stream_fldlistFile = stream_varlist_ndep, &
+ stream_fldListModel = stream_varlist_ndep, &
+ stream_lev_dimname = 'null', &
+ stream_mapalgo = 'bilinear', &
+ stream_offset = 0, &
+ stream_taxmode = 'cycle', &
+ stream_dtlimit = 1.0e30_r8, &
+ stream_tintalgo = 'linear', &
+ stream_name = 'Nitrogen deposition data ', &
+ rc = rc)
+ if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then
+ call ESMF_Finalize(endflag=ESMF_END_ABORT)
+ end if
+
+ end subroutine stream_ndep_init
+
+ !================================================================
+ subroutine stream_ndep_check_units( stream_fldFileName_ndep)
+
+ !--------------------------------------------------------
+ ! Check that units are correct on the file and if need any conversion
+ !--------------------------------------------------------
+
+ use cam_pio_utils , only : cam_pio_createfile, cam_pio_openfile, cam_pio_closefile, pio_subsystem
+ use pio , only : file_desc_t, io_desc_t, var_desc_t, pio_double, pio_def_dim
+ use pio , only : pio_bcast_error, pio_seterrorhandling, pio_inq_varid, pio_get_att
+ use pio , only : PIO_NOERR, PIO_NOWRITE
+
+ ! Arguments
+ character(len=*), intent(in) :: stream_fldFileName_ndep ! ndep filename
+ !
+ ! Local variables
+ type(file_desc_t) :: File ! NetCDF filehandle for ndep file
+ type(var_desc_t) :: vardesc ! variable descriptor
+ integer :: ierr ! error status
+ integer :: err_handling ! temporary
+ character(len=CS) :: ndepunits! ndep units
+ !-----------------------------------------------------------------------
+
+ call cam_pio_openfile( File, trim(stream_fldFileName_ndep), PIO_NOWRITE)
+ call pio_seterrorhandling(File, PIO_BCAST_ERROR, err_handling)
+ ierr = pio_inq_varid(File, stream_varlist_ndep(1), vardesc)
+ if (ierr /= PIO_NOERR) then
+ call endrun(' ERROR finding variable: '//trim(stream_varlist_ndep(1))//" in file: "// &
+ trim(stream_fldFileName_ndep)//errMsg(sourcefile, __LINE__))
+ else
+ ierr = PIO_get_att(File, vardesc, "units", ndepunits)
+ end if
+ call pio_seterrorhandling(File, err_handling)
+ call cam_pio_closefile(File)
+
+ ! Now check to make sure they are correct
+ if (.not. trim(ndepunits) == "g(N)/m2/s" )then
+ call endrun(' ERROR in units for nitrogen deposition equal to: '//trim(ndepunits)//" not units expected"// &
+ errMsg(sourcefile, __LINE__))
+ end if
+
+ end subroutine stream_ndep_check_units
+
+ !================================================================
+ subroutine stream_ndep_interp(cam_out, rc)
+
+ use dshr_methods_mod , only : dshr_fldbun_getfldptr
+ use dshr_strdata_mod , only : shr_strdata_advance
+ use camsrfexch , only : cam_out_t
+ use ppgrid , only : begchunk, endchunk
+ use time_manager , only : get_curr_date
+ use phys_grid , only : get_ncols_p
+
+ ! input/output variables
+ type(cam_out_t) , intent(inout) :: cam_out(begchunk:endchunk)
+ integer , intent(out) :: rc
+
+ ! local variables
+ integer :: i,c,g
+ integer :: year ! year (0, ...) for nstep+1
+ integer :: mon ! month (1, ..., 12) for nstep+1
+ integer :: day ! day of month (1, ..., 31) for nstep+1
+ integer :: sec ! seconds into current date for nstep+1
+ integer :: mcdate ! Current model date (yyyymmdd)
+ real(r8), pointer :: dataptr1d_nhx(:)
+ real(r8), pointer :: dataptr1d_noy(:)
+ !-----------------------------------------------------------------------
+
+ ! Advance sdat stream
+ call get_curr_date(year, mon, day, sec)
+ mcdate = year*10000 + mon*100 + day
+ call shr_strdata_advance(sdat_ndep, ymd=mcdate, tod=sec, logunit=iulog, istr='ndepdyn', rc=rc)
+ if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then
+ call ESMF_Finalize(endflag=ESMF_END_ABORT)
+ end if
+
+ ! Get pointer for stream data that is time and spatially interpolated to model time and grid
+ call dshr_fldbun_getFldPtr(sdat_ndep%pstrm(1)%fldbun_model, stream_varlist_ndep(1), fldptr1=dataptr1d_nhx, rc=rc)
+ if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then
+ call ESMF_Finalize(endflag=ESMF_END_ABORT)
+ end if
+ call dshr_fldbun_getFldPtr(sdat_ndep%pstrm(1)%fldbun_model, stream_varlist_ndep(2), fldptr1=dataptr1d_noy, rc=rc)
+ if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then
+ call ESMF_Finalize(endflag=ESMF_END_ABORT)
+ end if
+
+ g = 1
+ do c = begchunk,endchunk
+ do i = 1,get_ncols_p(c)
+ cam_out(c)%nhx_nitrogen_flx(i) = dataptr1d_nhx(g)
+ cam_out(c)%noy_nitrogen_flx(i) = dataptr1d_noy(g)
+ g = g + 1
+ end do
+ end do
+
+ end subroutine stream_ndep_interp
+
+end module atm_stream_ndep
diff --git a/src/dynamics/eul/dp_coupling.F90 b/src/dynamics/eul/dp_coupling.F90
index 946c66b092..bc900e2d0e 100644
--- a/src/dynamics/eul/dp_coupling.F90
+++ b/src/dynamics/eul/dp_coupling.F90
@@ -269,7 +269,7 @@ subroutine d_p_coupling(ps, t3, u3, v3, q3, &
! Compute initial geopotential heights
call geopotential_t (phys_state(lchnk)%lnpint, phys_state(lchnk)%lnpmid , phys_state(lchnk)%pint , &
phys_state(lchnk)%pmid , phys_state(lchnk)%pdel , phys_state(lchnk)%rpdel , &
- phys_state(lchnk)%t , phys_state(lchnk)%q(:,:,1), rairv(:,:,lchnk), gravit, zvirv, &
+ phys_state(lchnk)%t , phys_state(lchnk)%q(:,:,:), rairv(:,:,lchnk), gravit, zvirv, &
phys_state(lchnk)%zi , phys_state(lchnk)%zm , ncol )
! Compute initial dry static energy, include surface geopotential
diff --git a/src/dynamics/eul/dycore_budget.F90 b/src/dynamics/eul/dycore_budget.F90
new file mode 100644
index 0000000000..7531d69ac7
--- /dev/null
+++ b/src/dynamics/eul/dycore_budget.F90
@@ -0,0 +1,27 @@
+module dycore_budget
+implicit none
+
+public :: print_budget
+
+!=========================================================================================
+contains
+!=========================================================================================
+
+subroutine print_budget(hstwr)
+
+ use spmd_utils, only: masterproc
+ use cam_abortutils, only: endrun
+ use cam_budget, only: thermo_budget_history,thermo_budget_histfile_num
+
+ ! arguments
+ logical, intent(in) :: hstwr(:)
+ character(len=*), parameter :: subname = 'dycore_budget:print_budgets:'
+
+ !--------------------------------------------------------------------------------------
+
+ if (masterproc .and. thermo_budget_history .and. hstwr(thermo_budget_histfile_num)) then
+ call endrun(subname//' is not implemented for the EUL dycore')
+ end if
+end subroutine print_budget
+
+end module dycore_budget
diff --git a/src/dynamics/fv/dp_coupling.F90 b/src/dynamics/fv/dp_coupling.F90
index 4f109bf2ee..0b2aa31d55 100644
--- a/src/dynamics/fv/dp_coupling.F90
+++ b/src/dynamics/fv/dp_coupling.F90
@@ -77,7 +77,7 @@ subroutine d_p_coupling(grid, phys_state, phys_tend, pbuf2d, dyn_out)
use ctem, only: ctem_diags, do_circulation_diags
use diag_module, only: fv_diag_am_calc
use gravity_waves_sources, only: gws_src_fnct
- use cam_thermo, only: cam_thermo_update
+ use cam_thermo, only: cam_thermo_dry_air_update
use shr_const_mod, only: shr_const_rwv
use dyn_comp, only: frontgf_idx, frontga_idx, uzm_idx
use qbo, only: qbo_use_forcing
@@ -85,7 +85,7 @@ subroutine d_p_coupling(grid, phys_state, phys_tend, pbuf2d, dyn_out)
use zonal_mean, only: zonal_mean_3D
use d2a3dikj_mod, only: d2a3dikj
use qneg_module, only: qneg3
-
+ use air_composition,only: dry_air_species_num
!-----------------------------------------------------------------------
implicit none
!-----------------------------------------------------------------------
@@ -572,7 +572,7 @@ subroutine d_p_coupling(grid, phys_state, phys_tend, pbuf2d, dyn_out)
end do
end do
- if ( waccmx_is('ionosphere') .or. waccmx_is('neutral') ) then
+ if (dry_air_species_num>0) then
!------------------------------------------------------------
! Apply limiters to mixing ratios of major species
!------------------------------------------------------------
@@ -581,7 +581,7 @@ subroutine d_p_coupling(grid, phys_state, phys_tend, pbuf2d, dyn_out)
! Call cam_thermo_update to compute cpairv, rairv, mbarv, and cappav as constituent dependent variables
! and compute molecular viscosity(kmvis) and conductivity(kmcnd)
!-----------------------------------------------------------------------------
- call cam_thermo_update(phys_state(lchnk)%q, phys_state(lchnk)%t, lchnk, ncol)
+ call cam_thermo_dry_air_update(phys_state(lchnk)%q, phys_state(lchnk)%t, lchnk, ncol)
endif
!------------------------------------------------------------------------
@@ -596,7 +596,7 @@ subroutine d_p_coupling(grid, phys_state, phys_tend, pbuf2d, dyn_out)
! Compute initial geopotential heights
call geopotential_t (phys_state(lchnk)%lnpint, phys_state(lchnk)%lnpmid , phys_state(lchnk)%pint , &
phys_state(lchnk)%pmid , phys_state(lchnk)%pdel , phys_state(lchnk)%rpdel , &
- phys_state(lchnk)%t , phys_state(lchnk)%q(:,:,1), rairv(:,:,lchnk), gravit, zvirv, &
+ phys_state(lchnk)%t , phys_state(lchnk)%q(:,:,:), rairv(:,:,lchnk), gravit, zvirv, &
phys_state(lchnk)%zi , phys_state(lchnk)%zm , ncol )
! Compute initial dry static energy, include surface geopotential
diff --git a/src/dynamics/fv/dycore_budget.F90 b/src/dynamics/fv/dycore_budget.F90
new file mode 100644
index 0000000000..a672fef9cc
--- /dev/null
+++ b/src/dynamics/fv/dycore_budget.F90
@@ -0,0 +1,27 @@
+module dycore_budget
+implicit none
+
+public :: print_budget
+
+!=========================================================================================
+contains
+!=========================================================================================
+
+subroutine print_budget(hstwr)
+
+ use spmd_utils, only: masterproc
+ use cam_abortutils, only: endrun
+ use cam_budget, only: thermo_budget_histfile_num, thermo_budget_history
+
+ ! arguments
+ logical, intent(in) :: hstwr(:)
+ character(len=*), parameter :: subname = 'dycore_budget:print_budgets:'
+
+ !--------------------------------------------------------------------------------------
+
+ if (masterproc .and. thermo_budget_history .and. hstwr(thermo_budget_histfile_num)) then
+ call endrun(subname//' is not implemented for the FV dycore')
+ end if
+end subroutine print_budget
+
+end module dycore_budget
diff --git a/src/dynamics/fv/metdata.F90 b/src/dynamics/fv/metdata.F90
index 5f49143562..06957af5ef 100644
--- a/src/dynamics/fv/metdata.F90
+++ b/src/dynamics/fv/metdata.F90
@@ -660,7 +660,9 @@ subroutine get_met_srf2( cam_in )
! Nudging land and forcing ocean.
if (met_srf_land_scale) then
- met_rlx_sfc(:ncol) = (1._r8 - cam_in(c)%landfrac(:ncol)) * met_rlx_sfc(:ncol) + cam_in(c)%landfrac(:ncol) * met_rlx(pver)
+ met_rlx_sfc(:ncol) = (1._r8 - cam_in(c)%landfrac(:ncol)) * &
+ met_rlx_sfc(:ncol) + &
+ cam_in(c)%landfrac(:ncol) * met_rlx(pver)
else
where(cam_in(c)%landfrac(:ncol) == 1._r8) met_rlx_sfc(:ncol) = 0._r8
end if
@@ -725,9 +727,9 @@ subroutine get_met_srf2( cam_in )
end if
if (met_srf_refs) then
- cam_in(c)%qref(:ncol) = (1._r8-met_rlx_sfc(:ncol)) * cam_in(c)%qref(:ncol) + met_rlx_sfc(:ncol) * met_qref(:ncol,c)
- cam_in(c)%tref(:ncol) = (1._r8-met_rlx_sfc(:ncol)) * cam_in(c)%tref(:ncol) + met_rlx_sfc(:ncol) * met_tref(:ncol,c)
- cam_in(c)%u10(:ncol) = (1._r8-met_rlx_sfc(:ncol)) * cam_in(c)%u10(:ncol) + met_rlx_sfc(:ncol) * met_u10(:ncol,c)
+ cam_in(c)%qref(:ncol) = (1._r8-met_rlx_sfc(:ncol)) * cam_in(c)%qref(:ncol) + met_rlx_sfc(:ncol) * met_qref(:ncol,c)
+ cam_in(c)%tref(:ncol) = (1._r8-met_rlx_sfc(:ncol)) * cam_in(c)%tref(:ncol) + met_rlx_sfc(:ncol) * met_tref(:ncol,c)
+ cam_in(c)%u10(:ncol) = (1._r8-met_rlx_sfc(:ncol)) * cam_in(c)%u10(:ncol) + met_rlx_sfc(:ncol) * met_u10(:ncol,c)
end if
if (met_srf_sst) then
@@ -902,6 +904,8 @@ subroutine get_dyn_flds( state, tend, dt )
use ppgrid, only: pcols, pver, begchunk, endchunk
use phys_grid, only: get_ncols_p
use cam_history, only: outfld
+ use air_composition,only: thermodynamic_active_species_liq_num, thermodynamic_active_species_ice_num
+ use air_composition,only: thermodynamic_active_species_liq_idx,thermodynamic_active_species_ice_idx
implicit none
@@ -912,7 +916,10 @@ subroutine get_dyn_flds( state, tend, dt )
integer :: lats(pcols) ! array of latitude indices
integer :: lons(pcols) ! array of longitude indices
integer :: c, ncol, i,j,k
- real(r8):: qini(pcols,pver) ! initial specific humidity
+ integer :: m_cnst,m
+ real(r8):: qini(pcols,pver) ! initial specific humidity
+ real(r8):: totliqini(pcols,pver) ! initial total liquid
+ real(r8):: toticeini(pcols,pver) ! initial total ice
real(r8) :: tmp(pcols,pver)
@@ -920,14 +927,26 @@ subroutine get_dyn_flds( state, tend, dt )
do c = begchunk, endchunk
ncol = get_ncols_p(c)
+ !
+ ! update water variables
+ !
+ qini(:ncol,:pver) = state(c)%q(:ncol,:pver,1)
+ totliqini = 0.0_r8
+ do m_cnst=1,thermodynamic_active_species_liq_num
+ m = thermodynamic_active_species_liq_idx(m_cnst)
+ totliqini(:ncol,:pver) = totliqini(:ncol,:pver)+state(c)%q(:ncol,:pver,m)
+ end do
+ toticeini = 0.0_r8
+ do m_cnst=1,thermodynamic_active_species_ice_num
+ m = thermodynamic_active_species_ice_idx(m_cnst)
+ toticeini(:ncol,:pver) = toticeini(:ncol,:pver)+state(c)%q(:ncol,:pver,m)
+ end do
+
do k=1,pver
do i=1,ncol
if (met_nudge_temp) then
state(c)%t(i,k) = (1._r8-met_rlx(k))*state(c)%t(i,k) + met_rlx(k)*met_t(i,k,c)
end if
-
- qini(i,k) = state(c)%q(i,k,1)
-
! at this point tracer mixing ratios have already been
! converted from dry to moist
state(c)%q(i,k,1) = alpha*state(c)%q(i,k,1) + (D1_0-alpha)*met_q(i,k,c)
@@ -940,7 +959,7 @@ subroutine get_dyn_flds( state, tend, dt )
! now adjust mass of each layer now that water vapor has changed
if (( .not. online_test ) .and. (alpha .ne. D1_0 )) then
- call physics_dme_adjust(state(c), tend(c), qini, dt)
+ call physics_dme_adjust(state(c), tend(c), qini, totliqini, toticeini, dt)
endif
end do
diff --git a/src/dynamics/fv3/dp_coupling.F90 b/src/dynamics/fv3/dp_coupling.F90
index 2eb69c448e..3b7fcca69b 100644
--- a/src/dynamics/fv3/dp_coupling.F90
+++ b/src/dynamics/fv3/dp_coupling.F90
@@ -733,7 +733,7 @@ subroutine derived_phys_dry(phys_state, phys_tend, pbuf2d)
! Compute initial geopotential heights - based on full pressure
call geopotential_t (phys_state(lchnk)%lnpint, phys_state(lchnk)%lnpmid , phys_state(lchnk)%pint , &
phys_state(lchnk)%pmid , phys_state(lchnk)%pdel , phys_state(lchnk)%rpdel , &
- phys_state(lchnk)%t , phys_state(lchnk)%q(:,:,1), rairv(:,:,lchnk), gravit, zvirv , &
+ phys_state(lchnk)%t , phys_state(lchnk)%q(:,:,:), rairv(:,:,lchnk), gravit, zvirv , &
phys_state(lchnk)%zi , phys_state(lchnk)%zm , ncol )
! Compute initial dry static energy, include surface geopotential
diff --git a/src/dynamics/fv3/dycore_budget.F90 b/src/dynamics/fv3/dycore_budget.F90
new file mode 100644
index 0000000000..0645edb251
--- /dev/null
+++ b/src/dynamics/fv3/dycore_budget.F90
@@ -0,0 +1,27 @@
+module dycore_budget
+
+implicit none
+
+public :: print_budget
+
+!=========================================================================================
+contains
+!=========================================================================================
+
+subroutine print_budget(hstwr)
+
+ use spmd_utils, only: masterproc
+ use cam_abortutils, only: endrun
+ use cam_budget, only: thermo_budget_histfile_num, thermo_budget_history
+
+ ! arguments
+ logical, intent(in) :: hstwr(:)
+ character(len=*), parameter :: subname = 'dycore_budget:print_budgets:'
+
+ !--------------------------------------------------------------------------------------
+
+ if (masterproc .and. thermo_budget_history .and. hstwr(thermo_budget_histfile_num)) then
+ call endrun(subname//' is not implemented for the FV3 dycore')
+ end if
+end subroutine print_budget
+end module dycore_budget
diff --git a/src/dynamics/mpas/dp_coupling.F90 b/src/dynamics/mpas/dp_coupling.F90
index 2037a820cb..792a7d54b0 100644
--- a/src/dynamics/mpas/dp_coupling.F90
+++ b/src/dynamics/mpas/dp_coupling.F90
@@ -47,6 +47,7 @@ subroutine d_p_coupling(phys_state, phys_tend, pbuf2d, dyn_out)
! dry air mass.
use cam_history, only : hist_fld_active
use mpas_constants, only : Rv_over_Rd => rvord
+ use cam_budget, only : thermo_budget_history
! arguments
type(physics_state), intent(inout) :: phys_state(begchunk:endchunk)
@@ -70,8 +71,6 @@ subroutine d_p_coupling(phys_state, phys_tend, pbuf2d, dyn_out)
real(r8), pointer :: w(:,:)
real(r8), pointer :: theta_m(:,:)
real(r8), pointer :: tracers(:,:,:)
-
-
integer :: lchnk, icol, icol_p, k, kk ! indices over chunks, columns, physics columns and layers
integer :: i, m, ncols, blockid
integer :: block_index
@@ -90,10 +89,7 @@ subroutine d_p_coupling(phys_state, phys_tend, pbuf2d, dyn_out)
character(len=*), parameter :: subname = 'd_p_coupling'
!----------------------------------------------------------------------------
- compute_energy_diags=&
- (hist_fld_active('SE_dBF').or.hist_fld_active('SE_dAP').or.hist_fld_active('SE_dAM').or.&
- hist_fld_active('KE_dBF').or.hist_fld_active('KE_dAP').or.hist_fld_active('KE_dAM').or.&
- hist_fld_active('WV_dBF').or.hist_fld_active('WV_dAP').or.hist_fld_active('WV_dAM'))
+ compute_energy_diags=thermo_budget_history
nCellsSolve = dyn_out % nCellsSolve
index_qv = dyn_out % index_qv
@@ -110,7 +106,7 @@ subroutine d_p_coupling(phys_state, phys_tend, pbuf2d, dyn_out)
tracers => dyn_out % tracers
if (compute_energy_diags) then
- call tot_energy(nCellsSolve, plev,size(tracers, 1), index_qv, zz(:,1:nCellsSolve), zint(:,1:nCellsSolve), &
+ call tot_energy_dyn(nCellsSolve, plev,size(tracers, 1), index_qv, zz(:,1:nCellsSolve), zint(:,1:nCellsSolve), &
rho_zz(:,1:nCellsSolve), theta_m(:,1:nCellsSolve), tracers(:,:,1:nCellsSolve),&
ux(:,1:nCellsSolve),uy(:,1:nCellsSolve),'dBF')
end if
@@ -127,7 +123,7 @@ subroutine d_p_coupling(phys_state, phys_tend, pbuf2d, dyn_out)
if( ierr /= 0 ) call endrun(subname//':failed to allocate pintdry array')
call hydrostatic_pressure( &
- nCellsSolve, plev, zz, zint, rho_zz, theta_m, tracers(index_qv,:,:),&
+ nCellsSolve, plev, size(tracers, 1), index_qv, zz, zint, rho_zz, theta_m, exner, tracers,&
pmiddry, pintdry, pmid)
call t_startf('dpcopy')
@@ -324,7 +320,6 @@ end subroutine p_d_coupling
!=========================================================================================
subroutine derived_phys(phys_state, phys_tend, pbuf2d)
-
! Compute fields in the physics state object which are diagnosed from the
! MPAS prognostic fields.
@@ -332,11 +327,12 @@ subroutine derived_phys(phys_state, phys_tend, pbuf2d)
use check_energy, only: check_energy_timestep_init
use shr_vmath_mod, only: shr_vmath_log
use phys_control, only: waccmx_is
- use cam_thermo, only: cam_thermo_update
- use air_composition, only: rairv
+ use cam_thermo, only: cam_thermo_dry_air_update, cam_thermo_water_update
+ use air_composition, only: rairv, dry_air_species_num
use qneg_module, only: qneg3
use shr_const_mod, only: shr_const_rwv
use constituents, only: qmin
+ use dyn_tests_utils, only: vcoord=>vc_height
! Arguments
type(physics_state), intent(inout) :: phys_state(begchunk:endchunk)
type(physics_tend ), intent(inout) :: phys_tend(begchunk:endchunk)
@@ -344,7 +340,7 @@ subroutine derived_phys(phys_state, phys_tend, pbuf2d)
! Local variables
- integer :: i, k, lchnk, m, ncol
+ integer :: i, k, lchnk, m, ncol, m_cnst
real(r8) :: factor(pcols,pver)
real(r8) :: zvirv(pcols,pver)
@@ -391,7 +387,12 @@ subroutine derived_phys(phys_state, phys_tend, pbuf2d)
do k = 1, pver
! To be consistent with total energy formula in physic's check_energy module only
! include water vapor in moist pdel.
- factor(:ncol,k) = 1._r8 + phys_state(lchnk)%q(:ncol,k,1)
+ factor(:ncol,k) = 1.0_r8
+ do m_cnst=1,thermodynamic_active_species_num
+ m = thermodynamic_active_species_idx(m_cnst)
+ ! at this point all q's are dry
+ factor(:ncol,k) = factor(:ncol,k)+phys_state(lchnk)%q(:ncol,k,m)
+ end do
phys_state(lchnk)%pdel(:ncol,k) = phys_state(lchnk)%pdeldry(:ncol,k)*factor(:ncol,k)
phys_state(lchnk)%rpdel(:ncol,k) = 1._r8 / phys_state(lchnk)%pdel(:ncol,k)
end do
@@ -418,18 +419,10 @@ subroutine derived_phys(phys_state, phys_tend, pbuf2d)
phys_state(lchnk)%exner(:ncol,k) = (pref / phys_state(lchnk)%pmid(:ncol,k))**cappa
end do
- ! Tracers from MPAS are in dry mixing ratio units. CAM's physics package expects constituents
- ! which have been declared to be type 'wet' when they are registered to be represented by mixing
- ! ratios based on moist air mass (dry air + water vapor). Do appropriate conversion here.
- factor(:ncol,:) = 1._r8/factor(:ncol,:)
- do m = 1,pcnst
- if (cnst_type(m) == 'wet') then
- phys_state(lchnk)%q(:ncol,:,m) = factor(:ncol,:)*phys_state(lchnk)%q(:ncol,:,m)
- end if
- end do
- if ( waccmx_is('ionosphere') .or. waccmx_is('neutral') ) then
+
+ if (dry_air_species_num>0) then
!------------------------------------------------------------
! Apply limiters to mixing ratios of major species
!------------------------------------------------------------
@@ -440,11 +433,25 @@ subroutine derived_phys(phys_state, phys_tend, pbuf2d)
! Compute molecular viscosity(kmvis) and conductivity(kmcnd).
! Fill local zvirv variable; calculated for WACCM-X.
!-----------------------------------------------------------------------------
- call cam_thermo_update(phys_state(lchnk)%q, phys_state(lchnk)%t, lchnk, ncol)
+ call cam_thermo_dry_air_update(phys_state(lchnk)%q, phys_state(lchnk)%t, lchnk, ncol)
zvirv(:,:) = shr_const_rwv / rairv(:,:,lchnk) -1._r8
else
zvirv(:,:) = zvir
endif
+ !
+ ! update cp_dycore in module air_composition.
+ ! (note: at this point q is dry)
+ !
+ call cam_thermo_water_update(phys_state(lchnk)%q(1:ncol,:,:), lchnk, ncol, vcoord)
+ ! Tracers from MPAS are in dry mixing ratio units. CAM's physics package expects constituents
+ ! which have been declared to be type 'wet' when they are registered to be represented by mixing
+ ! ratios based on moist air mass (dry air + water vapor). Do appropriate conversion here.
+ factor(:ncol,:) = 1._r8/factor(:ncol,:)
+ do m = 1,pcnst
+ if (cnst_type(m) == 'wet') then
+ phys_state(lchnk)%q(:ncol,:,m) = factor(:ncol,:)*phys_state(lchnk)%q(:ncol,:,m)
+ end if
+ end do
! Compute geopotential height above surface - based on full pressure
! Note that phys_state%zi(:,plev+1) = 0 whereas zint in MPAS is surface height
@@ -452,7 +459,7 @@ subroutine derived_phys(phys_state, phys_tend, pbuf2d)
call geopotential_t( &
phys_state(lchnk)%lnpint, phys_state(lchnk)%lnpmid, phys_state(lchnk)%pint, &
phys_state(lchnk)%pmid, phys_state(lchnk)%pdel, phys_state(lchnk)%rpdel, &
- phys_state(lchnk)%t, phys_state(lchnk)%q(:,:,1), rairv(:,:,lchnk), gravit, zvirv, &
+ phys_state(lchnk)%t, phys_state(lchnk)%q(:,:,:), rairv(:,:,lchnk), gravit, zvirv, &
phys_state(lchnk)%zi, phys_state(lchnk)%zm, ncol)
! Compute initial dry static energy, include surface geopotential
@@ -484,7 +491,7 @@ subroutine derived_tend(nCellsSolve, nCells, t_tend, u_tend, v_tend, q_tend, dyn
use cam_mpas_subdriver, only : cam_mpas_cell_to_edge_winds, cam_mpas_update_halo
use mpas_constants, only : Rv_over_Rd => rvord
use time_manager, only : get_step_size
-
+ use air_composition, only: get_R
! Arguments
integer, intent(in) :: nCellsSolve
integer, intent(in) :: nCells
@@ -525,10 +532,13 @@ subroutine derived_tend(nCellsSolve, nCells, t_tend, u_tend, v_tend, q_tend, dyn
real(r8), pointer :: uy(:,:)
real(r8) :: theta_m_new(pver,nCellsSolve) !modified potential temperature after various physics updates
real(r8) :: rtheta_param(pver,nCellsSolve)!tendency from temperature change only (for diagnostics)
- real(r8) :: qk (thermodynamic_active_species_num,pver,nCellsSolve) !water species before physics (diagnostics)
+ real(r8) :: Rold(nCellsSolve,pver)
+ real(r8) :: Rnew(nCellsSolve,pver)
+ real(r8) :: qk (thermodynamic_active_species_num,pver,nCellsSolve) !water species before physics (diagnostics)
+ real(r8) :: qktmp (nCellsSolve,pver,thermodynamic_active_species_num)
+ integer :: idx_thermo (thermodynamic_active_species_num)
real(r8) :: qwv(pver,nCellsSolve) !water vapor before physics
real(r8) :: facnew, facold
- real(r8), allocatable :: tracers_old(:,:,:)
integer :: iCell,k
@@ -585,38 +595,76 @@ subroutine derived_tend(nCellsSolve, nCells, t_tend, u_tend, v_tend, q_tend, dyn
zint => dyn_in % zint
ux => dyn_in % ux
uy => dyn_in % uy
+
+ if (compute_energy_diags) then
+ !
+ ! Rnew and Rold are only needed for diagnostics purposes
+ !
+ do m=1,thermodynamic_active_species_num
+ idx_thermo(m) = m
+ idx_dycore = thermodynamic_active_species_idx_dycore(m)
+ do iCell = 1, nCellsSolve
+ do k = 1, pver
+ qktmp(iCell,k,m) = tracers(idx_dycore,k,iCell)
+ end do
+ end do
+ end do
+ call get_R(qktmp,idx_thermo,Rnew)
+ Rnew = Rnew*cv/Rgas
+
+ do m=1,thermodynamic_active_species_num
+ idx_dycore = thermodynamic_active_species_idx_dycore(m)
+ do iCell = 1, nCellsSolve
+ do k = 1, pver
+ qktmp(iCell,k,m) = tracers(idx_dycore,k,iCell)-dtime*q_tend(m,k,iCell)
+ end do
+ end do
+ end do
+ call get_R(qktmp,idx_thermo,Rold)
+ Rold=Rold*cv/Rgas
+ else
+ Rnew = 0.0_r8
+ Rold = 1.0_r8
+ end if
!
! Compute q not updated by physics
!
qwv = tracers(index_qv,:,1:nCellsSolve)-dtime*q_tend(index_qv_phys,:,1:nCellsSolve)
-
+ !
+ ! for energy diagnostics compute state with physics tendency (no water change) first
+ ! and then add water changes (parameterizations + dme_adjust)
+ !
do iCell = 1, nCellsSolve
do k = 1, pver
rhodk = zz(k,iCell) * rho_zz(k,iCell)
facold = 1.0_r8 + Rv_over_Rd *qwv(k,iCell)
thetak = theta_m(k,iCell)/facold
-
exnerk = (rgas*rhodk*theta_m(k,iCell)/p0)**(rgas/cv)
- tknew = exnerk*thetak+(cp/cv)*dtime*t_tend(k,icell)
-
-
- thetaknew = (tknew**(cv/cp))*((rgas*rhodk*facold)/p0)**(-rgas/cp)
+ !
+ ! for compute_energy_diags only
+ !
+ tknew = exnerk*thetak+(cp/Rold(iCell,k))*(Rnew(iCell,k)/cp)*dtime*t_tend(k,icell)!for diags only
+ thetaknew = (tknew**(cv/cp))*((rgas*rhodk*facold)/p0)**(-rgas/cp) !for diags only
!
! calculate theta_m tendency due to parameterizations (but no water adjustment)
+ ! (for diagnostics only)
!
- rtheta_param(k,iCell) = (thetaknew-thetak)/dtime
- rtheta_param(k,iCell) = rtheta_param(k,iCell)*(1.0_r8 + Rv_over_Rd *qwv(k,iCell)) !convert to thetam
- rtheta_param(k,iCell) = rtheta_param(k,iCell)*rho_zz(k,iCell)
+ rtheta_param(k,iCell) = (thetaknew-thetak)/dtime !for diags only
+ rtheta_param(k,iCell) = rtheta_param(k,iCell)*(1.0_r8 + Rv_over_Rd *qwv(k,iCell)) !for diags only
+ !convert to thetam
+ rtheta_param(k,iCell) = rtheta_param(k,iCell)*rho_zz(k,iCell) !for diags only
!
! include water change in theta_m
!
facnew = 1.0_r8 + Rv_over_Rd *tracers(index_qv,k,iCell)
+ tknew = exnerk*thetak+dtime*t_tend(k,icell)
thetaknew = (tknew**(cv/cp))*((rgas*rhodk*facnew)/p0)**(-rgas/cp)
rtheta_tend(k,iCell) = (thetaknew*facnew-thetak*facold)/dtime
rtheta_tend(k,iCell) = rtheta_tend(k,iCell) * rho_zz(k,iCell)
end do
end do
+
if (compute_energy_diags) then
!
! compute energy based on parameterization increment (excl. water change)
@@ -631,7 +679,7 @@ subroutine derived_tend(nCellsSolve, nCells, t_tend, u_tend, v_tend, q_tend, dyn
tracers(idx_dycore,:,1:nCellsSolve)= qk(m,:,: )-dtime*q_tend(m,:,1:nCellsSolve)
end do
- call tot_energy( &
+ call tot_energy_dyn( &
nCellsSolve, plev, size(tracers, 1), index_qv, zz(:,1:nCellsSolve), zint(:,1:nCellsSolve), rho_zz(:,1:nCellsSolve), &
theta_m_new, tracers(:,:,1:nCellsSolve), &
ux(:,1:nCellsSolve)+dtime*u_tend(:,1:nCellsSolve)/rho_zz(:,1:nCellsSolve), &
@@ -645,12 +693,17 @@ subroutine derived_tend(nCellsSolve, nCells, t_tend, u_tend, v_tend, q_tend, dyn
! compute energy incl. water change
!
theta_m_new = theta_m(:,1:nCellsSolve)+dtime*rtheta_tend(:,1:nCellsSolve)/rho_zz(:,1:nCellsSolve)
- call tot_energy( &
+ call tot_energy_dyn( &
nCellsSolve, plev, size(tracers, 1), index_qv, zz(:,1:nCellsSolve), zint(:,1:nCellsSolve), &
rho_zz(:,1:nCellsSolve), theta_m_new, tracers(:,:,1:nCellsSolve), &
ux(:,1:nCellsSolve)+dtime*u_tend(:,1:nCellsSolve)/rho_zz(:,1:nCellsSolve), &
uy(:,1:nCellsSolve)+dtime*v_tend(:,1:nCellsSolve)/rho_zz(:,1:nCellsSolve),'dAM')
end if
+ !
+ ! compute energy based on parameterization increment (excl. water change)
+ !
+ theta_m_new = theta_m(:,1:nCellsSolve)+dtime*rtheta_param(:,1:nCellsSolve)/rho_zz(:,1:nCellsSolve)
+
!
! Update halo for rtheta_m tendency
!
@@ -665,8 +718,8 @@ subroutine derived_tend(nCellsSolve, nCells, t_tend, u_tend, v_tend, q_tend, dyn
end subroutine derived_tend
!=========================================================================================
-subroutine hydrostatic_pressure(nCells, nVertLevels, zz, zgrid, rho_zz, theta_m, q, pmiddry, pintdry,pmid)
-
+subroutine hydrostatic_pressure(nCells, nVertLevels, qsize, index_qv, zz, zgrid, rho_zz, theta_m, &
+ exner, q, pmiddry, pintdry,pmid)
! Compute dry hydrostatic pressure at layer interfaces and midpoints
!
! Given arrays of zz, zgrid, rho_zz, and theta_m from the MPAS-A prognostic
@@ -680,71 +733,89 @@ subroutine hydrostatic_pressure(nCells, nVertLevels, zz, zgrid, rho_zz, theta_m,
! Arguments
integer, intent(in) :: nCells
integer, intent(in) :: nVertLevels
- real(r8), dimension(nVertLevels, nCells), intent(in) :: zz ! d(zeta)/dz [-]
- real(r8), dimension(nVertLevels+1, nCells), intent(in) :: zgrid ! geometric heights of layer interfaces [m]
- real(r8), dimension(nVertLevels, nCells), intent(in) :: rho_zz ! dry density / zz [kg m^-3]
- real(r8), dimension(nVertLevels, nCells), intent(in) :: theta_m ! modified potential temperature
- real(r8), dimension(nVertLevels, nCells), intent(in) :: q ! water vapor dry mixing ratio
- real(r8), dimension(nVertLevels, nCells), intent(out):: pmiddry ! layer midpoint dry hydrostatic pressure [Pa]
- real(r8), dimension(nVertLevels+1, nCells), intent(out):: pintdry ! layer interface dry hydrostatic pressure [Pa]
- real(r8), dimension(nVertLevels, nCells), intent(out):: pmid ! layer midpoint hydrostatic pressure [Pa]
+ integer, intent(in) :: qsize
+ integer, intent(in) :: index_qv
+ real(r8), dimension(nVertLevels, nCells), intent(in) :: zz ! d(zeta)/dz [-]
+ real(r8), dimension(nVertLevels+1, nCells), intent(in) :: zgrid ! geometric heights of layer interfaces [m]
+ real(r8), dimension(nVertLevels, nCells), intent(in) :: rho_zz ! dry density / zz [kg m^-3]
+ real(r8), dimension(nVertLevels, nCells), intent(in) :: theta_m ! modified potential temperature
+ real(r8), dimension(nVertLevels, nCells), intent(in) :: exner ! Exner function
+ real(r8), dimension(qsize,nVertLevels, nCells), intent(in) :: q ! water vapor dry mixing ratio
+ real(r8), dimension(nVertLevels, nCells), intent(out):: pmiddry ! layer midpoint dry hydrostatic pressure [Pa]
+ real(r8), dimension(nVertLevels+1, nCells), intent(out):: pintdry ! layer interface dry hydrostatic pressure [Pa]
+ real(r8), dimension(nVertLevels, nCells), intent(out):: pmid ! layer midpoint hydrostatic pressure [Pa]
! Local variables
- integer :: iCell, k
- real(r8), dimension(nVertLevels) :: dz ! Geometric layer thickness in column
- real(r8), dimension(nVertLevels+1) :: pint ! hydrostatic pressure at interface
- real(r8) :: pi, t
- real(r8) :: pk,rhok,rhodryk,theta,thetavk,kap1,kap2
-
+ integer :: iCell, k, idx
+ real(r8), dimension(nVertLevels) :: dz ! Geometric layer thickness in column
+ real(r8), dimension(nVertLevels) :: dp,dpdry ! Pressure thickness
+ real(r8), dimension(nVertLevels+1,nCells) :: pint ! hydrostatic pressure at interface
+ real(r8) :: pi, t, sum_water
+ real(r8) :: pk,rhok,rhodryk,theta,thetavk,kap1,kap2,tvk,tk
!
! For each column, integrate downward from model top to compute dry hydrostatic pressure at layer
! midpoints and interfaces. The pressure averaged to layer midpoints should be consistent with
! the ideal gas law using the rho_zz and theta values prognosed by MPAS at layer midpoints.
!
- kap1 = p0**(-rgas/cp) ! pre-compute constants
- kap2 = cp/cv ! pre-compute constants
do iCell = 1, nCells
-
dz(:) = zgrid(2:nVertLevels+1,iCell) - zgrid(1:nVertLevels,iCell)
+ do k = nVertLevels, 1, -1
+ rhodryk = zz(k,iCell)* rho_zz(k,iCell) !full CAM physics density
+ rhok = 1.0_r8
+ do idx=1,thermodynamic_active_species_num
+ rhok = rhok+q(thermodynamic_active_species_idx_dycore(idx),k,iCell)
+ end do
+ rhok = rhok*rhodryk
+ dp(k) = gravit*dz(k)*rhok
+ dpdry(k) = gravit*dz(k)*rhodryk
+ end do
k = nVertLevels
- rhok = (1.0_r8+q(k,iCell))*zz(k,iCell) * rho_zz(k,iCell) !full CAM physics density
- thetavk = theta_m(k,iCell)/ (1.0_r8 + q(k,iCell)) !convert modified theta to virtual theta
- pk = (rhok*rgas*thetavk*kap1)**kap2 !mid-level top pressure
+ sum_water = 1.0_r8
+ do idx=1,thermodynamic_active_species_num
+ sum_water = sum_water+q(thermodynamic_active_species_idx_dycore(idx),k,iCell)
+ end do
+ rhok = sum_water*zz(k,iCell) * rho_zz(k,iCell)
+ thetavk = theta_m(k,iCell)/sum_water
+ tvk = thetavk*exner(k,iCell)
+ pk = dp(k)*rgas*tvk/(gravit*dz(k))
!
! model top pressure consistently diagnosed using the assumption that the mid level
! is at height z(nVertLevels-1)+0.5*dz
- !
+ !
pintdry(nVertLevels+1,iCell) = pk-0.5_r8*dz(nVertLevels)*rhok*gravity !hydrostatic
- pint (nVertLevels+1) = pintdry(nVertLevels+1,iCell)
+ pint (nVertLevels+1,iCell) = pintdry(nVertLevels+1,iCell)
do k = nVertLevels, 1, -1
!
! compute hydrostatic dry interface pressure so that (pintdry(k+1)-pintdry(k))/g is pseudo density
!
- rhodryk = zz(k,iCell) * rho_zz(k,iCell)
- rhok = (1.0_r8+q(k,iCell))*rhodryk
- pintdry(k,iCell) = pintdry(k+1,iCell) + gravity * rhodryk * dz(k)
- pint (k) = pint (k+1) + gravity * rhok * dz(k)
- end do
-
- do k = nVertLevels, 1, -1
- !hydrostatic mid-level pressure - MPAS full pressure is (rhok*rgas*thetavk*kap1)**kap2
- pmid (k,iCell) = 0.5_r8*(pint(k+1)+pint(k))
- !hydrostatic dry mid-level dry pressure -
- !MPAS non-hydrostatic dry pressure is pmiddry(k,iCell) = (rhodryk*rgas*theta*kap1)**kap2
- pmiddry(k,iCell) = 0.5_r8*(pintdry(k+1,iCell)+pintdry(k,iCell))
+ sum_water = 1.0_r8
+ do idx=1,thermodynamic_active_species_num
+ sum_water = sum_water+q(thermodynamic_active_species_idx_dycore(idx),k,iCell)
+ end do
+ thetavk = theta_m(k,iCell)/sum_water!convert modified theta to virtual theta
+ tvk = thetavk*exner(k,iCell)
+ tk = tvk*sum_water/(1.0_r8+Rv_over_Rd*q(index_qv,k,iCell))
+ pint (k,iCell) = pint (k+1,iCell)+dp(k)
+ pintdry(k,iCell) = pintdry(k+1,iCell)+dpdry(k)
+ pmid(k,iCell) = dp(k) *rgas*tvk/(gravit*dz(k))
+ pmiddry(k,iCell) = dpdry(k)*rgas*tk /(gravit*dz(k))
end do
end do
end subroutine hydrostatic_pressure
-
-subroutine tot_energy(nCells, nVertLevels, qsize, index_qv, zz, zgrid, rho_zz, theta_m, q, ux,uy,outfld_name_suffix)
+subroutine tot_energy_dyn(nCells, nVertLevels, qsize, index_qv, zz, zgrid, rho_zz, theta_m, q, ux,uy,outfld_name_suffix)
use physconst, only: rair, cpair, gravit,cappa!=R/cp (dry air)
use mpas_constants, only: p0,cv,rv,rgas,cp
use cam_history, only: outfld, hist_fld_active
use mpas_constants, only: Rv_over_Rd => rvord
use air_composition, only: thermodynamic_active_species_ice_idx_dycore,thermodynamic_active_species_liq_idx_dycore
use air_composition, only: thermodynamic_active_species_ice_num,thermodynamic_active_species_liq_num
+ use air_composition, only: dry_air_species_num, thermodynamic_active_species_R
+ use cam_thermo, only: wvidx,wlidx,wiidx,seidx,poidx,keidx,teidx,thermo_budget_num_vars
+ use cam_thermo, only: get_hydrostatic_energy,thermo_budget_vars
+ use dyn_tests_utils, only: vcoord=>vc_height
+ use cam_history_support, only: max_fieldname_len
! Arguments
integer, intent(in) :: nCells
integer, intent(in) :: nVertLevels
@@ -760,83 +831,75 @@ subroutine tot_energy(nCells, nVertLevels, qsize, index_qv, zz, zgrid, rho_zz, t
character*(*), intent(in) :: outfld_name_suffix ! suffix for "outfld" names
! Local variables
- integer :: iCell, k, idx
- real(r8) :: rho_dz,zcell,temperature,theta,pk,ptop,exner
- real(r8), dimension(nVertLevels, nCells) :: rhod, dz
- real(r8), dimension(nCells) :: kinetic_energy,potential_energy,internal_energy,water_vapor,water_liq,water_ice
+ integer :: iCell, k, idx, idx_tmp
+ integer :: i
+ real(r8) :: rho_dz,theta,pk,ptop,exner,dz,rhod
+ real(r8), dimension(nCells,nVertLevels) :: temperature, pdeldry, cp_or_cv, zcell, u, v
+ real(r8), dimension(nCells) :: phis
+ real(r8), dimension(nCells,nVertLevels,qsize) :: tracers
+ real(r8), dimension(nCells) :: kinetic_energy,potential_energy,internal_energy,water_vapor
real(r8), dimension(nCells) :: liq !total column integrated liquid
real(r8), dimension(nCells) :: ice !total column integrated ice
-
- character(len=16) :: name_out1,name_out2,name_out3,name_out4,name_out5
-
- name_out1 = 'SE_' //trim(outfld_name_suffix)
- name_out2 = 'KE_' //trim(outfld_name_suffix)
- name_out3 = 'WV_' //trim(outfld_name_suffix)
- name_out4 = 'WL_' //trim(outfld_name_suffix)
- name_out5 = 'WI_' //trim(outfld_name_suffix)
-
- if ( hist_fld_active(name_out1).or.hist_fld_active(name_out2).or.hist_fld_active(name_out3).or.&
- hist_fld_active(name_out4).or.hist_fld_active(name_out5)) then
-
- kinetic_energy = 0.0_r8
- potential_energy = 0.0_r8
- internal_energy = 0.0_r8
- water_vapor = 0.0_r8
-
- do iCell = 1, nCells
- do k = 1, nVertLevels
- dz(k,iCell) = zgrid(k+1,iCell) - zgrid(k,iCell)
- zcell = 0.5_r8*(zgrid(k,iCell)+zgrid(k+1,iCell))
- rhod(k,iCell) = zz(k,iCell) * rho_zz(k,iCell)
- rho_dz = (1.0_r8+q(index_qv,k,iCell))*rhod(k,iCell)*dz(k,iCell)
- theta = theta_m(k,iCell)/(1.0_r8 + Rv_over_Rd *q(index_qv,k,iCell))!convert theta_m to theta
-
- exner = (rgas*rhod(k,iCell)*theta_m(k,iCell)/p0)**(rgas/cv)
- temperature = exner*theta
-
- water_vapor(iCell) = water_vapor(iCell) + rhod(k,iCell)*q(index_qv,k,iCell)*dz(k,iCell)
- kinetic_energy(iCell) = kinetic_energy(iCell) + &
- 0.5_r8*(ux(k,iCell)**2._r8+uy(k,iCell)**2._r8)*rho_dz
- potential_energy(iCell) = potential_energy(iCell)+ rho_dz*gravit*zcell
- internal_energy(iCell) = internal_energy(iCell) + rho_dz*cv*temperature
- end do
- internal_energy(iCell) = internal_energy(iCell) + potential_energy(iCell) !static energy
- end do
- call outfld(name_out1,internal_energy,ncells,1)
- call outfld(name_out2,kinetic_energy ,ncells,1)
- call outfld(name_out3,water_vapor ,ncells,1)
- !
- ! vertical integral of total liquid water
- !
- if (hist_fld_active(name_out4)) then
- liq = 0._r8
- do idx = 1,thermodynamic_active_species_liq_num
- do iCell = 1, nCells
- do k = 1, nVertLevels
- liq(iCell) = liq(iCell) + &
- q(thermodynamic_active_species_liq_idx_dycore(idx),k,iCell)*rhod(k,iCell)*dz(k,iCell)
- end do
+ real(r8) :: sum_species
+
+ character(len=max_fieldname_len) :: name_out(thermo_budget_num_vars)
+
+
+ do i=1,thermo_budget_num_vars
+ name_out(i)=trim(thermo_budget_vars(i))//'_'//trim(outfld_name_suffix)
+ end do
+
+ kinetic_energy = 0.0_r8
+ potential_energy = 0.0_r8
+ internal_energy = 0.0_r8
+ water_vapor = 0.0_r8
+ tracers = 0.0_r8
+
+ do iCell = 1, nCells
+ do k = 1, nVertLevels
+ dz = zgrid(k+1,iCell) - zgrid(k,iCell)
+ zcell(iCell,k) = 0.5_r8*(zgrid(k,iCell)+zgrid(k+1,iCell))-zgrid(1,iCell)
+ rhod = zz(k,iCell) * rho_zz(k,iCell)
+ theta = theta_m(k,iCell)/(1.0_r8 + Rv_over_Rd *q(index_qv,k,iCell))!convert theta_m to theta
+ exner = (rgas*rhod*theta_m(k,iCell)/p0)**(rgas/cv)
+
+ temperature(iCell,k) = exner*theta
+ pdeldry(iCell,k) = gravit*rhod*dz
+ !
+ ! internal energy coefficient for MPAS
+ ! (equation 92 in Eldred et al. 2023; https://rmets.onlinelibrary.wiley.com/doi/epdf/10.1002/qj.4353)
+ !
+ cp_or_cv(iCell,k) = rair
+ sum_species = 1.0_r8
+ do idx=dry_air_species_num + 1,thermodynamic_active_species_num
+ idx_tmp = thermodynamic_active_species_idx_dycore(idx)
+ cp_or_cv(iCell,k) = cp_or_cv(iCell,k)+thermodynamic_active_species_R(idx)*q(idx_tmp,k,iCell)
+ sum_species = sum_species+q(idx_tmp,k,iCell)
end do
- end do
- call outfld(name_out4,liq,ncells,1)
- end if
- !
- ! vertical integral of total frozen (ice) water
- !
- if (hist_fld_active(name_out5)) then
- ice = 0._r8
- do idx = 1,thermodynamic_active_species_ice_num
- do iCell = 1, nCells
- do k = 1, nVertLevels
- ice(iCell) = ice(iCell) + &
- q(thermodynamic_active_species_ice_idx_dycore(idx),k,iCell)*rhod(k,iCell)*dz(k,iCell)
- end do
+ cp_or_cv(iCell,k) = cv*cp_or_cv(iCell,k)/(sum_species*rair)
+ u(iCell,k) = ux(k,iCell)
+ v(iCell,k) = uy(k,iCell)
+ phis(iCell) = zgrid(1,iCell)*gravit
+ do idx=1,thermodynamic_active_species_num
+ idx_tmp = thermodynamic_active_species_idx_dycore(idx)
+ tracers(iCell,k,idx_tmp) = q(idx_tmp,k,iCell)
end do
- end do
- call outfld(name_out5,ice,ncells,1)
- end if
- end if
- end subroutine tot_energy
+ end do
+ enddo
+ call get_hydrostatic_energy(tracers, .false., pdeldry, cp_or_cv, u, v, temperature, &
+ vcoord=vcoord, phis = phis, z_mid=zcell, dycore_idx=.true., &
+ se=internal_energy, po=potential_energy, ke=kinetic_energy, &
+ wv=water_vapor , liq=liq , ice=ice)
+
+ call outfld(name_out(seidx),internal_energy ,ncells,1)
+ call outfld(name_out(poidx),potential_energy,ncells,1)
+ call outfld(name_out(keidx),kinetic_energy ,ncells,1)
+ call outfld(name_out(wvidx),water_vapor ,ncells,1)
+ call outfld(name_out(wlidx),liq ,ncells,1)
+ call outfld(name_out(wiidx),ice ,ncells,1)
+ call outfld(name_out(teidx),potential_energy+internal_energy+kinetic_energy,ncells,1)
+
+end subroutine tot_energy_dyn
end module dp_coupling
diff --git a/src/dynamics/mpas/dycore_budget.F90 b/src/dynamics/mpas/dycore_budget.F90
new file mode 100644
index 0000000000..18dd0e1375
--- /dev/null
+++ b/src/dynamics/mpas/dycore_budget.F90
@@ -0,0 +1,407 @@
+module dycore_budget
+use shr_kind_mod, only: r8=>shr_kind_r8
+implicit none
+
+public :: print_budget
+real(r8), parameter :: eps = 1.0E-9_r8
+real(r8), parameter :: eps_mass = 1.0E-12_r8
+real(r8), save :: previous_dEdt_dry_mass_adjust = 0.0_r8
+real(r8), save :: previous_dEdt_phys_dyn_coupl_err_Agrid = 0.0_r8
+!=========================================================================================
+contains
+!=========================================================================================
+
+subroutine print_budget(hstwr)
+
+ use cam_budget, only: cam_budget_get_global, thermo_budget_histfile_num, thermo_budget_history
+ use spmd_utils, only: masterproc
+ use cam_logfile, only: iulog
+ use cam_abortutils, only: endrun
+ use cam_thermo, only: thermo_budget_vars_descriptor, thermo_budget_num_vars, thermo_budget_vars_massv
+ use cam_thermo, only: teidx, seidx, keidx, poidx
+
+ ! arguments
+ logical, intent(in) :: hstwr(:)
+
+ ! Local variables
+ character(len=*), parameter :: subname = 'dycore_budget:print_budgets:'
+ !
+ ! physics energy tendencies
+ !
+ integer :: idx(4)
+ real(r8) :: dEdt_param_physE(4) ! dE/dt CAM physics using physics E formula (phAP-phBP)
+ real(r8) :: dEdt_param_dynE(4) ! dE/dt CAM physics using dycore E (dyAP-dyBP)
+
+ real(r8) :: dEdt_efix_physE(4) ! dE/dt energy fixer using physics E formula (phBP-phBF)
+ real(r8) :: dEdt_efix_dynE(4) ! dE/dt energy fixer using dycore E formula (dyBP-dyBF)
+
+ real(r8) :: dEdt_dme_adjust_physE(4) ! dE/dt dry mass adjustment using physics E formula (phAM-phAP)
+ real(r8) :: dEdt_dme_adjust_dynE(4) ! dE/dt dry mass adjustment using dycore E (dyAM-dyAP)
+
+ real(r8) :: dEdt_param_efix_physE(4) ! dE/dt CAM physics + energy fixer using physics E formula (phAP-phBF)
+ real(r8) :: dEdt_param_efix_dynE(4) ! dE/dt CAM physics + energy fixer using dycore E formula (dyAP-dyBF)
+
+ real(r8) :: dEdt_phys_total_dynE(4) ! dE/dt physics total using dycore E (dyAM-dyBF)
+ ! physics total = parameterizations + efix + dry-mass adjustment
+ !
+ ! dycore specific energy tendencies
+ !
+ real(r8) :: dEdt_phys_total_in_dyn(4) ! dEdt of physics total in dynamical core
+ ! physics total = parameterizations + efix + dry-mass adjustment
+ real(r8) :: dEdt_param_efix_in_dyn(4) ! dEdt CAM physics + energy fixer in dynamical core
+ real(r8) :: dEdt_dme_adjust_in_dyn(4) ! dEdt of dme adjust in dynamical core
+ real(r8) :: dEdt_dycore_and_pdc_estimated_from_efix ! dEdt dycore and PDC errors (estimated in physics)
+ !
+ ! mass budgets physics
+ !
+ real(r8) :: dMdt_efix ! mass tendency energy fixer
+ real(r8) :: dMdt_parameterizations ! mass tendency physics paramterizations
+ real(r8) :: dMdt_dme_adjust ! mass tendency dry-mass adjustment
+ real(r8) :: dMdt_phys_total ! mass tendency physics total (energy fixer + parameterizations + dry-mass adjustment)
+ !
+ ! mass budgets dynamics
+ !
+ real(r8) :: dMdt_phys_total_in_dyn ! mass tendency physics total in dycore
+ real(r8) :: dMdt_PDC ! mass tendency physics-dynamics coupling
+ !
+ ! physics-dynamics coupling variables
+ !
+ real(r8) :: E_dBF(4) ! E of dynamics state at the end of dycore integration (on dycore deomposition)
+ real(r8) :: E_dyBF(4) ! E of physics state using dycore E
+
+
+ real(r8) :: diff, tmp ! dummy variables
+ integer :: m_cnst, i
+ character(LEN=*), parameter :: fmt = "(a40,a15,a1,F6.2,a1,F6.2,a1,E10.2,a5)"
+ character(LEN=*), parameter :: fmtf = "(a48,F8.4,a6)"
+ character(LEN=*), parameter :: fmtm = "(a48,E8.2,a9)"
+ character(LEN=15) :: str(4)
+ character(LEN=5) :: pf ! pass or fail identifier
+ !--------------------------------------------------------------------------------------
+
+ if (masterproc .and. thermo_budget_history .and. hstwr(thermo_budget_histfile_num)) then
+ idx(1) = teidx !total energy index
+ idx(2) = seidx !enthaly index
+ idx(3) = keidx !kinetic energy index
+ idx(4) = poidx !surface potential energy index
+ str(1) = "(total )"
+ str(2) = "(internal )"
+ str(3) = "(kinetic )"
+ str(4) = "(potential )"
+ do i=1,4
+ !
+ ! CAM physics energy tendencies
+ !
+ call cam_budget_get_global('phAP-phBP',idx(i),dEdt_param_physE(i))
+ call cam_budget_get_global('phBP-phBF',idx(i),dEdt_efix_physE(i))
+ call cam_budget_get_global('phAM-phAP',idx(i),dEdt_dme_adjust_physE(i))
+ call cam_budget_get_global('phAP-phBF',idx(i),dEdt_param_efix_physE(i))
+ !
+ ! CAM physics energy tendencies using dycore energy formula scaling
+ ! temperature tendencies for consistency with CAM physics
+ !
+ call cam_budget_get_global('dyAP-dyBP',idx(i),dEdt_param_dynE(i))
+ call cam_budget_get_global('dyBP-dyBF',idx(i),dEdt_efix_dynE(i))
+ call cam_budget_get_global('dyAM-dyAP',idx(i),dEdt_dme_adjust_dynE(i))
+ call cam_budget_get_global('dyAP-dyBF',idx(i),dEdt_param_efix_dynE(i))
+ call cam_budget_get_global('dyAM-dyBF',idx(i),dEdt_phys_total_dynE(i))
+ call cam_budget_get_global('dyBF' ,idx(i),E_dyBF(i))!state beginning physics
+ !
+ ! CAM physics energy tendencies in dynamical core
+ !
+ call cam_budget_get_global('dAP-dBF',teidx,dEdt_param_efix_in_dyn(i))
+ call cam_budget_get_global('dAM-dAP',teidx,dEdt_dme_adjust_in_dyn(i))
+ call cam_budget_get_global('dAM-dBF',teidx,dEdt_param_efix_in_dyn(i))
+
+ call cam_budget_get_global('dAM-dBF',idx(i),dEdt_phys_total_in_dyn(i))
+ call cam_budget_get_global('dBF' ,idx(i),E_dBF(i)) !state passed to physics
+ end do
+ write(iulog,*)" "
+ write(iulog,*)"======================================================================"
+ write(iulog,*)"Total energy diagnostics introduced in Lauritzen and Williamson (2019)"
+ write(iulog,*)"(DOI:10.1029/2018MS001549)"
+ write(iulog,*)"======================================================================"
+ write(iulog,*)" "
+ write(iulog,*)"Globally and vertically integrated total energy (E) diagnostics are"
+ write(iulog,*)"computed at various points in the physics and dynamics loops to compute"
+ write(iulog,*)"energy tendencies (dE/dt) and check for consistency (e.g., is E of"
+ write(iulog,*)"state passed to physics computed using dycore state variables the same"
+ write(iulog,*)"E of the state in the beginning of physics computed using the physics"
+ write(iulog,*)"representation of the state)"
+ write(iulog,*)" "
+ write(iulog,*)"Energy stages in physics:"
+ write(iulog,*)"-------------------------"
+ write(iulog,*)" "
+ write(iulog,*)" xxBF: state passed to parameterizations, before energy fixer"
+ write(iulog,*)" xxBP: after energy fixer, before parameterizations"
+ write(iulog,*)" xxAP: after last phys_update in parameterizations and state "
+ write(iulog,*)" saved for energy fixer"
+ write(iulog,*)" xxAM: after dry mass adjustment"
+ write(iulog,*)" history files saved off here"
+ write(iulog,*)" "
+ write(iulog,*)"where xx='ph','dy' "
+ write(iulog,*)" "
+ write(iulog,*)"Suffix ph is CAM physics total energy"
+ write(iulog,*)"(eq. 111 in Lauritzen et al. 2022; 10.1029/2022MS003117)"
+ write(iulog,*)" "
+ write(iulog,*)"Suffix dy is dycore energy computed in CAM physics using"
+ write(iulog,*)"CAM physics state variables"
+ write(iulog,*)" "
+ write(iulog,*)" "
+ write(iulog,*)"Energy stages in dynamics"
+ write(iulog,*)"-------------------------"
+ write(iulog,*)" "
+ write(iulog,*)" dBF: dynamics state before physics (d_p_coupling)"
+ write(iulog,*)" dAP: dynamics state with T,u,V increment but not incl water changes"
+ write(iulog,*)" dAM: dynamics state with full physics increment (incl. water)"
+ write(iulog,*)" "
+ write(iulog,*)"Note that these energies are computed using the dynamical core"
+ write(iulog,*)"state variables which may be different from the physics prognostic"
+ write(iulog,*)"variables."
+ write(iulog,*)" "
+ write(iulog,*)" "
+ write(iulog,*)"FYI : norm. diff = absolute normalized difference"
+ write(iulog,*)"FYI2: diff = difference (not normalized)"
+ write(iulog,*)" "
+ write(iulog,*)" "
+ write(iulog,*)"Consistency check 0:"
+ write(iulog,*)"--------------------"
+ write(iulog,*)" "
+ write(iulog,*)"For energetic consistency we require that dE/dt [W/m^2] from energy "
+ write(iulog,*)"fixer and all parameterizations computed using physics E and"
+ write(iulog,*)"dycore in physics E are the same! Checking:"
+ write(iulog,*)" "
+ write(iulog,*) " xx=ph xx=dy norm. diff."
+ write(iulog,*) " ----- ----- -----------"
+ do i=1,4
+ diff = abs_diff(dEdt_efix_physE(i),dEdt_efix_dynE(i),pf=pf)
+ write(iulog,fmt)"dE/dt energy fixer (xxBP-xxBF) ",str(i)," ",dEdt_efix_physE(i), " ",dEdt_efix_dynE(i)," ",diff,pf
+ diff = abs_diff(dEdt_param_physE(i),dEdt_param_dynE(i),pf=pf)
+ write(iulog,fmt)"dE/dt all parameterizations (xxAP-xxBP) ",str(i)," ",dEdt_param_physE(i)," ",dEdt_param_dynE(i)," ",diff,pf
+ write(iulog,*) " "
+ if (diff>eps) then
+ write(iulog,*)"FAIL"
+ call endrun(subname//"dE/dt's in physics inconsistent")
+ end if
+ end do
+ write(iulog,*)" "
+ write(iulog,*)" "
+ write(iulog,*)"dE/dt from dry-mass adjustment will differ if dynamics and physics use"
+ write(iulog,*)"different energy definitions! Checking:"
+ write(iulog,*)" "
+ write(iulog,*) " xx=ph xx=dy diff"
+ write(iulog,*) " ----- ----- ----"
+ do i=1,4
+ diff = dEdt_dme_adjust_physE(i)-dEdt_dme_adjust_dynE(i)
+ write(iulog,fmt)"dE/dt dry mass adjustment (xxAM-xxAP) ",str(i)," ",dEdt_dme_adjust_physE(i), &
+ " ",dEdt_dme_adjust_dynE(i)," ",diff
+ end do
+ write(iulog,*)" "
+ write(iulog,*)"Compare to dry mass adjustment in dynamics (xx=d,dy):"
+ write(iulog,*) " xx=d xx=dy norm. diff"
+ write(iulog,*) " ----- ----- ----------"
+ do i=1,4
+ diff = abs_diff(dEdt_dme_adjust_in_dyn(i),dEdt_dme_adjust_dynE(i),pf=pf)
+ write(iulog,fmt)"dE/dt dry mass adjustment (xxAM-xxAP) ",str(i)," ",dEdt_dme_adjust_in_dyn(i),&
+ " ",dEdt_dme_adjust_dynE(i)," ",diff,pf
+ end do
+ write(iulog,*)" "
+ write(iulog,*)" "
+ !
+ ! these diagnostics only make sense time-step to time-step
+ !
+ write(iulog,*)" "
+ write(iulog,*)"Some energy budget observations:"
+ write(iulog,*)"--------------------------------"
+ write(iulog,*)" "
+ write(iulog,*)" Note that total energy fixer fixes:"
+ write(iulog,*)" "
+ write(iulog,*)" -dE/dt energy fixer(t=n) = dE/dt dry mass adjustment (t=n-1) +"
+ write(iulog,*)" dE/dt adiabatic dycore (t=n-1) +"
+ write(iulog,*)" dE/dt physics-dynamics coupling errors (t=n-1)"
+ write(iulog,*)" "
+ write(iulog,*)" (equation 23 in Lauritzen and Williamson (2019))"
+ write(iulog,*)" "
+ write(iulog,*)" Technically this equation is only valid with instantaneous time-step to"
+ write(iulog,*)" time-step output"
+ write(iulog,*) " "
+ write(iulog,*) " dE/dt energy fixer(t=n) = ",dEdt_efix_dynE(1)
+ write(iulog,*) " dE/dt dry mass adjustment (t=n-1) = ",previous_dEdt_dry_mass_adjust
+ write(iulog,*) " dE/dt adiabatic dycore (t=n-1) = unknown"
+ write(iulog,*) " dE/dt PDC errors (A-grid) (t=n-1) = ",previous_dEdt_phys_dyn_coupl_err_Agrid
+ write(iulog,*) " dE/dt PDC errors (other ) (t=n-1) = unknown"
+
+ dEdt_dycore_and_pdc_estimated_from_efix = -dEdt_efix_dynE(1) - &
+ previous_dEdt_phys_dyn_coupl_err_Agrid - &
+ previous_dEdt_dry_mass_adjust
+ write(iulog,*) " "
+ write(iulog,*) "Hence the dycore E dissipation and physics-dynamics coupling errors"
+ write(iulog,*) "associated with mapping wind tendencies to C-grid and dribbling "
+ write(iulog,*) "tendencies in the dycore (PDC other), estimated from energy fixer "
+ write(iulog,'(A39,F6.2,A6)') "based on previous time-step values is ",dEdt_dycore_and_pdc_estimated_from_efix," W/M^2"
+ write(iulog,*) " "
+ write(iulog,*) " "
+ write(iulog,*) "-------------------------------------------------------------------"
+ write(iulog,*) " Consistency check 1: state passed to physics same as end dynamics?"
+ write(iulog,*) "-------------------------------------------------------------------"
+ write(iulog,*) " "
+ write(iulog,*) "Is globally integrated total energy of state at the end of dynamics (dBF)"
+ write(iulog,*) "and beginning of physics (using dynamics in physics energy; dyBF) the same?"
+ write(iulog,*) ""
+
+ if (abs(E_dyBF(1))>eps) then
+ diff = abs_diff(E_dBF(1),E_dyBF(1))
+ if (abs(diff)eps) then
+ do i=1,4
+ write(iulog,*) str(i),":"
+ write(iulog,*) "======"
+ diff = abs_diff(dEdt_phys_total_dynE(i),dEdt_phys_total_in_dyn(i),pf=pf)
+ write(iulog,*) "dE/dt physics-dynamics coupling errors (diff) ",diff
+ write(iulog,*) "dE/dt physics total in dynamics (dAM-dBF) ",dEdt_phys_total_in_dyn(i)
+ write(iulog,*) "dE/dt physics total in physics (pAM-pBF) ",dEdt_phys_total_dynE(i)
+ write(iulog,*) " "
+ write(iulog,*) " physics total = parameterizations + efix + dry-mass adjustment"
+ write(iulog,*) " "
+ end do
+ end if
+ write(iulog,*)" "
+ write(iulog,*)"------------------------------------------------------------"
+ write(iulog,*)" MPAS dycore energy tendencies"
+ write(iulog,*)"------------------------------------------------------------"
+ write(iulog,*)" "
+ write(iulog,*)" Energy diagnostics have not been implemented in the MPAS"
+ write(iulog,*)" dynamical core so a detailed budget is not available."
+ write(iulog,*)" "
+ write(iulog,*)" dE/dt adiabatic dynamical core must therefore be estimated"
+ write(iulog,*)" from"
+ write(iulog,*)" "
+ write(iulog,*)" dE/dt adiabatic dycore (t=n-1) = "
+ write(iulog,*)" -dE/dt dry mass adjustment (t=n-1) +"
+ write(iulog,*)" -dE/dt energy fixer(t=n)"
+ write(iulog,*)" -dE/dt physics-dynamics coupling errors (t=n-1)"
+ write(iulog,*)" "
+ dEdt_dycore_and_pdc_estimated_from_efix = -dEdt_efix_dynE(1)-previous_dEdt_dry_mass_adjust
+ write(iulog,'(A34,F6.2,A6)') " = ",dEdt_dycore_and_pdc_estimated_from_efix," W/M^2"
+ write(iulog,*)" "
+ write(iulog,*)" assuming no physics-dynamics coupling errors, that is,"
+ write(iulog,*)" dE/dt physics-dynamics coupling errors (t=n-1) = 0"
+ write(iulog,*)" "
+ write(iulog,*)" For MPAS the physics-dynamics coupling errors include:"
+ write(iulog,*)" - `dribbling' temperature and wind tendencies during the"
+ write(iulog,*)" dynamical core time-integration"
+ write(iulog,*)" - mapping wind tendencies from A to C grid"
+ write(iulog,*)" "
+
+ write(iulog,*)" "
+ write(iulog,*)"------------------------------------------------------------"
+ write(iulog,*)"Tracer mass budgets"
+ write(iulog,*)"------------------------------------------------------------"
+ write(iulog,*)" "
+ write(iulog,*)"Below the physics-dynamics coupling error is computed as "
+ write(iulog,*)"dMASS/dt physics tendency in dycore (dBD-dAF) minus"
+ write(iulog,*)"dMASS/dt total physics (pAM-pBF)"
+ write(iulog,*)" "
+ write(iulog,*)" "
+ do m_cnst=1,thermo_budget_num_vars
+ if (thermo_budget_vars_massv(m_cnst)) then
+ write(iulog,*)thermo_budget_vars_descriptor(m_cnst)
+ write(iulog,*)"------------------------------"
+ call cam_budget_get_global('phBP-phBF',m_cnst,dMdt_efix)
+ call cam_budget_get_global('phAM-phAP',m_cnst,dMdt_dme_adjust)
+ call cam_budget_get_global('phAP-phBP',m_cnst,dMdt_parameterizations)
+ call cam_budget_get_global('phAM-phBF',m_cnst,dMdt_phys_total)
+ !
+ ! total energy fixer should not affect mass - checking
+ !
+ if (abs(dMdt_efix)>eps_mass) then
+ write(iulog,*) "dMASS/dt energy fixer (pBP-pBF) ",dMdt_efix," Pa/m^2/s"
+ write(iulog,*) "ERROR: Mass not conserved in energy fixer. ABORT"
+ call endrun(subname//"Mass not conserved in energy fixer. See atm.log")
+ endif
+ !
+ ! dry-mass adjustmnt should not affect mass - checking
+ !
+ if (abs(dMdt_dme_adjust)>eps_mass) then
+ write(iulog,*)"dMASS/dt dry mass adjustment (pAM-pAP) ",dMdt_dme_adjust," Pa/m^2/s"
+ write(iulog,*) "ERROR: Mass not conserved in dry mass adjustment. ABORT"
+ call endrun(subname//"Mass not conserved in dry mass adjustment. See atm.log")
+ end if
+ !
+ ! all of the mass-tendency should come from parameterization - checking
+ !
+ if (abs(dMdt_parameterizations-dMdt_phys_total)>eps_mass) then
+ write(iulog,*) "Error: dMASS/dt parameterizations (pAP-pBP) /= dMASS/dt physics total (pAM-pBF)"
+ write(iulog,*) "dMASS/dt parameterizations (pAP-pBP) ",dMdt_parameterizations," Pa/m^2/s"
+ write(iulog,*) "dMASS/dt physics total (pAM-pBF) ",dMdt_phys_total," Pa/m^2/s"
+ call endrun(subname//"mass change not only due to parameterizations. See atm.log")
+ end if
+ write(iulog,*)" "
+ !
+ ! check if mass change in physics is the same as dynamical core
+ !
+ call cam_budget_get_global('dAM-dBF',m_cnst,dMdt_phys_total_in_dyn)
+ dMdt_PDC = dMdt_phys_total-dMdt_phys_total_in_dyn
+ write(iulog,fmtm)" Mass physics-dynamics coupling error ",dMdt_PDC," Pa/m^2/s"
+ write(iulog,*)" "
+ if (abs(dMdt_PDC)>eps_mass) then
+ write(iulog,fmtm)" dMASS/dt physics tendency in dycore (dAM-dBF) ",dMdt_phys_total_in_dyn," Pa/m^2/s"
+ write(iulog,fmtm)" dMASS/dt total physics ",dMdt_phys_total," Pa/m^2/s"
+ end if
+ end if
+ end do
+ !
+ ! save dry-mass adjustment to avoid sampling error
+ !
+ previous_dEdt_dry_mass_adjust = dEdt_dme_adjust_dynE(1)
+ end if
+ end subroutine print_budget
+ !=========================================================================================
+ function abs_diff(a,b,pf)
+ real(r8), intent(in) :: a,b
+ character(LEN=5), optional, intent(out):: pf
+ real(r8) :: abs_diff
+ if (abs(b)>eps) then
+ abs_diff = abs((b-a)/b)
+ else
+ abs_diff = abs(b-a)
+ end if
+ if (present(pf)) then
+ if (abs_diff>eps) then
+ pf = ' FAIL'
+ else
+ pf = ' PASS'
+ end if
+ end if
+ end function abs_diff
+end module dycore_budget
+
diff --git a/src/dynamics/mpas/dyn_comp.F90 b/src/dynamics/mpas/dyn_comp.F90
index d4ff112434..7b27c4521e 100644
--- a/src/dynamics/mpas/dyn_comp.F90
+++ b/src/dynamics/mpas/dyn_comp.F90
@@ -22,7 +22,7 @@ module dyn_comp
use inic_analytic, only: analytic_ic_active, dyn_set_inic_col
use dyn_tests_utils, only: vcoord=>vc_height
-use cam_history, only: addfld, add_default, horiz_only, register_vector_field, &
+use cam_history, only: add_default, horiz_only, register_vector_field, &
outfld, hist_fld_active
use cam_history_support, only: max_fieldname_len
use string_utils, only: date2yyyymmdd, sec2hms, int2str
@@ -39,8 +39,9 @@ module dyn_comp
use cam_abortutils, only: endrun
use mpas_timekeeping, only : MPAS_TimeInterval_type
-
use cam_mpas_subdriver, only: cam_mpas_global_sum_real
+use cam_budget, only: cam_budget_em_snapshot, cam_budget_em_register
+
implicit none
private
@@ -196,8 +197,6 @@ module dyn_comp
real(r8), dimension(:), pointer :: fzm ! Interp weight from k layer midpoint to k layer
! interface [dimensionless] (nver)
real(r8), dimension(:), pointer :: fzp ! Interp weight from k-1 layer midpoint to k
- ! layer interface [dimensionless] (nver)
-
!
! State that may be directly derived from dycore prognostic state
!
@@ -316,6 +315,9 @@ subroutine dyn_init(dyn_in, dyn_out)
use mpas_constants, only : mpas_constants_compute_derived
use dyn_tests_utils, only : vc_dycore, vc_height, string_vc, vc_str_lgth
use constituents, only : cnst_get_ind
+ use phys_control, only: phys_getopts
+ use cam_budget, only: thermo_budget_history
+
! arguments:
type(dyn_import_t), intent(inout) :: dyn_in
type(dyn_export_t), intent(inout) :: dyn_out
@@ -347,29 +349,21 @@ subroutine dyn_init(dyn_in, dyn_out)
character(len=*), parameter :: subname = 'dyn_comp::dyn_init'
! variables for initializing energy and axial angular momentum diagnostics
- integer, parameter :: num_stages = 3, num_vars = 5
- character (len = 3), dimension(num_stages) :: stage = (/"dBF","dAP","dAM"/)
+ integer, parameter :: num_stages = 6
+ character (len = 8), dimension(num_stages) :: stage = (/"dBF ","dAP ","dAM ","BD_dparm","BD_DMEA ","BD_phys "/)
character (len = 55),dimension(num_stages) :: stage_txt = (/&
" dynamics state before physics (d_p_coupling) ",&
" dynamics state with T,u,V increment but not q ",&
- " dynamics state with full physics increment (incl.q)" &
+ " dynamics state with full physics increment (incl.q)",&
+ "dE/dt params+efix in dycore (dparam)(dAP-dBF) ",&
+ "dE/dt dry mass adjustment in dycore (dAM-dAP)",&
+ "dE/dt physics total in dycore (phys) (dAM-dBF)" &
/)
- character (len = 2) , dimension(num_vars) :: vars = (/"WV" ,"WL" ,"WI" ,"SE" ,"KE"/)
- character (len = 45) , dimension(num_vars) :: vars_descriptor = (/&
- "Total column water vapor ",&
- "Total column cloud water ",&
- "Total column cloud ice ",&
- "Total column static energy ",&
- "Total column kinetic energy "/)
- character (len = 14), dimension(num_vars) :: &
- vars_unit = (/&
- "kg/m2 ","kg/m2 ","kg/m2 ","J/m2 ",&
- "J/m2 "/)
-
integer :: istage, ivars, m
character (len=108) :: str1, str2, str3
character (len=vc_str_lgth) :: vc_str
+ !-------------------------------------------------------
vc_dycore = vc_height
if (masterproc) then
@@ -536,40 +530,54 @@ subroutine dyn_init(dyn_in, dyn_out)
! Set the interval over which the dycore should integrate during each call to dyn_run.
call MPAS_set_timeInterval(integrationLength, S=nint(dtime), S_n=0, S_d=1)
- do istage = 1, num_stages
- do ivars=1, num_vars
- write(str1,*) TRIM(ADJUSTL(vars(ivars))),"_",TRIM(ADJUSTL(stage(istage)))
- write(str2,*) TRIM(ADJUSTL(vars_descriptor(ivars)))," ", &
- TRIM(ADJUSTL(stage_txt(istage)))
- write(str3,*) TRIM(ADJUSTL(vars_unit(ivars)))
- call addfld (TRIM(ADJUSTL(str1)), horiz_only, 'A', TRIM(ADJUSTL(str3)),TRIM(ADJUSTL(str2)), gridname='mpas_cell')
- end do
- end do
+ !
+ ! initialize history for MPAS energy budgets
+
+ if (thermo_budget_history) then
+ ! Define energy/mass snapshots using stage structure
+ do istage = 1, num_stages
+ call cam_budget_em_snapshot(TRIM(ADJUSTL(stage(istage))), 'dyn', longname=TRIM(ADJUSTL(stage_txt(istage))))
+ end do
+ !
+ ! initialize MPAS energy budgets
+ ! add budgets that are derived from stages
+ !
+ call cam_budget_em_register('dEdt_param_efix_in_dyn','dAP','dBF',pkgtype='dyn',optype='dif', &
+ longname="dE/dt parameterizations+efix in dycore (dparam)(dAP-dBF)")
+ call cam_budget_em_register('dEdt_dme_adjust_in_dyn','dAM','dAP',pkgtype='dyn',optype='dif', &
+ longname="dE/dt dry mass adjustment in dycore (dAM-dAP)")
+ call cam_budget_em_register('dEdt_phys_total_in_dyn','dAM','dBF',pkgtype='dyn',optype='dif', &
+ longname="dE/dt physics total in dycore (phys) (dAM-dBF)")
+ end if
+
!
! initialize CAM thermodynamic infrastructure
!
do m=1,thermodynamic_active_species_num
- thermodynamic_active_species_idx_dycore(m) = dyn_in % mpas_from_cam_cnst(thermodynamic_active_species_idx(m))
- if (masterproc) then
- write(iulog,*) subname//": m,thermodynamic_active_species_idx_dycore: ",m,thermodynamic_active_species_idx_dycore(m)
- end if
+ thermodynamic_active_species_idx_dycore(m) = dyn_out % cam_from_mpas_cnst(thermodynamic_active_species_idx(m))
+ if (masterproc) then
+ write(iulog,'(a,2I4)') subname//": m,thermodynamic_active_species_idx_dycore: ", &
+ m,thermodynamic_active_species_idx_dycore(m)
+ end if
end do
do m=1,thermodynamic_active_species_liq_num
- thermodynamic_active_species_liq_idx_dycore(m) = dyn_in % mpas_from_cam_cnst(thermodynamic_active_species_liq_idx(m))
- if (masterproc) then
- write(iulog,*) subname//": m,thermodynamic_active_species_idx_liq_dycore: ",m,thermodynamic_active_species_liq_idx_dycore(m)
- end if
+ thermodynamic_active_species_liq_idx_dycore(m) = dyn_out % cam_from_mpas_cnst(thermodynamic_active_species_liq_idx(m))
+ if (masterproc) then
+ write(iulog,'(a,2I4)') subname//": m,thermodynamic_active_species_idx_liq_dycore: ", &
+ m,thermodynamic_active_species_liq_idx_dycore(m)
+ end if
end do
do m=1,thermodynamic_active_species_ice_num
- thermodynamic_active_species_ice_idx_dycore(m) = dyn_in % mpas_from_cam_cnst(thermodynamic_active_species_ice_idx(m))
- if (masterproc) then
- write(iulog,*) subname//": m,thermodynamic_active_species_idx_ice_dycore: ",m,thermodynamic_active_species_ice_idx_dycore(m)
- end if
+ thermodynamic_active_species_ice_idx_dycore(m) = dyn_out % cam_from_mpas_cnst(thermodynamic_active_species_ice_idx(m))
+ if (masterproc) then
+ write(iulog,'(a,2I4)') subname//": m,thermodynamic_active_species_idx_ice_dycore: ", &
+ m,thermodynamic_active_species_ice_idx_dycore(m)
+ end if
end do
-
-end subroutine dyn_init
-
+
+ end subroutine dyn_init
+
!=========================================================================================
subroutine dyn_run(dyn_in, dyn_out)
@@ -588,6 +596,7 @@ subroutine dyn_run(dyn_in, dyn_out)
! Local variables
type(mpas_pool_type), pointer :: state_pool
character(len=*), parameter :: subname = 'dyn_comp:dyn_run'
+ real(r8) :: dtime
!----------------------------------------------------------------------------
@@ -609,11 +618,10 @@ subroutine dyn_run(dyn_in, dyn_out)
end subroutine dyn_run
-!=========================================================================================
subroutine dyn_final(dyn_in, dyn_out)
- use cam_mpas_subdriver, only : cam_mpas_finalize
+ use cam_mpas_subdriver, only : cam_mpas_finalize
! Deallocates the dynamics import and export states, and finalizes
! the MPAS dycore.
@@ -775,7 +783,7 @@ subroutine read_inidat(dyn_in)
real(r8), pointer :: uReconstructZ(:,:)
integer :: mpas_idx, cam_idx, ierr
- character(len=16) :: trac_name
+ character(len=32) :: trac_name
character(len=*), parameter :: subname = 'dyn_comp:read_inidat'
!--------------------------------------------------------------------------------------
diff --git a/src/dynamics/mpas/dyn_grid.F90 b/src/dynamics/mpas/dyn_grid.F90
index c8efc66123..104524a3c9 100644
--- a/src/dynamics/mpas/dyn_grid.F90
+++ b/src/dynamics/mpas/dyn_grid.F90
@@ -530,6 +530,7 @@ subroutine define_cam_grids()
use cam_grid_support, only: horiz_coord_t, horiz_coord_create, iMap
use cam_grid_support, only: cam_grid_register, cam_grid_attribute_register
+ use shr_const_mod, only: PI => SHR_CONST_PI
! Local variables
integer :: i, j
@@ -545,6 +546,7 @@ subroutine define_cam_grids()
real(r8), dimension(:), pointer :: latCell ! cell center latitude (radians)
real(r8), dimension(:), pointer :: lonCell ! cell center longitude (radians)
real(r8), dimension(:), pointer :: areaCell ! cell areas in m^2
+ real(r8), dimension(:), pointer :: areaWeight! normalized cell areas weights
integer, dimension(:), pointer :: indexToEdgeID ! global indices of edge nodes
real(r8), dimension(:), pointer :: latEdge ! edge node latitude (radians)
@@ -555,6 +557,13 @@ subroutine define_cam_grids()
real(r8), dimension(:), pointer :: lonVertex ! vertex node longitude (radians)
integer :: ierr
character(len=*), parameter :: subname = 'dyn_grid::define_cam_grids'
+ integer :: hdim1_d ! Global Longitudes or global grid size (nCells_g)
+ integer :: hdim2_d ! Latitudes or 1 for unstructured grids
+ integer :: num_levels ! Number of levels
+ integer :: index_model_top_layer
+ integer :: index_surface_layer
+ logical :: unstructured
+ type (physics_column_t), allocatable :: dyn_cols(:)
!----------------------------------------------------------------------------
call mpas_pool_get_subpool(domain_ptr % blocklist % structs, 'mesh', meshPool)
@@ -578,6 +587,11 @@ subroutine define_cam_grids()
lon_coord => horiz_coord_create('lonCell', 'nCells', nCells_g, 'longitude', &
'degrees_east', 1, nCellsSolve, lonCell(1:nCellsSolve)*rad2deg, map=gidx)
+ allocate(areaWeight(nCellsSolve), stat=ierr)
+ if( ierr /= 0 ) call endrun(subname//':failed to allocate area_weight :'//int2str(__LINE__))
+ call get_dyn_grid_info(hdim1_d, hdim2_d, num_levels, index_model_top_layer, index_surface_layer, unstructured, dyn_cols)
+
+
! Map for cell centers grid
allocate(grid_map(3, nCellsSolve), stat=ierr)
if( ierr /= 0 ) call endrun(subname//':failed to allocate grid_map array at line:'//int2str(__LINE__))
@@ -586,11 +600,19 @@ subroutine define_cam_grids()
grid_map(1, i) = i
grid_map(2, i) = 1
grid_map(3, i) = gidx(i)
+ areaWeight(i) = dyn_cols(i)%weight/(4.0_r8*PI)
end do
! cell center grid for I/O using MPAS names
call cam_grid_register('mpas_cell', dyn_decomp, lat_coord, lon_coord, &
grid_map, block_indexed=.false., unstruct=.true.)
+ call cam_grid_attribute_register('mpas_cell', 'area_cell', 'mpas cell areas', &
+ 'nCells', areaCell, map=gidx)
+ call cam_grid_attribute_register('mpas_cell', 'area_weight_mpas', 'mpas area weight', &
+ 'nCells', areaWeight, map=gidx)
+
+ nullify(areaWeight) ! areaWeight belongs to grid now
+ nullify(areaCell) ! areaCell belongs to grid now
! create new coordinates and grid using CAM names
lat_coord => horiz_coord_create('lat', 'ncol', nCells_g, 'latitude', &
@@ -603,6 +625,8 @@ subroutine define_cam_grids()
! gidx can be deallocated. Values are copied into the coordinate and attribute objects.
deallocate(gidx)
+ deallocate(dyn_cols)
+
! grid_map memory cannot be deallocated. The cam_filemap_t object just points
! to it. Pointer can be disassociated.
nullify(grid_map) ! Map belongs to grid now
diff --git a/src/dynamics/se/advect_tend.F90 b/src/dynamics/se/advect_tend.F90
index 856e3408a2..44ea0ff6f7 100644
--- a/src/dynamics/se/advect_tend.F90
+++ b/src/dynamics/se/advect_tend.F90
@@ -25,7 +25,7 @@ subroutine compute_adv_tends_xyz(elem,fvm,nets,nete,qn0,n0)
use cam_history, only: outfld, hist_fld_active
use time_manager, only: get_step_size
use constituents, only: tottnam,pcnst
- use dimensions_mod, only: nc,np,nlev,ntrac
+ use dimensions_mod, only: nc,np,nlev,use_cslam
use element_mod, only: element_t
use fvm_control_volume_mod, only: fvm_struct
implicit none
@@ -38,7 +38,7 @@ subroutine compute_adv_tends_xyz(elem,fvm,nets,nete,qn0,n0)
logical :: init
real(r8), allocatable, dimension(:,:) :: ftmp
- if (ntrac>0) then
+ if (use_cslam) then
nx=nc
else
nx=np
@@ -52,7 +52,7 @@ subroutine compute_adv_tends_xyz(elem,fvm,nets,nete,qn0,n0)
adv_tendxyz(:,:,:,:,:) = 0._r8
endif
- if (ntrac>0) then
+ if (use_cslam) then
do ie=nets,nete
do ic=1,pcnst
adv_tendxyz(:,:,:,ic,ie) = fvm(ie)%c(1:nc,1:nc,:,ic) - adv_tendxyz(:,:,:,ic,ie)
diff --git a/src/dynamics/se/dp_coupling.F90 b/src/dynamics/se/dp_coupling.F90
index 03132e8ccf..7dae784315 100644
--- a/src/dynamics/se/dp_coupling.F90
+++ b/src/dynamics/se/dp_coupling.F90
@@ -57,7 +57,7 @@ subroutine d_p_coupling(phys_state, phys_tend, pbuf2d, dyn_out)
use time_mod, only: timelevel_qdp
use control_mod, only: qsplit
use test_fvm_mapping, only: test_mapping_overwrite_dyn_state, test_mapping_output_phys_state
-
+ use prim_advance_mod, only: tot_energy_dyn
! arguments
type(dyn_export_t), intent(inout) :: dyn_out ! dynamics export
type(physics_buffer_desc), pointer :: pbuf2d(:,:)
@@ -128,6 +128,8 @@ subroutine d_p_coupling(phys_state, phys_tend, pbuf2d, dyn_out)
allocate(q_tmp(nphys_pts,pver,pcnst,nelemd))
allocate(omega_tmp(nphys_pts,pver,nelemd))
+ call tot_energy_dyn(elem,dyn_out%fvm, 1, nelemd,tl_f , tl_qdp_np0,'dBF')
+
if (use_gw_front .or. use_gw_front_igw) then
allocate(frontgf(nphys_pts,pver,nelemd), stat=ierr)
if (ierr /= 0) call endrun("dp_coupling: Allocate of frontgf failed.")
@@ -377,9 +379,7 @@ subroutine p_d_coupling(phys_state, phys_tend, dyn_in, tl_f, tl_qdp)
end do
end do
end do
- call thermodynamic_consistency( &
- phys_state(lchnk), phys_tend(lchnk), ncols, pver, lchnk)
- end do
+ end do
call t_startf('pd_copy')
!$omp parallel do num_threads(max_num_threads) private (col_ind, lchnk, icol, ie, blk_ind, ilyr, m)
@@ -539,8 +539,10 @@ subroutine derived_phys_dry(phys_state, phys_tend, pbuf2d)
use constituents, only: qmin
use physconst, only: gravit, zvir
- use cam_thermo, only: cam_thermo_update
- use air_composition, only: cpairv, rairv, cappav
+ use cam_thermo, only: cam_thermo_dry_air_update, cam_thermo_water_update
+ use air_composition, only: thermodynamic_active_species_num
+ use air_composition, only: thermodynamic_active_species_idx
+ use air_composition, only: cpairv, rairv, cappav, dry_air_species_num
use shr_const_mod, only: shr_const_rwv
use phys_control, only: waccmx_is
use geopotential, only: geopotential_t
@@ -548,7 +550,7 @@ subroutine derived_phys_dry(phys_state, phys_tend, pbuf2d)
use hycoef, only: hyai, ps0
use shr_vmath_mod, only: shr_vmath_log
use qneg_module, only: qneg3
-
+ use dyn_tests_utils, only: vc_dry_pressure
! arguments
type(physics_state), intent(inout), dimension(begchunk:endchunk) :: phys_state
type(physics_tend ), intent(inout), dimension(begchunk:endchunk) :: phys_tend
@@ -560,7 +562,7 @@ subroutine derived_phys_dry(phys_state, phys_tend, pbuf2d)
real(r8) :: zvirv(pcols,pver) ! Local zvir array pointer
real(r8) :: factor_array(pcols,nlev)
- integer :: m, i, k, ncol
+ integer :: m, i, k, ncol, m_cnst
type(physics_buffer_desc), pointer :: pbuf_chnk(:)
!----------------------------------------------------------------------------
@@ -602,13 +604,15 @@ subroutine derived_phys_dry(phys_state, phys_tend, pbuf2d)
end do
! wet pressure variables (should be removed from physics!)
-
- do k=1,nlev
- do i=1,ncol
- ! to be consistent with total energy formula in physic's check_energy module only
- ! include water vapor in in moist dp
- factor_array(i,k) = 1+phys_state(lchnk)%q(i,k,1)
- end do
+ factor_array(:,:) = 1.0_r8
+ do m_cnst=1,thermodynamic_active_species_num
+ m = thermodynamic_active_species_idx(m_cnst)
+ do k=1,nlev
+ do i=1,ncol
+ ! at this point all q's are dry
+ factor_array(i,k) = factor_array(i,k)+phys_state(lchnk)%q(i,k,m)
+ end do
+ end do
end do
do k=1,nlev
@@ -640,49 +644,51 @@ subroutine derived_phys_dry(phys_state, phys_tend, pbuf2d)
end do
end do
- ! all tracers (including moisture) are in dry mixing ratio units
- ! physics expect water variables moist
- factor_array(1:ncol,1:nlev) = 1/factor_array(1:ncol,1:nlev)
-
- do m = 1,pcnst
- if (cnst_type(m) == 'wet') then
- do k = 1, nlev
- do i = 1, ncol
- phys_state(lchnk)%q(i,k,m) = factor_array(i,k)*phys_state(lchnk)%q(i,k,m)
- end do
- end do
- end if
- end do
-
- if ( waccmx_is('ionosphere') .or. waccmx_is('neutral') ) then
- !------------------------------------------------------------
- ! Apply limiters to mixing ratios of major species
- !------------------------------------------------------------
+ !------------------------------------------------------------
+ ! Apply limiters to mixing ratios of major species (waccmx)
+ !------------------------------------------------------------
+ if (dry_air_species_num>0) then
call physics_cnst_limit( phys_state(lchnk) )
!-----------------------------------------------------------------------------
- ! Call cam_thermo_update to compute cpairv, rairv, mbarv, and cappav as
+ ! Call cam_thermo_dry_air_update to compute cpairv, rairv, mbarv, and cappav as
! constituent dependent variables.
! Compute molecular viscosity(kmvis) and conductivity(kmcnd).
! Fill local zvirv variable; calculated for WACCM-X.
!-----------------------------------------------------------------------------
- call cam_thermo_update(phys_state(lchnk)%q, phys_state(lchnk)%t, lchnk, ncol,&
- to_moist_factor=phys_state(lchnk)%pdeldry(:ncol,:)/phys_state(lchnk)%pdel(:ncol,:) )
+ call cam_thermo_dry_air_update(phys_state(lchnk)%q, phys_state(lchnk)%t, lchnk, ncol)
zvirv(:,:) = shr_const_rwv / rairv(:,:,lchnk) -1._r8
else
zvirv(:,:) = zvir
- endif
-
+ end if
+ !
+ ! update cp_dycore in module air_composition.
+ ! (note: at this point q is dry)
+ !
+ call cam_thermo_water_update(phys_state(lchnk)%q(1:ncol,:,:), lchnk, ncol, vc_dry_pressure)
do k = 1, nlev
do i = 1, ncol
phys_state(lchnk)%exner(i,k) = (phys_state(lchnk)%pint(i,pver+1) &
/ phys_state(lchnk)%pmid(i,k))**cappav(i,k,lchnk)
end do
end do
+ !
+ ! CAM physics: water tracers are moist; the rest dry
+ !
+ factor_array(1:ncol,1:nlev) = 1._r8/factor_array(1:ncol,1:nlev)
+ do m = 1,pcnst
+ if (cnst_type(m) == 'wet') then
+ do k = 1, nlev
+ do i = 1, ncol
+ phys_state(lchnk)%q(i,k,m) = factor_array(i,k)*phys_state(lchnk)%q(i,k,m)
+ end do
+ end do
+ end if
+ end do
! Compute initial geopotential heights - based on full pressure
call geopotential_t (phys_state(lchnk)%lnpint, phys_state(lchnk)%lnpmid , phys_state(lchnk)%pint , &
phys_state(lchnk)%pmid , phys_state(lchnk)%pdel , phys_state(lchnk)%rpdel , &
- phys_state(lchnk)%t , phys_state(lchnk)%q(:,:,1), rairv(:,:,lchnk), gravit, zvirv , &
+ phys_state(lchnk)%t , phys_state(lchnk)%q(:,:,:), rairv(:,:,lchnk), gravit, zvirv , &
phys_state(lchnk)%zi , phys_state(lchnk)%zm , ncol )
! Compute initial dry static energy, include surface geopotential
@@ -705,40 +711,4 @@ subroutine derived_phys_dry(phys_state, phys_tend, pbuf2d)
end do ! lchnk
end subroutine derived_phys_dry
-
-!=========================================================================================
-
-subroutine thermodynamic_consistency(phys_state, phys_tend, ncols, pver, lchnk)
- !
- ! Adjust the physics temperature tendency for thermal energy consistency with the
- ! dynamics.
- ! Note: mixing ratios are assumed to be dry.
- !
- use dimensions_mod, only: lcp_moist
- use air_composition, only: get_cp
- use control_mod, only: phys_dyn_cp
- use air_composition, only: cpairv
-
- type(physics_state), intent(in) :: phys_state
- type(physics_tend ), intent(inout) :: phys_tend
- integer, intent(in) :: ncols, pver, lchnk
-
- real(r8):: inv_cp(ncols,pver)
- !----------------------------------------------------------------------------
-
- if (lcp_moist.and.phys_dyn_cp==1) then
- !
- ! scale temperature tendency so that thermal energy increment from physics
- ! matches SE (not taking into account dme adjust)
- !
- ! note that if lcp_moist=.false. then there is thermal energy increment
- ! consistency (not taking into account dme adjust)
- !
- call get_cp(phys_state%q(1:ncols,1:pver,:), .true., inv_cp)
- phys_tend%dtdt(1:ncols,1:pver) = phys_tend%dtdt(1:ncols,1:pver) * cpairv(1:ncols,1:pver,lchnk) * inv_cp
- end if
-end subroutine thermodynamic_consistency
-
-!=========================================================================================
-
end module dp_coupling
diff --git a/src/dynamics/se/dycore/control_mod.F90 b/src/dynamics/se/dycore/control_mod.F90
index 0ecc2079d5..4c1127c45b 100644
--- a/src/dynamics/se/dycore/control_mod.F90
+++ b/src/dynamics/se/dycore/control_mod.F90
@@ -23,9 +23,6 @@ module control_mod
! every rsplit tracer timesteps
logical, public :: variable_nsplit=.false.
- integer, public :: phys_dyn_cp = 1 !=0; no thermal energy scaling of T increment
- !=1; scale increment for cp consistency between dynamics and physics
-
logical, public :: refined_mesh
integer, public :: vert_remap_q_alg = 10
diff --git a/src/dynamics/se/dycore/dimensions_mod.F90 b/src/dynamics/se/dycore/dimensions_mod.F90
index 8a41ea30c3..eb1564600c 100644
--- a/src/dynamics/se/dycore/dimensions_mod.F90
+++ b/src/dynamics/se/dycore/dimensions_mod.F90
@@ -15,7 +15,6 @@ module dimensions_mod
#else
integer, parameter :: ntrac_d = 0 ! No fvm tracers if CSLAM is off
#endif
-
!
! The variables below hold indices of water vapor and condensate loading tracers as well as
! associated heat capacities (initialized in dyn_init):
@@ -31,20 +30,14 @@ module dimensions_mod
!
character(len=16), allocatable, public :: cnst_name_gll(:) ! constituent names for SE tracers
character(len=128), allocatable, public :: cnst_longname_gll(:) ! long name of SE tracers
- !
- !moist cp in energy conversion term
- !
- ! .false.: force dycore to use cpd (cp dry) instead of moist cp
- ! .true. : use moist cp in dycore
- !
- logical , public :: lcp_moist = .true.
-
+
integer, parameter, public :: np = NP
integer, parameter, public :: nc = 3 !cslam resolution
integer , public :: fv_nphys !physics-grid resolution - the "MAX" is so that the code compiles with NC=0
- integer :: ntrac = 0 !ntrac is set in dyn_comp
- integer :: qsize = 0 !qsize is set in dyn_comp
+ integer :: ntrac = 0 !ntrac is set in dyn_comp
+ logical, public :: use_cslam = .false. !logical for CSLAM
+ integer :: qsize = 0 !qsize is set in dyn_comp
!
! fvm dimensions:
logical, public :: lprint!for debugging
diff --git a/src/dynamics/se/dycore/fvm_mod.F90 b/src/dynamics/se/dycore/fvm_mod.F90
index 93aa41a008..c55358a063 100644
--- a/src/dynamics/se/dycore/fvm_mod.F90
+++ b/src/dynamics/se/dycore/fvm_mod.F90
@@ -290,14 +290,14 @@ subroutine fvm_init1(par,elem)
use control_mod, only: rsplit
use dimensions_mod, only: qsize, qsize_d
use dimensions_mod, only: fvm_supercycling, fvm_supercycling_jet
- use dimensions_mod, only: nc,nhe, nhc, nlev,ntrac, ntrac_d,ns, nhr
+ use dimensions_mod, only: nc,nhe, nhc, nlev,ntrac, ntrac_d,ns, nhr, use_cslam
use dimensions_mod, only: large_Courant_incr
use dimensions_mod, only: kmin_jet,kmax_jet
type (parallel_t) :: par
type (element_t),intent(inout) :: elem(:)
!
- if (ntrac>0) then
+ if (use_cslam) then
if (par%masterproc) then
write(iulog,*) " "
write(iulog,*) "|-----------------------------------------|"
@@ -305,7 +305,7 @@ subroutine fvm_init1(par,elem)
write(iulog,*) "|-----------------------------------------|"
write(iulog,*) " "
end if
- if (ntrac>0) then
+ if (use_cslam) then
if (par%masterproc) then
write(iulog,*) "Running consistent SE-CSLAM, Lauritzen et al. (2017, MWR)."
write(iulog,*) "CSLAM = Conservative Semi-LAgrangian Multi-tracer scheme"
@@ -517,8 +517,8 @@ end subroutine fvm_init2
subroutine fvm_init3(elem,fvm,hybrid,nets,nete,irecons)
use control_mod , only: neast, nwest, seast, swest
use fvm_analytic_mod, only: compute_reconstruct_matrix
- use dimensions_mod , only: fv_nphys
- use dimensions_mod, only: nlev, nc, nhe, nlev, ntrac, ntrac_d,nhc
+ use dimensions_mod , only: fv_nphys, use_cslam
+ use dimensions_mod, only: nlev, nc, nhe, nlev, nhc
use coordinate_systems_mod, only: cartesian2D_t,cartesian3D_t
use coordinate_systems_mod, only: cubedsphere2cart, cart2cubedsphere
implicit none
@@ -536,7 +536,7 @@ subroutine fvm_init3(elem,fvm,hybrid,nets,nete,irecons)
type (cartesian2D_t) :: gnom
type(cartesian3D_t) :: tmpcart3d
- if (ntrac>0.and.nc.ne.fv_nphys) then
+ if (use_cslam.and.nc.ne.fv_nphys) then
!
! fill the fvm halo for mapping in d_p_coupling if
! physics grid resolution is different than fvm resolution
@@ -728,7 +728,6 @@ subroutine fvm_pg_init(elem, fvm, hybrid, nets, nete,irecons)
use control_mod, only : neast, nwest, seast, swest
use coordinate_systems_mod, only : cubedsphere2cart, cart2cubedsphere
use dimensions_mod, only: fv_nphys, nhe_phys,nhc_phys
- use dimensions_mod, only: ntrac_d
use cube_mod ,only: dmap
use control_mod ,only: cubed_sphere_map
use fvm_analytic_mod, only: compute_reconstruct_matrix
diff --git a/src/dynamics/se/dycore/global_norms_mod.F90 b/src/dynamics/se/dycore/global_norms_mod.F90
index de295da01a..843fd88bc7 100644
--- a/src/dynamics/se/dycore/global_norms_mod.F90
+++ b/src/dynamics/se/dycore/global_norms_mod.F90
@@ -24,26 +24,27 @@ module global_norms_mod
private :: global_maximum
type (EdgeBuffer_t), private :: edgebuf
+ interface global_integral
+ module procedure global_integral_elem
+ module procedure global_integral_fvm
+ end interface global_integral
+
contains
- subroutine global_integrals(elem, h,hybrid,npts,num_flds,nets,nete,I_sphere)
+ subroutine global_integrals(elem,fld,hybrid,npts,num_flds,nets,nete,I_sphere)
use hybrid_mod, only: hybrid_t
use element_mod, only: element_t
- use dimensions_mod, only: np, nelemd
+ use dimensions_mod, only: np
use physconst, only: pi
use parallel_mod, only: global_shared_buf, global_shared_sum
type(element_t) , intent(in) :: elem(:)
integer , intent(in) :: npts,nets,nete,num_flds
- real (kind=r8), intent(in) :: h(npts,npts,num_flds,nets:nete)
+ real (kind=r8), intent(in) :: fld(npts,npts,num_flds,nets:nete)
type (hybrid_t) , intent(in) :: hybrid
real (kind=r8) :: I_sphere(num_flds)
-
- real (kind=r8) :: I_priv
- real (kind=r8) :: I_shared
- common /gblintcom/I_shared
!
! Local variables
!
@@ -57,13 +58,12 @@ subroutine global_integrals(elem, h,hybrid,npts,num_flds,nets,nete,I_sphere)
!
J_tmp = 0.0_r8
-!JMD print *,'global_integral: before loop'
do ie=nets,nete
do q=1,num_flds
do j=1,np
do i=1,np
da = elem(ie)%mp(i,j)*elem(ie)%metdet(i,j)
- J_tmp(ie,q) = J_tmp(ie,q) + da*h(i,j,q,ie)
+ J_tmp(ie,q) = J_tmp(ie,q) + da*fld(i,j,q,ie)
end do
end do
end do
@@ -71,28 +71,21 @@ subroutine global_integrals(elem, h,hybrid,npts,num_flds,nets,nete,I_sphere)
do ie=nets,nete
global_shared_buf(ie,1:num_flds) = J_tmp(ie,:)
enddo
- !JMD print *,'global_integral: before wrap_repro_sum'
call wrap_repro_sum(nvars=num_flds, comm=hybrid%par%comm)
- !JMD print *,'global_integral: after wrap_repro_sum'
I_sphere(:) =global_shared_sum(1:num_flds) /(4.0_r8*PI)
end subroutine global_integrals
- subroutine global_integrals_general(h,hybrid,npts,da,num_flds,nets,nete,I_sphere)
+ subroutine global_integrals_general(fld,hybrid,npts,da,num_flds,nets,nete,I_sphere)
use hybrid_mod, only: hybrid_t
- use dimensions_mod, only: nc, nelemd
use physconst, only: pi
use parallel_mod, only: global_shared_buf, global_shared_sum
integer, intent(in) :: npts,nets,nete,num_flds
- real (kind=r8), intent(in) :: h(npts,npts,num_flds,nets:nete)
+ real (kind=r8), intent(in) :: fld(npts,npts,num_flds,nets:nete)
type (hybrid_t), intent(in) :: hybrid
real (kind=r8), intent(in) :: da(npts,npts,nets:nete)
real (kind=r8) :: I_sphere(num_flds)
-
- real (kind=r8) :: I_priv
- real (kind=r8) :: I_shared
- common /gblintcom/I_shared
!
! Local variables
!
@@ -105,12 +98,11 @@ subroutine global_integrals_general(h,hybrid,npts,da,num_flds,nets,nete,I_sphere
!
J_tmp = 0.0_r8
-!JMD print *,'global_integral: before loop'
do ie=nets,nete
do q=1,num_flds
do j=1,npts
do i=1,npts
- J_tmp(ie,q) = J_tmp(ie,q) + da(i,j,ie)*h(i,j,q,ie)
+ J_tmp(ie,q) = J_tmp(ie,q) + da(i,j,ie)*fld(i,j,q,ie)
end do
end do
end do
@@ -118,9 +110,7 @@ subroutine global_integrals_general(h,hybrid,npts,da,num_flds,nets,nete,I_sphere
do ie=nets,nete
global_shared_buf(ie,1:num_flds) = J_tmp(ie,:)
enddo
- !JMD print *,'global_integral: before wrap_repro_sum'
call wrap_repro_sum(nvars=num_flds, comm=hybrid%par%comm)
- !JMD print *,'global_integral: after wrap_repro_sum'
I_sphere(:) =global_shared_sum(1:num_flds) /(4.0_r8*PI)
end subroutine global_integrals_general
@@ -133,24 +123,20 @@ end subroutine global_integrals_general
!
! ================================
! --------------------------
- function global_integral(elem, h,hybrid,npts,nets,nete) result(I_sphere)
+ function global_integral_elem(elem,fld,hybrid,npts,nets,nete) result(I_sphere)
use hybrid_mod, only: hybrid_t
use element_mod, only: element_t
- use dimensions_mod, only: np, nelemd
+ use dimensions_mod, only: np
use physconst, only: pi
use parallel_mod, only: global_shared_buf, global_shared_sum
type(element_t) , intent(in) :: elem(:)
integer , intent(in) :: npts,nets,nete
- real (kind=r8), intent(in) :: h(npts,npts,nets:nete)
+ real (kind=r8), intent(in) :: fld(npts,npts,nets:nete)
type (hybrid_t) , intent(in) :: hybrid
real (kind=r8) :: I_sphere
- real (kind=r8) :: I_priv
- real (kind=r8) :: I_shared
- common /gblintcom/I_shared
-
! Local variables
integer :: ie,j,i
@@ -159,31 +145,69 @@ function global_integral(elem, h,hybrid,npts,nets,nete) result(I_sphere)
real (kind=r8) :: da
real (kind=r8) :: J_tmp(nets:nete)
!
-! This algorythm is independent of thread count and task count.
+! This algorithm is independent of thread count and task count.
! This is a requirement of consistancy checking in cam.
!
J_tmp = 0.0_r8
-!JMD print *,'global_integral: before loop'
do ie=nets,nete
do j=1,np
do i=1,np
da = elem(ie)%mp(i,j)*elem(ie)%metdet(i,j)
- J_tmp(ie) = J_tmp(ie) + da*h(i,j,ie)
+ J_tmp(ie) = J_tmp(ie) + da*fld(i,j,ie)
end do
end do
end do
do ie=nets,nete
global_shared_buf(ie,1) = J_tmp(ie)
enddo
-!JMD print *,'global_integral: before wrap_repro_sum'
call wrap_repro_sum(nvars=1, comm=hybrid%par%comm)
-!JMD print *,'global_integral: after wrap_repro_sum'
I_tmp = global_shared_sum(1)
-!JMD print *,'global_integral: after global_shared_sum'
I_sphere = I_tmp(1)/(4.0_r8*PI)
- end function global_integral
+ end function global_integral_elem
+
+ function global_integral_fvm(fvm,fld,hybrid,npts,nets,nete) result(I_sphere)
+ use hybrid_mod, only: hybrid_t
+ use fvm_control_volume_mod, only: fvm_struct
+ use physconst, only: pi
+ use parallel_mod, only: global_shared_buf, global_shared_sum
+
+ type (fvm_struct) , intent(in) :: fvm(:)
+ integer , intent(in) :: npts,nets,nete
+ real (kind=r8), intent(in) :: fld(npts,npts,nets:nete)
+ type (hybrid_t) , intent(in) :: hybrid
+
+ real (kind=r8) :: I_sphere
+
+ ! Local variables
+
+ integer :: ie,j,i
+ real(kind=r8) :: I_tmp(1)
+
+ real (kind=r8) :: da
+ real (kind=r8) :: J_tmp(nets:nete)
+!
+! This algorithm is independent of thread count and task count.
+! This is a requirement of consistancy checking in cam.
+!
+ J_tmp = 0.0_r8
+ do ie=nets,nete
+ do j=1,npts
+ do i=1,npts
+ da = fvm(ie)%area_sphere(i,j)
+ J_tmp(ie) = J_tmp(ie) + da*fld(i,j,ie)
+ end do
+ end do
+ end do
+ do ie=nets,nete
+ global_shared_buf(ie,1) = J_tmp(ie)
+ enddo
+ call wrap_repro_sum(nvars=1, comm=hybrid%par%comm)
+ I_tmp = global_shared_sum(1)
+ I_sphere = I_tmp(1)/(4.0_r8*PI)
+
+ end function global_integral_fvm
!------------------------------------------------------------------------------------
@@ -205,23 +229,22 @@ subroutine print_cfl(elem,hybrid,nets,nete,dtnu,ptop,pmid,&
! worse viscosity CFL (given by dtnu) is not violated by reducing
! viscosity coefficient in regions where CFL is violated
!
- use hybrid_mod, only: hybrid_t, PrintHybrid
+ use hybrid_mod, only: hybrid_t
use element_mod, only: element_t
- use dimensions_mod, only: np,ne,nelem,nelemd,nc,nhe,qsize,ntrac,nlev,large_Courant_incr
+ use dimensions_mod, only: np,ne,nelem,nc,nhe,use_cslam,nlev,large_Courant_incr
use dimensions_mod, only: nu_scale_top,nu_div_lev,nu_lev,nu_t_lev
use quadrature_mod, only: gausslobatto, quadrature_t
use reduction_mod, only: ParallelMin,ParallelMax
use physconst, only: ra, rearth, pi
- use control_mod, only: nu, nu_div, nu_q, nu_p, nu_t, nu_top, fine_ne, rk_stage_user, max_hypervis_courant
+ use control_mod, only: nu, nu_div, nu_q, nu_p, nu_t, nu_top, fine_ne, max_hypervis_courant
use control_mod, only: tstep_type, hypervis_power, hypervis_scaling
use control_mod, only: sponge_del4_nu_div_fac, sponge_del4_nu_fac, sponge_del4_lev
use cam_abortutils, only: endrun
use parallel_mod, only: global_shared_buf, global_shared_sum
use edge_mod, only: initedgebuffer, FreeEdgeBuffer, edgeVpack, edgeVunpack
use bndry_mod, only: bndry_exchange
- use time_mod, only: tstep
use mesh_mod, only: MeshUseMeshFile
use dimensions_mod, only: ksponge_end, kmvis_ref, kmcnd_ref,rho_ref
use physconst, only: cpair
@@ -241,14 +264,14 @@ subroutine print_cfl(elem,hybrid,nets,nete,dtnu,ptop,pmid,&
real (kind=r8) :: max_min_dx,min_min_dx,min_max_dx,max_unif_dx ! used for normalizing scalar HV
real (kind=r8) :: max_normDinv, min_normDinv ! used for CFL
real (kind=r8) :: min_area, max_area,max_ratio !min/max element area
- real (kind=r8) :: avg_area, avg_min_dx
+ real (kind=r8) :: avg_area, avg_min_dx,tot_area,tot_area_rad
real (kind=r8) :: min_hypervis, max_hypervis, avg_hypervis, stable_hv
real (kind=r8) :: normDinv_hypervis
real (kind=r8) :: x, y, noreast, nw, se, sw
real (kind=r8), dimension(np,np,nets:nete) :: zeta
real (kind=r8) :: lambda_max, lambda_vis, min_gw, lambda,umax, ugw
- real (kind=r8) :: scale1,scale2,scale3, max_laplace,z(nlev)
- integer :: ie,corner, i, j, rowind, colind, k
+ real (kind=r8) :: scale1, max_laplace,z(nlev)
+ integer :: ie, i, j, rowind, colind, k
type (quadrature_t) :: gp
character(LEN=256) :: rk_str
@@ -257,7 +280,7 @@ subroutine print_cfl(elem,hybrid,nets,nete,dtnu,ptop,pmid,&
real (kind=r8) :: dt_max_hypervis, dt_max_hypervis_tracer, dt_max_laplacian_top
real(kind=r8) :: I_sphere, nu_max, nu_div_max
- real(kind=r8) :: h(np,np,nets:nete)
+ real(kind=r8) :: fld(np,np,nets:nete)
logical :: top_000_032km, top_032_042km, top_042_090km, top_090_140km, top_140_600km ! model top location ranges
logical :: nu_set,div_set,lev_set
@@ -312,9 +335,9 @@ subroutine print_cfl(elem,hybrid,nets,nete,dtnu,ptop,pmid,&
!
!******************************************************************************************
!
- h(:,:,nets:nete)=1.0_r8
+ fld(:,:,nets:nete)=1.0_r8
! Calculate surface area by integrating 1.0_r8 over sphere and dividing by 4*PI (Should be 1)
- I_sphere = global_integral(elem, h(:,:,nets:nete),hybrid,np,nets,nete)
+ I_sphere = global_integral(elem, fld(:,:,nets:nete),hybrid,np,nets,nete)
min_normDinv = 1E99_r8
max_normDinv = 0
@@ -341,6 +364,7 @@ subroutine print_cfl(elem,hybrid,nets,nete,dtnu,ptop,pmid,&
enddo
call wrap_repro_sum(nvars=2, comm=hybrid%par%comm)
avg_area = global_shared_sum(1)/dble(nelem)
+ tot_area_rad = global_shared_sum(1)
avg_min_dx = global_shared_sum(2)/dble(nelem)
min_area = ParallelMin(min_area,hybrid)
@@ -351,16 +375,19 @@ subroutine print_cfl(elem,hybrid,nets,nete,dtnu,ptop,pmid,&
max_min_dx = ParallelMax(max_min_dx,hybrid)
min_max_dx = ParallelMin(min_max_dx,hybrid)
max_ratio = ParallelMax(max_ratio,hybrid)
- ! Physical units for area
- min_area = min_area*rearth*rearth/1000000._r8
- max_area = max_area*rearth*rearth/1000000._r8
- avg_area = avg_area*rearth*rearth/1000000._r8
+ ! Physical units for area (unit sphere to Earth sphere)
+ min_area = min_area*rearth*rearth/1000000._r8 !m2 (rearth is in units of km)
+ max_area = max_area*rearth*rearth/1000000._r8 !m2 (rearth is in units of km)
+ avg_area = avg_area*rearth*rearth/1000000._r8 !m2 (rearth is in units of km)
+ tot_area = tot_area_rad*rearth*rearth/1000000._r8!m2 (rearth is in units of km)
if (hybrid%masterthread) then
write(iulog,* )""
write(iulog,* )"Running Global Integral Diagnostic..."
write(iulog,*)"Area of unit sphere is",I_sphere
write(iulog,*)"Should be 1.0 to round off..."
write(iulog,'(a,f9.3)') 'Element area: max/min',(max_area/min_area)
+ write(iulog,'(a,E23.15)') 'Total Grid area: ',(tot_area)
+ write(iulog,'(a,E23.15)') 'Total Grid area rad^2: ',(tot_area_rad)
if (.not.MeshUseMeshFile) then
write(iulog,'(a,f6.3,f8.2)') "Average equatorial node spacing (deg, km) = ", &
dble(90)/dble(ne*(np-1)), PI*rearth/(2000.0_r8*dble(ne*(np-1)))
@@ -716,7 +743,7 @@ subroutine print_cfl(elem,hybrid,nets,nete,dtnu,ptop,pmid,&
dt_max_adv = S_rk/(umax*max_normDinv*lambda_max*ra)
dt_max_gw = S_rk/(ugw*max_normDinv*lambda_max*ra)
dt_max_tracer_se = S_rk_tracer*min_gw/(umax*max_normDinv*ra)
- if (ntrac>0) then
+ if (use_cslam) then
if (large_Courant_incr) then
dt_max_tracer_fvm = dble(nhe)*(4.0_r8*pi*Rearth/dble(4.0_r8*ne*nc))/umax
else
@@ -753,7 +780,7 @@ subroutine print_cfl(elem,hybrid,nets,nete,dtnu,ptop,pmid,&
dt_tracer_visco_actual,'s'
if (dt_tracer_visco_actual>dt_max_hypervis_tracer) write(iulog,*) 'WARNING: dt_tracer_hypervis theoretically unstable'
- if (ntrac>0) then
+ if (use_cslam) then
write(iulog,'(a,f10.2,a,f10.2,a)') '* dt_tracer_fvm (time-stepping tracers ; q ) < ',dt_max_tracer_fvm,&
's ',dt_tracer_fvm_actual
if (dt_tracer_fvm_actual>dt_max_tracer_fvm) write(iulog,*) 'WARNING: dt_tracer_fvm theortically unstable'
@@ -792,13 +819,13 @@ end subroutine print_cfl
!
! ================================
- function global_maximum(h,hybrid,npts,nets,nete) result(Max_sphere)
+ function global_maximum(fld,hybrid,npts,nets,nete) result(Max_sphere)
use hybrid_mod, only : hybrid_t
use reduction_mod, only : red_max, pmax_mt
integer , intent(in) :: npts,nets,nete
- real (kind=r8), intent(in) :: h(npts,npts,nets:nete)
+ real (kind=r8), intent(in) :: fld(npts,npts,nets:nete)
type (hybrid_t) , intent(in) :: hybrid
real (kind=r8) :: Max_sphere
@@ -807,7 +834,7 @@ function global_maximum(h,hybrid,npts,nets,nete) result(Max_sphere)
real (kind=r8) :: redp(1)
- Max_sphere = MAXVAL(h(:,:,nets:nete))
+ Max_sphere = MAXVAL(fld(:,:,nets:nete))
redp(1) = Max_sphere
call pmax_mt(red_max,redp,1,hybrid)
@@ -822,39 +849,39 @@ end function global_maximum
! for a scalar quantity
! ===========================================================
- function l1_snorm(elem, h,ht,hybrid,npts,nets,nete) result(l1)
+ function l1_snorm(elem,fld,fld_exact,hybrid,npts,nets,nete) result(l1)
use element_mod, only : element_t
use hybrid_mod, only : hybrid_t
type(element_t) , intent(in) :: elem(:)
integer , intent(in) :: npts,nets,nete
- real (kind=r8), intent(in) :: h(npts,npts,nets:nete) ! computed soln
- real (kind=r8), intent(in) :: ht(npts,npts,nets:nete) ! true soln
+ real (kind=r8), intent(in) :: fld(npts,npts,nets:nete) ! computed soln
+ real (kind=r8), intent(in) :: fld_exact(npts,npts,nets:nete) ! true soln
type (hybrid_t) , intent(in) :: hybrid
real (kind=r8) :: l1
! Local variables
- real (kind=r8) :: dhabs(npts,npts,nets:nete)
- real (kind=r8) :: htabs(npts,npts,nets:nete)
- real (kind=r8) :: dhabs_int
- real (kind=r8) :: htabs_int
+ real (kind=r8) :: dfld_abs(npts,npts,nets:nete)
+ real (kind=r8) :: fld_exact_abs(npts,npts,nets:nete)
+ real (kind=r8) :: dfld_abs_int
+ real (kind=r8) :: fld_exact_abs_int
integer i,j,ie
do ie=nets,nete
do j=1,npts
do i=1,npts
- dhabs(i,j,ie) = ABS(h(i,j,ie)-ht(i,j,ie))
- htabs(i,j,ie) = ABS(ht(i,j,ie))
+ dfld_abs(i,j,ie) = ABS(fld(i,j,ie)-fld_exact(i,j,ie))
+ fld_exact_abs(i,j,ie) = ABS(fld_exact(i,j,ie))
end do
end do
end do
- dhabs_int = global_integral(elem, dhabs(:,:,nets:nete),hybrid,npts,nets,nete)
- htabs_int = global_integral(elem, htabs(:,:,nets:nete),hybrid,npts,nets,nete)
+ dfld_abs_int = global_integral(elem, dfld_abs(:,:,nets:nete),hybrid,npts,nets,nete)
+ fld_exact_abs_int = global_integral(elem, fld_exact_abs(:,:,nets:nete),hybrid,npts,nets,nete)
- l1 = dhabs_int/htabs_int
+ l1 = dfld_abs_int/fld_exact_abs_int
end function l1_snorm
@@ -930,38 +957,38 @@ end function l1_vnorm
!
! ===========================================================
- function l2_snorm(elem, h,ht,hybrid,npts,nets,nete) result(l2)
+ function l2_snorm(elem,fld,fld_exact,hybrid,npts,nets,nete) result(l2)
use element_mod, only : element_t
use hybrid_mod, only : hybrid_t
type(element_t), intent(in) :: elem(:)
integer , intent(in) :: npts,nets,nete
- real (kind=r8), intent(in) :: h(npts,npts,nets:nete) ! computed soln
- real (kind=r8), intent(in) :: ht(npts,npts,nets:nete) ! true soln
+ real (kind=r8), intent(in) :: fld(npts,npts,nets:nete) ! computed soln
+ real (kind=r8), intent(in) :: fld_exact(npts,npts,nets:nete) ! true soln
type (hybrid_t) , intent(in) :: hybrid
real (kind=r8) :: l2
! Local variables
real (kind=r8) :: dh2(npts,npts,nets:nete)
- real (kind=r8) :: ht2(npts,npts,nets:nete)
+ real (kind=r8) :: fld_exact2(npts,npts,nets:nete)
real (kind=r8) :: dh2_int
- real (kind=r8) :: ht2_int
+ real (kind=r8) :: fld_exact2_int
integer i,j,ie
do ie=nets,nete
do j=1,npts
do i=1,npts
- dh2(i,j,ie)=(h(i,j,ie)-ht(i,j,ie))**2
- ht2(i,j,ie)=ht(i,j,ie)**2
+ dh2(i,j,ie)=(fld(i,j,ie)-fld_exact(i,j,ie))**2
+ fld_exact2(i,j,ie)=fld_exact(i,j,ie)**2
end do
end do
end do
dh2_int = global_integral(elem,dh2(:,:,nets:nete),hybrid,npts,nets,nete)
- ht2_int = global_integral(elem,ht2(:,:,nets:nete),hybrid,npts,nets,nete)
+ fld_exact2_int = global_integral(elem,fld_exact2(:,:,nets:nete),hybrid,npts,nets,nete)
- l2 = SQRT(dh2_int)/SQRT(ht2_int)
+ l2 = SQRT(dh2_int)/SQRT(fld_exact2_int)
end function l2_snorm
@@ -1036,35 +1063,35 @@ end function l2_vnorm
!
! ===========================================================
- function linf_snorm(h,ht,hybrid,npts,nets,nete) result(linf)
+ function linf_snorm(fld,fld_exact,hybrid,npts,nets,nete) result(linf)
use hybrid_mod, only : hybrid_t
integer , intent(in) :: npts,nets,nete
- real (kind=r8), intent(in) :: h(npts,npts,nets:nete) ! computed soln
- real (kind=r8), intent(in) :: ht(npts,npts,nets:nete) ! true soln
+ real (kind=r8), intent(in) :: fld(npts,npts,nets:nete) ! computed soln
+ real (kind=r8), intent(in) :: fld_exact(npts,npts,nets:nete) ! true soln
type (hybrid_t) , intent(in) :: hybrid
real (kind=r8) :: linf
! Local variables
- real (kind=r8) :: dhabs(npts,npts,nets:nete)
- real (kind=r8) :: htabs(npts,npts,nets:nete)
- real (kind=r8) :: dhabs_max
- real (kind=r8) :: htabs_max
+ real (kind=r8) :: dfld_abs(npts,npts,nets:nete)
+ real (kind=r8) :: fld_exact_abs(npts,npts,nets:nete)
+ real (kind=r8) :: dfld_abs_max
+ real (kind=r8) :: fld_exact_abs_max
integer i,j,ie
do ie=nets,nete
do j=1,npts
do i=1,npts
- dhabs(i,j,ie)=ABS(h(i,j,ie)-ht(i,j,ie))
- htabs(i,j,ie)=ABS(ht(i,j,ie))
+ dfld_abs(i,j,ie)=ABS(fld(i,j,ie)-fld_exact(i,j,ie))
+ fld_exact_abs(i,j,ie)=ABS(fld_exact(i,j,ie))
end do
end do
end do
- dhabs_max = global_maximum(dhabs(:,:,nets:nete),hybrid,npts,nets,nete)
- htabs_max = global_maximum(htabs(:,:,nets:nete),hybrid,npts,nets,nete)
+ dfld_abs_max = global_maximum(dfld_abs(:,:,nets:nete),hybrid,npts,nets,nete)
+ fld_exact_abs_max = global_maximum(fld_exact_abs(:,:,nets:nete),hybrid,npts,nets,nete)
- linf = dhabs_max/htabs_max
+ linf = dfld_abs_max/fld_exact_abs_max
end function linf_snorm
diff --git a/src/dynamics/se/dycore/hybrid_mod.F90 b/src/dynamics/se/dycore/hybrid_mod.F90
index 19f1043a92..5e7b4208ca 100644
--- a/src/dynamics/se/dycore/hybrid_mod.F90
+++ b/src/dynamics/se/dycore/hybrid_mod.F90
@@ -7,7 +7,7 @@ module hybrid_mod
use parallel_mod , only : parallel_t, copy_par
use thread_mod , only : omp_set_num_threads, omp_get_thread_num
use thread_mod , only : horz_num_threads, vert_num_threads, tracer_num_threads
-use dimensions_mod, only : nlev, qsize, ntrac
+use dimensions_mod, only : nlev, qsize, ntrac, use_cslam
implicit none
private
@@ -241,7 +241,7 @@ subroutine init_loop_ranges(nelemd)
work_pool_trac(ith+1,2) = end_index
end do
- if(ntrac>0 .and. ntrac0) then
+ if ((cubed_sphere_map /= 0) .AND. use_cslam) then
if (par%masterproc) then
write(iulog, *) subname, 'fvm transport and require equi-angle gnomonic cube sphere mapping.'
write(iulog, *) ' Set cubed_sphere_map = 0 or comment it out all together. '
diff --git a/src/dynamics/se/dycore/prim_advance_mod.F90 b/src/dynamics/se/dycore/prim_advance_mod.F90
index 7f3ee98d68..c9f1ac194b 100644
--- a/src/dynamics/se/dycore/prim_advance_mod.F90
+++ b/src/dynamics/se/dycore/prim_advance_mod.F90
@@ -10,7 +10,7 @@ module prim_advance_mod
private
save
- public :: prim_advance_exp, prim_advance_init, applyCAMforcing, calc_tot_energy_dynamics, compute_omega
+ public :: prim_advance_exp, prim_advance_init, applyCAMforcing, tot_energy_dyn, compute_omega
type (EdgeBuffer_t) :: edge3,edgeOmega,edgeSponge
real (kind=r8), allocatable :: ur_weights(:)
@@ -54,16 +54,15 @@ subroutine prim_advance_exp(elem, fvm, deriv, hvcoord, hybrid,dt, tl, nets, net
use hybvcoord_mod, only: hvcoord_t
use hybrid_mod, only: hybrid_t
use time_mod, only: TimeLevel_t, timelevel_qdp, tevolve
- use dimensions_mod, only: lcp_moist
use fvm_control_volume_mod, only: fvm_struct
use cam_thermo, only: get_kappa_dry
- use air_composition, only: thermodynamic_active_species_num, dry_air_species_num
+ use air_composition, only: thermodynamic_active_species_num
use air_composition, only: thermodynamic_active_species_idx_dycore, get_cp
- use physconst, only: cpair, rair
+ use physconst, only: cpair
implicit none
type (element_t), intent(inout), target :: elem(:)
- type(fvm_struct) , intent(in) :: fvm(:)
+ type(fvm_struct) , intent(inout) :: fvm(:)
type (derivative_t) , intent(in) :: deriv
type (hvcoord_t) :: hvcoord
type (hybrid_t) , intent(in) :: hybrid
@@ -74,7 +73,6 @@ subroutine prim_advance_exp(elem, fvm, deriv, hvcoord, hybrid,dt, tl, nets, net
! Local
real (kind=r8) :: dt_vis, eta_ave_w
- real (kind=r8) :: dp(np,np)
integer :: ie,nm1,n0,np1,k,qn0,m_cnst, nq
real (kind=r8) :: inv_cp_full(np,np,nlev,nets:nete)
real (kind=r8) :: qwater(np,np,nlev,thermodynamic_active_species_num,nets:nete)
@@ -123,22 +121,16 @@ subroutine prim_advance_exp(elem, fvm, deriv, hvcoord, hybrid,dt, tl, nets, net
!
! make sure Q is updated
!
- qwater(:,:,:,nq,ie) = elem(ie)%state%Qdp(:,:,:,m_cnst,qn0)/elem(ie)%state%dp3d(:,:,:,n0)
+ qwater(:,:,:,nq,ie) = elem(ie)%state%Qdp(:,:,:,m_cnst,qn0)/elem(ie)%state%dp3d(:,:,:,n0)
end do
end do
!
- ! compute Cp and kappa=Rdry/cpdry here and not in RK-stages since Q stays constant => Cp and kappa also stays constant
+ ! compute Cp and kappa=Rdry/cpdry here and not in RK-stages since Q stays constant
!
- if (lcp_moist) then
- do ie=nets,nete
- call get_cp(qwater(:,:,:,:,ie),&
- .true., inv_cp_full(:,:,:,ie), active_species_idx_dycore=qidx)
- end do
- else
- do ie=nets,nete
- inv_cp_full(:,:,:,ie) = 1.0_r8/cpair
- end do
- end if
+ do ie=nets,nete
+ call get_cp(qwater(:,:,:,:,ie),.true.,&
+ inv_cp_full(:,:,:,ie), active_species_idx_dycore=qidx)
+ end do
do ie=nets,nete
call get_kappa_dry(qwater(:,:,:,:,ie), qidx, kappa(:,:,:,ie))
end do
@@ -270,7 +262,7 @@ end subroutine prim_advance_exp
subroutine applyCAMforcing(elem,fvm,np1,np1_qdp,dt_dribble,dt_phys,nets,nete,nsubstep)
- use dimensions_mod, only: np, nc, nlev, qsize, ntrac
+ use dimensions_mod, only: np, nc, nlev, qsize, ntrac, use_cslam
use element_mod, only: element_t
use control_mod, only: ftype, ftype_conserve
use fvm_control_volume_mod, only: fvm_struct
@@ -290,7 +282,7 @@ subroutine applyCAMforcing(elem,fvm,np1,np1_qdp,dt_dribble,dt_phys,nets,nete,nsu
real (kind=r8), allocatable :: ftmp_fvm(:,:,:,:,:) !diagnostics
- if (ntrac>0) allocate(ftmp_fvm(nc,nc,nlev,ntrac,nets:nete))
+ if (use_cslam) allocate(ftmp_fvm(nc,nc,nlev,ntrac,nets:nete))
if (ftype==0) then
!
@@ -322,7 +314,7 @@ subroutine applyCAMforcing(elem,fvm,np1,np1_qdp,dt_dribble,dt_phys,nets,nete,nsu
! do state-update for tracers and "dribbling" forcing for u,v,T
!
dt_local = dt_dribble
- if (ntrac>0) then
+ if (use_cslam) then
dt_local_tracer = dt_dribble
dt_local_tracer_fvm = dt_phys
if (nsubstep.ne.1) then
@@ -371,7 +363,7 @@ subroutine applyCAMforcing(elem,fvm,np1,np1_qdp,dt_dribble,dt_phys,nets,nete,nsu
else
ftmp(:,:,:,:,ie) = 0.0_r8
end if
- if (ntrac>0.and.dt_local_tracer_fvm>0) then
+ if (use_cslam.and.dt_local_tracer_fvm>0) then
!
! Repeat for the fvm tracers: fc holds tendency (fc_new-fc_old)/dt_physics
!
@@ -395,18 +387,16 @@ subroutine applyCAMforcing(elem,fvm,np1,np1_qdp,dt_dribble,dt_phys,nets,nete,nsu
end do
end do
else
- if (ntrac>0) ftmp_fvm(:,:,:,:,ie) = 0.0_r8
+ if (use_cslam) ftmp_fvm(:,:,:,:,ie) = 0.0_r8
end if
-
if (ftype_conserve==1) then
call get_dp(elem(ie)%state%Qdp(:,:,:,1:qsize,np1_qdp), MASS_MIXING_RATIO, &
- thermodynamic_active_species_idx_dycore, elem(ie)%state%dp3d(:,:,:,np1), pdel)
+ thermodynamic_active_species_idx_dycore, elem(ie)%state%dp3d(:,:,:,np1), pdel)
do k=1,nlev
do j=1,np
do i = 1,np
pdel(i,j,k)=elem(ie)%derived%FDP(i,j,k)/pdel(i,j,k)
-
elem(ie)%state%T(i,j,k,np1) = elem(ie)%state%T(i,j,k,np1) + &
dt_local*elem(ie)%derived%FT(i,j,k)*pdel(i,j,k)
!
@@ -426,13 +416,13 @@ subroutine applyCAMforcing(elem,fvm,np1,np1_qdp,dt_dribble,dt_phys,nets,nete,nsu
dt_local*elem(ie)%derived%FM(:,:,:,:)
end if
end do
- if (ntrac>0) then
+ if (use_cslam) then
call output_qdp_var_dynamics(ftmp_fvm(:,:,:,:,:),nc,ntrac,nets,nete,'PDC')
else
call output_qdp_var_dynamics(ftmp(:,:,:,:,:),np,qsize,nets,nete,'PDC')
end if
- if (ftype==1.and.nsubstep==1) call calc_tot_energy_dynamics(elem,fvm,nets,nete,np1,np1_qdp,'p2d')
- if (ntrac>0) deallocate(ftmp_fvm)
+ if (ftype==1.and.nsubstep==1) call tot_energy_dyn(elem,fvm,nets,nete,np1,np1_qdp,'p2d')
+ if (use_cslam) deallocate(ftmp_fvm)
end subroutine applyCAMforcing
@@ -446,11 +436,11 @@ subroutine advance_hypervis_dp(edge3,elem,fvm,hybrid,deriv,nt,qn0,nets,nete,dt2,
! For correct scaling, dt2 should be the same 'dt2' used in the leapfrog advace
!
!
- use physconst, only: gravit, cappa, cpair, tref, lapse_rate
+ use physconst, only: cappa, cpair
use cam_thermo, only: get_molecular_diff_coef, get_rho_dry
- use dimensions_mod, only: np, nlev, nc, ntrac, npsq, qsize, ksponge_end
+ use dimensions_mod, only: np, nlev, nc, use_cslam, npsq, qsize, ksponge_end
use dimensions_mod, only: nu_scale_top,nu_lev,kmvis_ref,kmcnd_ref,rho_ref,km_sponge_factor
- use dimensions_mod, only: kmvisi_ref,kmcndi_ref,nu_t_lev
+ use dimensions_mod, only: nu_t_lev
use control_mod, only: nu, nu_t, hypervis_subcycle,hypervis_subcycle_sponge, nu_p, nu_top
use control_mod, only: molecular_diff
use hybrid_mod, only: hybrid_t!, get_loop_ranges
@@ -468,7 +458,7 @@ subroutine advance_hypervis_dp(edge3,elem,fvm,hybrid,deriv,nt,qn0,nets,nete,dt2,
type (hybrid_t) , intent(in) :: hybrid
type (element_t) , intent(inout), target :: elem(:)
- type(fvm_struct) , intent(in) :: fvm(:)
+ type(fvm_struct) , intent(inout) :: fvm(:)
type (EdgeBuffer_t), intent(inout):: edge3
type (derivative_t), intent(in ) :: deriv
integer , intent(in) :: nets,nete, nt, qn0
@@ -489,16 +479,13 @@ subroutine advance_hypervis_dp(edge3,elem,fvm,hybrid,deriv,nt,qn0,nets,nete,dt2,
type (EdgeDescriptor_t) :: desc
real (kind=r8), dimension(np,np) :: lap_t,lap_dp
- real (kind=r8), dimension(np,np) :: tmp, tmp2
real (kind=r8), dimension(np,np,ksponge_end,nets:nete):: kmvis,kmcnd,rho_dry
- real (kind=r8), dimension(np,np,ksponge_end+1):: kmvisi,kmcndi
real (kind=r8), dimension(np,np,nlev) :: tmp_kmvis,tmp_kmcnd
real (kind=r8), dimension(np,np,2) :: lap_v
- real (kind=r8) :: v1,v2,v1new,v2new,dt,heating,T0,T1
+ real (kind=r8) :: v1,v2,v1new,v2new,dt,heating
real (kind=r8) :: laplace_fluxes(nc,nc,4)
real (kind=r8) :: rhypervis_subcycle
real (kind=r8) :: nu_ratio1, ptop, inv_rho
- real (kind=r8), dimension(ksponge_end) :: dtemp,du,dv
real (kind=r8) :: nu_temp, nu_dp, nu_velo
if (nu_t == 0 .and. nu == 0 .and. nu_p==0 ) return;
@@ -516,7 +503,7 @@ subroutine advance_hypervis_dp(edge3,elem,fvm,hybrid,deriv,nt,qn0,nets,nete,dt2,
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
do ic=1,hypervis_subcycle
- call calc_tot_energy_dynamics(elem,fvm,nets,nete,nt,qn0,'dBH')
+ call tot_energy_dyn(elem,fvm,nets,nete,nt,qn0,'dBH')
rhypervis_subcycle=1.0_r8/real(hypervis_subcycle,kind=r8)
call biharmonic_wk_dp3d(elem,dptens,dpflux,ttens,vtens,deriv,edge3,hybrid,nt,nets,nete,kbeg,kend,hvcoord)
@@ -554,7 +541,7 @@ subroutine advance_hypervis_dp(edge3,elem,fvm,hybrid,deriv,nt,qn0,nets,nete,dt2,
enddo
enddo
- if (ntrac>0) then
+ if (use_cslam) then
!OMP_COLLAPSE_SIMD
!DIR_VECTOR_ALIGNED
do j=1,nc
@@ -606,7 +593,7 @@ subroutine advance_hypervis_dp(edge3,elem,fvm,hybrid,deriv,nt,qn0,nets,nete,dt2,
kptr = kbeg - 1 + 2*nlev
call edgeVunpack(edge3,vtens(:,:,2,kbeg:kend,ie),kblk,kptr,ie)
- if (ntrac>0) then
+ if (use_cslam) then
do k=kbeg,kend
temp(:,:,k) = elem(ie)%state%dp3d(:,:,k,nt) / elem(ie)%spheremp ! STATE before DSS
corners(0:np+1,0:np+1,k) = 0.0_r8
@@ -616,7 +603,7 @@ subroutine advance_hypervis_dp(edge3,elem,fvm,hybrid,deriv,nt,qn0,nets,nete,dt2,
kptr = kbeg - 1 + 3*nlev
call edgeVunpack(edge3,elem(ie)%state%dp3d(:,:,kbeg:kend,nt),kblk,kptr,ie)
- if (ntrac>0) then
+ if (use_cslam) then
desc = elem(ie)%desc
kptr = kbeg - 1 + 3*nlev
@@ -676,10 +663,13 @@ subroutine advance_hypervis_dp(edge3,elem,fvm,hybrid,deriv,nt,qn0,nets,nete,dt2,
enddo
end do
- call calc_tot_energy_dynamics(elem,fvm,nets,nete,nt,qn0,'dCH')
+ call tot_energy_dyn(elem,fvm,nets,nete,nt,qn0,'dCH')
do ie=nets,nete
!$omp parallel do num_threads(vert_num_threads), private(k,i,j,v1,v2,heating)
- do k=kbeg,kend
+ do k=ksponge_end,nlev
+ !
+ ! only do "frictional heating" away from sponge
+ !
!OMP_COLLAPSE_SIMD
!DIR_VECTOR_ALIGNED
do j=1,np
@@ -696,7 +686,7 @@ subroutine advance_hypervis_dp(edge3,elem,fvm,hybrid,deriv,nt,qn0,nets,nete,dt2,
enddo
enddo
enddo
- call calc_tot_energy_dynamics(elem,fvm,nets,nete,nt,qn0,'dAH')
+ call tot_energy_dyn(elem,fvm,nets,nete,nt,qn0,'dAH')
end do
!
@@ -771,7 +761,7 @@ subroutine advance_hypervis_dp(edge3,elem,fvm,hybrid,deriv,nt,qn0,nets,nete,dt2,
! Horizontal Laplacian diffusion
!
dt=dt2/hypervis_subcycle_sponge
- call calc_tot_energy_dynamics(elem,fvm,nets,nete,nt,qn0,'dBS')
+ call tot_energy_dyn(elem,fvm,nets,nete,nt,qn0,'dBS')
kblk = ksponge_end
do ic=1,hypervis_subcycle_sponge
rhypervis_subcycle=1.0_r8/real(hypervis_subcycle_sponge,kind=r8)
@@ -828,7 +818,7 @@ subroutine advance_hypervis_dp(edge3,elem,fvm,hybrid,deriv,nt,qn0,nets,nete,dt2,
end do
end if
- if (ntrac>0.and.nu_dp>0) then
+ if (use_cslam.and.nu_dp>0) then
!
! mass flux for CSLAM due to sponge layer diffusion on dp
!
@@ -876,7 +866,7 @@ subroutine advance_hypervis_dp(edge3,elem,fvm,hybrid,deriv,nt,qn0,nets,nete,dt2,
kptr = 2*ksponge_end
call edgeVunpack(edgeSponge,vtens(:,:,2,1:ksponge_end,ie),kblk,kptr,ie)
- if (ntrac>0.and.nu_dp>0.0_r8) then
+ if (use_cslam.and.nu_dp>0.0_r8) then
do k=1,ksponge_end
temp(:,:,k) = elem(ie)%state%dp3d(:,:,k,nt) / elem(ie)%spheremp ! STATE before DSS
corners(0:np+1,0:np+1,k) = 0.0_r8
@@ -886,7 +876,7 @@ subroutine advance_hypervis_dp(edge3,elem,fvm,hybrid,deriv,nt,qn0,nets,nete,dt2,
kptr = 3*ksponge_end
call edgeVunpack(edgeSponge,elem(ie)%state%dp3d(:,:,1:ksponge_end,nt),kblk,kptr,ie)
- if (ntrac>0.and.nu_dp>0.0_r8) then
+ if (use_cslam.and.nu_dp>0.0_r8) then
desc = elem(ie)%desc
kptr = 3*ksponge_end
@@ -926,38 +916,40 @@ subroutine advance_hypervis_dp(edge3,elem,fvm,hybrid,deriv,nt,qn0,nets,nete,dt2,
vtens(i,j,2,k,ie)=dt*vtens(i,j,2,k,ie)*elem(ie)%rspheremp(i,j)
ttens(i,j,k,ie)=dt*ttens(i,j,k,ie)*elem(ie)%rspheremp(i,j)
elem(ie)%state%dp3d(i,j,k,nt)=elem(ie)%state%dp3d(i,j,k,nt)*elem(ie)%rspheremp(i,j)
+ ! update v first (gives better results than updating v after heating)
+ elem(ie)%state%v(i,j,:,k,nt)=elem(ie)%state%v(i,j,:,k,nt) + vtens(i,j,:,k,ie)
+ elem(ie)%state%T(i,j, k,nt)=elem(ie)%state%T(i,j, k,nt) + ttens(i,j, k,ie)
enddo
enddo
enddo
- !$omp parallel do num_threads(vert_num_threads) private(k,i,j,v1,v2,v1new,v2new)
- do k=1,ksponge_end
- !OMP_COLLAPSE_SIMD
- !DIR_VECTOR_ALIGNED
- do j=1,np
- do i=1,np
- ! update v first (gives better results than updating v after heating)
- elem(ie)%state%v(i,j,:,k,nt)=elem(ie)%state%v(i,j,:,k,nt) + &
- vtens(i,j,:,k,ie)
- elem(ie)%state%T(i,j,k,nt)=elem(ie)%state%T(i,j,k,nt) &
- +ttens(i,j,k,ie)
-
- v1new=elem(ie)%state%v(i,j,1,k,nt)
- v2new=elem(ie)%state%v(i,j,2,k,nt)
- v1 =elem(ie)%state%v(i,j,1,k,nt)- vtens(i,j,1,k,ie)
- v2 =elem(ie)%state%v(i,j,2,k,nt)- vtens(i,j,2,k,ie)
- !
- ! frictional heating
- !
- heating = 0.5_r8*(v1new*v1new+v2new*v2new-(v1*v1+v2*v2))
- elem(ie)%state%T(i,j,k,nt)=elem(ie)%state%T(i,j,k,nt) &
- -heating*inv_cp_full(i,j,k,ie)
+ if (molecular_diff>0) then
+ !
+ ! no frictional heating for artificial sponge
+ !
+ !$omp parallel do num_threads(vert_num_threads) private(k,i,j,v1,v2,v1new,v2new)
+ do k=1,ksponge_end
+ !OMP_COLLAPSE_SIMD
+ !DIR_VECTOR_ALIGNED
+ do j=1,np
+ do i=1,np
+ v1new=elem(ie)%state%v(i,j,1,k,nt)
+ v2new=elem(ie)%state%v(i,j,2,k,nt)
+ v1 =elem(ie)%state%v(i,j,1,k,nt)- vtens(i,j,1,k,ie)
+ v2 =elem(ie)%state%v(i,j,2,k,nt)- vtens(i,j,2,k,ie)
+ !
+ ! frictional heating
+ !
+ heating = 0.5_r8*(v1new*v1new+v2new*v2new-(v1*v1+v2*v2))
+ elem(ie)%state%T(i,j,k,nt)=elem(ie)%state%T(i,j,k,nt) &
+ -heating*inv_cp_full(i,j,k,ie)
+ enddo
enddo
enddo
- enddo
+ end if
end do
end do
call t_stopf('sponge_diff')
- call calc_tot_energy_dynamics(elem,fvm,nets,nete,nt,qn0,'dAS')
+ call tot_energy_dyn(elem,fvm,nets,nete,nt,qn0,'dAS')
end subroutine advance_hypervis_dp
@@ -983,7 +975,7 @@ subroutine compute_and_apply_rhs(np1,nm1,n0,dt2,elem,hvcoord,hybrid,&
! allows us to fuse these two loops for more cache reuse
!
! ===================================
- use dimensions_mod, only: np, nc, nlev, ntrac, ksponge_end
+ use dimensions_mod, only: np, nc, nlev, use_cslam
use hybrid_mod, only: hybrid_t
use element_mod, only: element_t
use derivative_mod, only: derivative_t, divergence_sphere, gradient_sphere, vorticity_sphere
@@ -992,12 +984,10 @@ subroutine compute_and_apply_rhs(np1,nm1,n0,dt2,elem,hvcoord,hybrid,&
use edgetype_mod, only: edgedescriptor_t
use bndry_mod, only: bndry_exchange
use hybvcoord_mod, only: hvcoord_t
- use physconst, only: epsilo
use cam_thermo, only: get_gz, get_virtual_temp
use air_composition, only: thermodynamic_active_species_num, dry_air_species_num
- use air_composition, only: thermodynamic_active_species_idx_dycore, get_cp_dry, get_R_dry
- use physconst, only: tref,cpair,gravit,lapse_rate
- use time_mod, only : tevolve
+ use air_composition, only: get_cp_dry, get_R_dry
+ use physconst, only: tref,cpair,rga,lapse_rate
implicit none
integer, intent(in) :: np1,nm1,n0,nets,nete
@@ -1028,9 +1018,7 @@ subroutine compute_and_apply_rhs(np1,nm1,n0,dt2,elem,hvcoord,hybrid,&
real (kind=r8), dimension(np,np) :: vgrad_T ! v.grad(T)
real (kind=r8), dimension(np,np) :: Ephi ! kinetic energy + PHI term
real (kind=r8), dimension(np,np,2,nlev) :: grad_p_full
- real (kind=r8), dimension(np,np,2,nlev) :: grad_p_m_pmet! gradient(p - p_met)
real (kind=r8), dimension(np,np,nlev) :: vort ! vorticity
- real (kind=r8), dimension(np,np,nlev) :: p_dry ! pressure dry
real (kind=r8), dimension(np,np,nlev) :: dp_dry ! delta pressure dry
real (kind=r8), dimension(np,np,nlev) :: R_dry, cp_dry!
real (kind=r8), dimension(np,np,nlev) :: p_full ! pressure
@@ -1053,7 +1041,7 @@ subroutine compute_and_apply_rhs(np1,nm1,n0,dt2,elem,hvcoord,hybrid,&
real (kind=r8) :: sum_water(np,np,nlev), density_inv(np,np)
real (kind=r8) :: E,v1,v2,glnps1,glnps2
integer :: i,j,k,kptr,ie
- real (kind=r8) :: u_m_umet, v_m_vmet, t_m_tmet, ptop
+ real (kind=r8) :: ptop
!JMD call t_barrierf('sync_compute_and_apply_rhs', hybrid%par%comm)
call t_adj_detailf(+1)
@@ -1217,7 +1205,7 @@ subroutine compute_and_apply_rhs(np1,nm1,n0,dt2,elem,hvcoord,hybrid,&
! T1 = .0065*Tref*Cp/g ! = ~191
! T0 = Tref-T1 ! = ~97
!
- T1 = lapse_rate*Tref*cpair/gravit
+ T1 = lapse_rate*Tref*cpair*rga
T0 = Tref-T1
if (hvcoord%hybm(k)>0) then
@@ -1274,7 +1262,7 @@ subroutine compute_and_apply_rhs(np1,nm1,n0,dt2,elem,hvcoord,hybrid,&
enddo
- if (ntrac>0.and.eta_ave_w.ne.0._r8) then
+ if (use_cslam.and.eta_ave_w.ne.0._r8) then
!OMP_COLLAPSE_SIMD
!DIR_VECTOR_ALIGNED
do j=1,np
@@ -1317,7 +1305,7 @@ subroutine compute_and_apply_rhs(np1,nm1,n0,dt2,elem,hvcoord,hybrid,&
kptr=nlev
call edgeVunpack(edge3, elem(ie)%state%v(:,:,:,:,np1), 2*nlev, kptr, ie)
- if (ntrac>0.and.eta_ave_w.ne.0._r8) then
+ if (use_cslam.and.eta_ave_w.ne.0._r8) then
do k=1,nlev
stashdp3d(:,:,k) = elem(ie)%state%dp3d(:,:,k,np1)/elem(ie)%spheremp(:,:)
end do
@@ -1328,7 +1316,7 @@ subroutine compute_and_apply_rhs(np1,nm1,n0,dt2,elem,hvcoord,hybrid,&
kptr=kptr+2*nlev
call edgeVunpack(edge3, elem(ie)%state%dp3d(:,:,:,np1),nlev,kptr,ie)
- if (ntrac>0.and.eta_ave_w.ne.0._r8) then
+ if (use_cslam.and.eta_ave_w.ne.0._r8) then
desc = elem(ie)%desc
call edgeDGVunpack(edge3, corners, nlev, kptr, ie)
@@ -1447,35 +1435,50 @@ subroutine distribute_flux_at_corners(cflux, corners, getmapP)
endif
end subroutine distribute_flux_at_corners
- subroutine calc_tot_energy_dynamics(elem,fvm,nets,nete,tl,tl_qdp,outfld_name_suffix)
- use dimensions_mod, only: npsq,nlev,np,lcp_moist,nc,ntrac,qsize
- use physconst, only: gravit, cpair, rearth, omega
+ subroutine tot_energy_dyn(elem,fvm,nets,nete,tl,tl_qdp,outfld_name_suffix)
+ use dimensions_mod, only: npsq,nlev,np,nc,use_cslam,qsize
+ use physconst, only: rga, cpair, rearth, omega
use element_mod, only: element_t
- use cam_history, only: outfld, hist_fld_active
+ use cam_history, only: outfld
+ use cam_history_support, only: max_fieldname_len
use constituents, only: cnst_get_ind
use string_utils, only: strlist_get_ind
use hycoef, only: hyai, ps0
use fvm_control_volume_mod, only: fvm_struct
- use cam_thermo, only: get_dp, MASS_MIXING_RATIO
+ use cam_thermo, only: get_dp, MASS_MIXING_RATIO,wvidx,wlidx,wiidx,seidx,keidx,moidx,mridx,ttidx,teidx, &
+ poidx,thermo_budget_num_vars,thermo_budget_vars
+ use cam_thermo, only: get_hydrostatic_energy
use air_composition, only: thermodynamic_active_species_idx_dycore, get_cp
+ use air_composition, only: thermodynamic_active_species_num, thermodynamic_active_species_idx_dycore
+ use air_composition, only: thermodynamic_active_species_liq_num,thermodynamic_active_species_liq_idx
+ use air_composition, only: thermodynamic_active_species_ice_num,thermodynamic_active_species_ice_idx
use dimensions_mod, only: cnst_name_gll
+ use dyn_tests_utils, only: vcoord=>vc_dry_pressure
+ use cam_budget, only: thermo_budget_history
!------------------------------Arguments--------------------------------
- type (element_t) , intent(in) :: elem(:)
- type(fvm_struct) , intent(in) :: fvm(:)
+ type (element_t) , intent(inout) :: elem(:)
+ type(fvm_struct) , intent(inout) :: fvm(:)
integer , intent(in) :: tl, tl_qdp,nets,nete
character*(*) , intent(in) :: outfld_name_suffix ! suffix for "outfld" names
!---------------------------Local storage-------------------------------
- real(kind=r8) :: se(npsq) ! Dry Static energy (J/m2)
- real(kind=r8) :: ke(npsq) ! kinetic energy (J/m2)
+ real(kind=r8) :: se(np,np) ! Enthalpy energy (J/m2)
+ real(kind=r8) :: ke(np,np) ! kinetic energy (J/m2)
+ real(kind=r8) :: po(np,np) ! PHIS term in energy equation (J/m2)
+ real(kind=r8) :: wv(np,np) ! water vapor
+ real(kind=r8) :: liq(np,np) ! liquid
+ real(kind=r8) :: ice(np,np) ! ice
+ real(kind=r8) :: q(np,nlev,qsize)
+ integer :: qidx(thermodynamic_active_species_num)
real(kind=r8) :: cdp_fvm(nc,nc,nlev)
- real(kind=r8) :: se_tmp
- real(kind=r8) :: ke_tmp
- real(kind=r8) :: ps(np,np)
+ real(kind=r8) :: cdp(np,np,nlev)
+ real(kind=r8) :: ptop(np,np)
real(kind=r8) :: pdel(np,np,nlev)
+ real(kind=r8) :: cp(np,np,nlev)
+
!
! global axial angular momentum (AAM) can be separated into one part (mr) associatedwith the relative motion
! of the atmosphere with respect to the planets surface (also known as wind AAM) and another part (mo)
@@ -1485,25 +1488,19 @@ subroutine calc_tot_energy_dynamics(elem,fvm,nets,nete,tl,tl_qdp,outfld_name_suf
real(kind=r8) :: mr(npsq) ! wind AAM
real(kind=r8) :: mo(npsq) ! mass AAM
real(kind=r8) :: mr_cnst, mo_cnst, cos_lat, mr_tmp, mo_tmp
- real(kind=r8) :: cp(np,np,nlev)
- integer :: ie,i,j,k
+ integer :: ie,i,j,k,m_cnst,nq,idx
integer :: ixwv,ixcldice, ixcldliq, ixtt ! CLDICE, CLDLIQ and test tracer indices
- character(len=16) :: name_out1,name_out2,name_out3,name_out4,name_out5,name_out6
+ character(len=max_fieldname_len) :: name_out(thermo_budget_num_vars)
!-----------------------------------------------------------------------
- name_out1 = 'SE_' //trim(outfld_name_suffix)
- name_out2 = 'KE_' //trim(outfld_name_suffix)
- name_out3 = 'WV_' //trim(outfld_name_suffix)
- name_out4 = 'WL_' //trim(outfld_name_suffix)
- name_out5 = 'WI_' //trim(outfld_name_suffix)
- name_out6 = 'TT_' //trim(outfld_name_suffix)
-
- if ( hist_fld_active(name_out1).or.hist_fld_active(name_out2).or.hist_fld_active(name_out3).or.&
- hist_fld_active(name_out4).or.hist_fld_active(name_out5).or.hist_fld_active(name_out6)) then
+ if (thermo_budget_history) then
+ do i=1,thermo_budget_num_vars
+ name_out(i)=trim(thermo_budget_vars(i))//'_'//trim(outfld_name_suffix)
+ end do
- if (ntrac>0) then
+ if (use_cslam) then
ixwv = 1
call cnst_get_ind('CLDLIQ' , ixcldliq, abort=.false.)
call cnst_get_ind('CLDICE' , ixcldice, abort=.false.)
@@ -1519,79 +1516,104 @@ subroutine calc_tot_energy_dynamics(elem,fvm,nets,nete,tl,tl_qdp,outfld_name_suf
!
! Compute frozen static energy in 3 parts: KE, SE, and energy associated with vapor and liquid
!
+ do nq=1,thermodynamic_active_species_num
+ qidx(nq) = nq
+ end do
do ie=nets,nete
- se = 0.0_r8
- ke = 0.0_r8
- call get_dp(elem(ie)%state%Qdp(:,:,:,1:qsize,tl_qdp), MASS_MIXING_RATIO, thermodynamic_active_species_idx_dycore,&
- elem(ie)%state%dp3d(:,:,:,tl), pdel, ps=ps, ptop=hyai(1)*ps0)
call get_cp(elem(ie)%state%Qdp(:,:,:,1:qsize,tl_qdp),&
- .false., cp, dp_dry=elem(ie)%state%dp3d(:,:,:,tl),&
+ .false., cp, factor=1.0_r8/elem(ie)%state%dp3d(:,:,:,tl),&
active_species_idx_dycore=thermodynamic_active_species_idx_dycore)
- do k = 1, nlev
- do j=1,np
- do i = 1, np
- !
- ! kinetic energy
- !
- ke_tmp = 0.5_r8*(elem(ie)%state%v(i,j,1,k,tl)**2+ elem(ie)%state%v(i,j,2,k,tl)**2)*pdel(i,j,k)/gravit
- if (lcp_moist) then
- se_tmp = cp(i,j,k)*elem(ie)%state%T(i,j,k,tl)*pdel(i,j,k)/gravit
- else
- !
- ! using CAM physics definition of internal energy
- !
- se_tmp = cpair*elem(ie)%state%T(i,j,k,tl)*pdel(i,j,k)/gravit
- end if
- se (i+(j-1)*np) = se (i+(j-1)*np) + se_tmp
- ke (i+(j-1)*np) = ke (i+(j-1)*np) + ke_tmp
- end do
- end do
- end do
-
+ ptop = hyai(1)*ps0
do j=1,np
- do i = 1, np
- se(i+(j-1)*np) = se(i+(j-1)*np) + elem(ie)%state%phis(i,j)*ps(i,j)/gravit
+ !get mixing ratio of thermodynamic active species only
+ !(other tracers not used in get_hydrostatic_energy)
+ do nq=1,thermodynamic_active_species_num
+ m_cnst = thermodynamic_active_species_idx_dycore(nq)
+ q(:,:,m_cnst) = elem(ie)%state%Qdp(:,j,:,m_cnst,tl_qdp)/&
+ elem(ie)%state%dp3d(:,j,:,tl)
end do
+ call get_hydrostatic_energy(q, &
+ .false., elem(ie)%state%dp3d(:,j,:,tl), cp(:,j,:), elem(ie)%state%v(:,j,1,:,tl), &
+ elem(ie)%state%v(:,j,2,:,tl), elem(ie)%state%T(:,j,:,tl), vcoord, ptop=ptop(:,j),&
+ phis=elem(ie)%state%phis(:,j), dycore_idx=.true., &
+ se=se(:,j), po=po(:,j), ke=ke(:,j), wv=wv(:,j), liq=liq(:,j), ice=ice(:,j))
end do
!
! Output energy diagnostics on GLL grid
!
- call outfld(name_out1 ,se ,npsq,ie)
- call outfld(name_out2 ,ke ,npsq,ie)
+ call outfld(name_out(poidx) ,po ,npsq,ie)
+ call outfld(name_out(seidx) ,se ,npsq,ie)
+ call outfld(name_out(keidx) ,ke ,npsq,ie)
+ call outfld(name_out(teidx) ,ke+se+po ,npsq,ie)
!
! mass variables are output on CSLAM grid if using CSLAM else GLL grid
!
- if (ntrac>0) then
- if (ixwv>0) then
- cdp_fvm = fvm(ie)%c(1:nc,1:nc,:,ixwv)*fvm(ie)%dp_fvm(1:nc,1:nc,:)
- call util_function(cdp_fvm,nc,nlev,name_out3,ie)
- end if
- if (ixcldliq>0) then
- cdp_fvm = fvm(ie)%c(1:nc,1:nc,:,ixcldliq)*fvm(ie)%dp_fvm(1:nc,1:nc,:)
- call util_function(cdp_fvm,nc,nlev,name_out4,ie)
- end if
- if (ixcldice>0) then
- cdp_fvm = fvm(ie)%c(1:nc,1:nc,:,ixcldice)*fvm(ie)%dp_fvm(1:nc,1:nc,:)
- call util_function(cdp_fvm,nc,nlev,name_out5,ie)
- end if
- if (ixtt>0) then
- cdp_fvm = fvm(ie)%c(1:nc,1:nc,:,ixtt)*fvm(ie)%dp_fvm(1:nc,1:nc,:)
- call util_function(cdp_fvm,nc,nlev,name_out6,ie)
- end if
+ if (use_cslam) then
+ if (ixwv>0) then
+ cdp_fvm = fvm(ie)%c(1:nc,1:nc,:,ixwv)*fvm(ie)%dp_fvm(1:nc,1:nc,:)
+ call util_function(cdp_fvm,nc,nlev,name_out(wvidx),ie)
+ end if
+ !
+ ! sum over liquid water
+ !
+ if (thermodynamic_active_species_liq_num>0) then
+ cdp_fvm = 0.0_r8
+ do nq = 1,thermodynamic_active_species_liq_num
+ cdp_fvm = cdp_fvm + fvm(ie)%c(1:nc,1:nc,:,thermodynamic_active_species_liq_idx(nq))&
+ *fvm(ie)%dp_fvm(1:nc,1:nc,:)
+ end do
+ call util_function(cdp_fvm,nc,nlev,name_out(wlidx),ie)
+ end if
+ !
+ ! sum over ice water
+ !
+ if (thermodynamic_active_species_ice_num>0) then
+ cdp_fvm = 0.0_r8
+ do nq = 1,thermodynamic_active_species_ice_num
+ cdp_fvm = cdp_fvm + fvm(ie)%c(1:nc,1:nc,:,thermodynamic_active_species_ice_idx(nq))&
+ *fvm(ie)%dp_fvm(1:nc,1:nc,:)
+ end do
+ call util_function(cdp_fvm,nc,nlev,name_out(wiidx),ie)
+ end if
+ if (ixtt>0) then
+ cdp_fvm = fvm(ie)%c(1:nc,1:nc,:,ixtt)*fvm(ie)%dp_fvm(1:nc,1:nc,:)
+ call util_function(cdp_fvm,nc,nlev,name_out(ttidx),ie)
+ end if
else
- call util_function(elem(ie)%state%qdp(:,:,:,1 ,tl_qdp),np,nlev,name_out3,ie)
- if (ixcldliq>0) call util_function(elem(ie)%state%qdp(:,:,:,ixcldliq,tl_qdp),np,nlev,name_out4,ie)
- if (ixcldice>0) call util_function(elem(ie)%state%qdp(:,:,:,ixcldice,tl_qdp),np,nlev,name_out5,ie)
- if (ixtt>0 ) call util_function(elem(ie)%state%qdp(:,:,:,ixtt ,tl_qdp),np,nlev,name_out6,ie)
+ cdp = elem(ie)%state%qdp(:,:,:,1,tl_qdp)
+ call util_function(cdp,np,nlev,name_out(wvidx),ie)
+ !
+ ! sum over liquid water
+ !
+ if (thermodynamic_active_species_liq_num>0) then
+ cdp = 0.0_r8
+ do idx = 1,thermodynamic_active_species_liq_num
+ cdp = cdp + elem(ie)%state%qdp(:,:,:,thermodynamic_active_species_liq_idx(idx),tl_qdp)
+ end do
+ call util_function(cdp,np,nlev,name_out(wlidx),ie)
+ end if
+ !
+ ! sum over ice water
+ !
+ if (thermodynamic_active_species_ice_num>0) then
+ cdp = 0.0_r8
+ do idx = 1,thermodynamic_active_species_ice_num
+ cdp = cdp + elem(ie)%state%qdp(:,:,:,thermodynamic_active_species_ice_idx(idx),tl_qdp)
+ end do
+ call util_function(cdp,np,nlev,name_out(wiidx),ie)
+ end if
+ if (ixtt>0) then
+ cdp = elem(ie)%state%qdp(:,:,:,ixtt ,tl_qdp)
+ call util_function(cdp,np,nlev,name_out(ttidx),ie)
+ end if
end if
- end do
- end if
- !
- ! Axial angular momentum diagnostics
- !
- ! Code follows
- !
- ! Lauritzen et al., (2014): Held-Suarez simulations with the Community Atmosphere Model
+ end do
+ !
+ ! Axial angular momentum diagnostics
+ !
+ ! Code follows
+ !
+ ! Lauritzen et al., (2014): Held-Suarez simulations with the Community Atmosphere Model
! Spectral Element (CAM-SE) dynamical core: A global axial angularmomentum analysis using Eulerian
! and floating Lagrangian vertical coordinates. J. Adv. Model. Earth Syst. 6,129-140,
! doi:10.1002/2013MS000268
@@ -1599,19 +1621,16 @@ subroutine calc_tot_energy_dynamics(elem,fvm,nets,nete,tl,tl_qdp,outfld_name_suf
! MR is equation (6) without \Delta A and sum over areas (areas are in units of radians**2)
! MO is equation (7) without \Delta A and sum over areas (areas are in units of radians**2)
!
- name_out1 = 'MR_' //trim(outfld_name_suffix)
- name_out2 = 'MO_' //trim(outfld_name_suffix)
- if ( hist_fld_active(name_out1).or.hist_fld_active(name_out2)) then
call strlist_get_ind(cnst_name_gll, 'CLDLIQ', ixcldliq, abort=.false.)
call strlist_get_ind(cnst_name_gll, 'CLDICE', ixcldice, abort=.false.)
- mr_cnst = rearth**3/gravit
- mo_cnst = omega*rearth**4/gravit
+ mr_cnst = rga*rearth**3
+ mo_cnst = rga*omega*rearth**4
do ie=nets,nete
mr = 0.0_r8
mo = 0.0_r8
call get_dp(elem(ie)%state%Qdp(:,:,:,1:qsize,tl_qdp), MASS_MIXING_RATIO, thermodynamic_active_species_idx_dycore,&
- elem(ie)%state%dp3d(:,:,:,tl), pdel, ps=ps, ptop=hyai(1)*ps0)
+ elem(ie)%state%dp3d(:,:,:,tl), pdel)
do k = 1, nlev
do j=1,np
do i = 1, np
@@ -1624,17 +1643,17 @@ subroutine calc_tot_energy_dynamics(elem,fvm,nets,nete,tl,tl_qdp,outfld_name_suf
end do
end do
end do
- call outfld(name_out1 ,mr ,npsq,ie)
- call outfld(name_out2 ,mo ,npsq,ie)
+ call outfld(name_out(mridx) ,mr ,npsq,ie)
+ call outfld(name_out(moidx) ,mo ,npsq,ie)
end do
- end if
+ endif ! if thermo budget history
+ end subroutine tot_energy_dyn
- end subroutine calc_tot_energy_dynamics
subroutine output_qdp_var_dynamics(qdp,nx,num_trac,nets,nete,outfld_name)
- use dimensions_mod, only: nlev,ntrac
- use cam_history , only: outfld, hist_fld_active
+ use dimensions_mod, only: nlev
+ use cam_history , only: hist_fld_active
use constituents , only: cnst_get_ind
!------------------------------Arguments--------------------------------
@@ -1674,17 +1693,15 @@ end subroutine output_qdp_var_dynamics
! column integrate mass-variable and outfld
!
subroutine util_function(f_in,nx,nz,name_out,ie)
- use physconst, only: gravit
+ use physconst, only: rga
use cam_history, only: outfld, hist_fld_active
integer, intent(in) :: nx,nz,ie
real(kind=r8), intent(in) :: f_in(nx,nx,nz)
character(len=16), intent(in) :: name_out
real(kind=r8) :: f_out(nx*nx)
integer :: i,j,k
- real(kind=r8) :: inv_g
if (hist_fld_active(name_out)) then
f_out = 0.0_r8
- inv_g = 1.0_r8/gravit
do k = 1, nz
do j = 1, nx
do i = 1, nx
@@ -1692,7 +1709,7 @@ subroutine util_function(f_in,nx,nz,name_out,ie)
end do
end do
end do
- f_out = f_out*inv_g
+ f_out = f_out*rga
call outfld(name_out,f_out,nx*nx,ie)
end if
end subroutine util_function
@@ -1708,7 +1725,6 @@ subroutine compute_omega(hybrid,n0,qn0,elem,deriv,nets,nete,dt,hvcoord)
use bndry_mod, only: bndry_exchange
use viscosity_mod, only: biharmonic_wk_omega
use cam_thermo, only: get_dp, MASS_MIXING_RATIO
- use air_composition,only: thermodynamic_active_species_num
use air_composition,only: thermodynamic_active_species_idx_dycore
implicit none
type (hybrid_t) , intent(in) :: hybrid
@@ -1723,7 +1739,7 @@ subroutine compute_omega(hybrid,n0,qn0,elem,deriv,nets,nete,dt,hvcoord)
real (kind=r8) :: dp_full(np,np,nlev)
real (kind=r8) :: p_full(np,np,nlev),grad_p_full(np,np,2),vgrad_p_full(np,np,nlev)
real (kind=r8) :: divdp_full(np,np,nlev),vdp_full(np,np,2)
- real(kind=r8) :: Otens(np,np ,nlev,nets:nete), dt_hyper, sum_water(np,np,nlev)
+ real(kind=r8) :: Otens(np,np ,nlev,nets:nete), dt_hyper
logical, parameter :: del4omega = .true.
diff --git a/src/dynamics/se/dycore/prim_advection_mod.F90 b/src/dynamics/se/dycore/prim_advection_mod.F90
index 0391762cb5..7c54abc2cd 100644
--- a/src/dynamics/se/dycore/prim_advection_mod.F90
+++ b/src/dynamics/se/dycore/prim_advection_mod.F90
@@ -949,7 +949,7 @@ subroutine vertical_remap(hybrid,elem,fvm,hvcoord,np1,np1_qdp,nets,nete)
use hybrid_mod, only: hybrid_t, config_thread_region,get_loop_ranges, PrintHybrid
use fvm_control_volume_mod, only: fvm_struct
use dimensions_mod, only: ntrac
- use dimensions_mod, only: lcp_moist, kord_tr,kord_tr_cslam
+ use dimensions_mod, only: kord_tr,kord_tr_cslam
use cam_logfile, only: iulog
use physconst, only: pi
use air_composition, only: thermodynamic_active_species_idx_dycore
@@ -965,7 +965,7 @@ subroutine vertical_remap(hybrid,elem,fvm,hvcoord,np1,np1_qdp,nets,nete)
type (hvcoord_t) :: hvcoord
integer :: ie,i,j,k,np1,nets,nete,np1_qdp,q, m_cnst
real (kind=r8), dimension(np,np,nlev) :: dp_moist,dp_star_moist, dp_dry,dp_star_dry
- real (kind=r8), dimension(np,np,nlev) :: internal_energy_star
+ real (kind=r8), dimension(np,np,nlev) :: enthalpy_star
real (kind=r8), dimension(np,np,nlev,2):: ttmp
real(r8), parameter :: rad2deg = 180.0_r8/pi
integer :: region_num_threads,qbeg,qend,kord_uvT(1)
@@ -980,22 +980,20 @@ subroutine vertical_remap(hybrid,elem,fvm,hvcoord,np1,np1_qdp,nets,nete)
! prepare for mapping of temperature
!
if (vert_remap_uvTq_alg>-20) then
- if (lcp_moist) then
- !
- ! compute internal energy on Lagrangian levels
- ! (do it here since qdp is overwritten by remap1)
- !
- call get_enthalpy(elem(ie)%state%qdp(:,:,:,1:qsize,np1_qdp), &
- elem(ie)%state%t(:,:,:,np1), elem(ie)%state%dp3d(:,:,:,np1), internal_energy_star, &
- active_species_idx_dycore=thermodynamic_active_species_idx_dycore)
- end if
+ !
+ ! compute enthalpy on Lagrangian levels
+ ! (do it here since qdp is overwritten by remap1)
+ !
+ call get_enthalpy(elem(ie)%state%qdp(:,:,:,1:qsize,np1_qdp), &
+ elem(ie)%state%t(:,:,:,np1), elem(ie)%state%dp3d(:,:,:,np1), enthalpy_star, &
+ active_species_idx_dycore=thermodynamic_active_species_idx_dycore)
else
!
! map Tv over log(p) following FV and FV3
!
- call get_virtual_temp(elem(ie)%state%qdp(:,:,:,1:qsize,np1_qdp), internal_energy_star, &
+ call get_virtual_temp(elem(ie)%state%qdp(:,:,:,1:qsize,np1_qdp), enthalpy_star, &
dp_dry=elem(ie)%state%dp3d(:,:,:,np1), active_species_idx_dycore=thermodynamic_active_species_idx_dycore)
- internal_energy_star = internal_energy_star*elem(ie)%state%t(:,:,:,np1)
+ enthalpy_star = enthalpy_star*elem(ie)%state%t(:,:,:,np1)
end if
!
! update final psdry
@@ -1048,34 +1046,28 @@ subroutine vertical_remap(hybrid,elem,fvm,hvcoord,np1,np1_qdp,nets,nete)
!
if (vert_remap_uvTq_alg>-20) then
!
- ! remap internal energy and back out temperature
+ ! remap enthalpy energy and back out temperature
!
- if (lcp_moist) then
- call remap1(internal_energy_star,np,1,1,1,dp_star_dry,dp_dry,ptop,1,.true.,kord_uvT)
- !
- ! compute sum c^(l)_p*m^(l)*dp on arrival (Eulerian) grid
- !
- ttmp(:,:,:,1) = 1.0_r8
- call get_enthalpy(elem(ie)%state%qdp(:,:,:,1:qsize,np1_qdp), &
- ttmp(:,:,:,1), dp_dry,ttmp(:,:,:,2), &
- active_species_idx_dycore=thermodynamic_active_species_idx_dycore)
- elem(ie)%state%t(:,:,:,np1)=internal_energy_star/ttmp(:,:,:,2)
- else
- internal_energy_star(:,:,:)=elem(ie)%state%t(:,:,:,np1)*dp_star_moist
- call remap1(internal_energy_star,np,1,1,1,dp_star_moist,dp_moist,ptop,1,.true.,kord_uvT)
- elem(ie)%state%t(:,:,:,np1)=internal_energy_star/dp_moist
- end if
+ call remap1(enthalpy_star,np,1,1,1,dp_star_dry,dp_dry,ptop,1,.true.,kord_uvT)
+ !
+ ! compute sum c^(l)_p*m^(l)*dp on arrival (Eulerian) grid
+ !
+ ttmp(:,:,:,1) = 1.0_r8
+ call get_enthalpy(elem(ie)%state%qdp(:,:,:,1:qsize,np1_qdp), &
+ ttmp(:,:,:,1), dp_dry,ttmp(:,:,:,2), &
+ active_species_idx_dycore=thermodynamic_active_species_idx_dycore)
+ elem(ie)%state%t(:,:,:,np1)=enthalpy_star/ttmp(:,:,:,2)
else
!
! map Tv over log(p); following FV and FV3
!
- call remap1(internal_energy_star,np,1,1,1,dp_star_moist,dp_moist,ptop,1,.false.,kord_uvT)
+ call remap1(enthalpy_star,np,1,1,1,dp_star_moist,dp_moist,ptop,1,.false.,kord_uvT)
call get_virtual_temp(elem(ie)%state%qdp(:,:,:,1:qsize,np1_qdp), ttmp(:,:,:,1), &
dp_dry=dp_dry, active_species_idx_dycore=thermodynamic_active_species_idx_dycore)
!
! convert new Tv to T
!
- elem(ie)%state%t(:,:,:,np1)=internal_energy_star/ttmp(:,:,:,1)
+ elem(ie)%state%t(:,:,:,np1)=enthalpy_star/ttmp(:,:,:,1)
end if
!
! remap velocity components
diff --git a/src/dynamics/se/dycore/prim_driver_mod.F90 b/src/dynamics/se/dycore/prim_driver_mod.F90
index 5ea869b53c..af22869f24 100644
--- a/src/dynamics/se/dycore/prim_driver_mod.F90
+++ b/src/dynamics/se/dycore/prim_driver_mod.F90
@@ -26,7 +26,7 @@ module prim_driver_mod
subroutine prim_init2(elem, fvm, hybrid, nets, nete, tl, hvcoord)
use dimensions_mod, only: irecons_tracer, fvm_supercycling
- use dimensions_mod, only: fv_nphys, ntrac, nc
+ use dimensions_mod, only: fv_nphys, nc
use parallel_mod, only: syncmp
use time_mod, only: timelevel_t, tstep, phys_tscale, nsplit, TimeLevel_Qdp
use time_mod, only: nsplit_baseline,rsplit_baseline
@@ -40,7 +40,7 @@ subroutine prim_init2(elem, fvm, hybrid, nets, nete, tl, hvcoord)
use hybvcoord_mod, only: hvcoord_t
use prim_advection_mod, only: prim_advec_init2,deriv
use prim_advance_mod, only: compute_omega
- use physconst, only: gravit, cappa, cpair, tref, lapse_rate
+ use physconst, only: rga, cappa, cpair, tref, lapse_rate
use cam_thermo, only: get_dp_ref
use physconst, only: pstd
@@ -157,7 +157,7 @@ subroutine prim_init2(elem, fvm, hybrid, nets, nete, tl, hvcoord)
! T1 = .0065*Tref*Cp/g ! = ~191
! T0 = Tref-T1 ! = ~97
!
- T1 = lapse_rate*Tref*cpair/gravit
+ T1 = lapse_rate*Tref*cpair*rga
T0 = Tref-T1
do ie=nets,nete
do k=1,nlev
@@ -221,13 +221,13 @@ subroutine prim_run_subcycle(elem, fvm, hybrid,nets,nete, dt, tl, hvcoord,nsubst
use time_mod, only: TimeLevel_t, timelevel_update, timelevel_qdp, nsplit
use control_mod, only: statefreq,qsplit, rsplit, variable_nsplit
use prim_advance_mod, only: applycamforcing
- use prim_advance_mod, only: calc_tot_energy_dynamics,compute_omega
+ use prim_advance_mod, only: tot_energy_dyn,compute_omega
use prim_state_mod, only: prim_printstate, adjust_nsplit
use prim_advection_mod, only: vertical_remap, deriv
use thread_mod, only: omp_get_thread_num
use perf_mod , only: t_startf, t_stopf
use fvm_mod , only: fill_halo_fvm, ghostBufQnhc_h
- use dimensions_mod, only: ntrac,fv_nphys, ksponge_end
+ use dimensions_mod, only: use_cslam,fv_nphys, ksponge_end
type (element_t) , intent(inout) :: elem(:)
type(fvm_struct), intent(inout) :: fvm(:)
@@ -282,9 +282,9 @@ subroutine prim_run_subcycle(elem, fvm, hybrid,nets,nete, dt, tl, hvcoord,nsubst
call TimeLevel_Qdp( tl, qsplit, n0_qdp)
- call calc_tot_energy_dynamics(elem,fvm,nets,nete,tl%n0,n0_qdp,'dAF')
+ call tot_energy_dyn(elem,fvm,nets,nete,tl%n0,n0_qdp,'dAF')
call ApplyCAMForcing(elem,fvm,tl%n0,n0_qdp,dt_remap,dt_phys,nets,nete,nsubstep)
- call calc_tot_energy_dynamics(elem,fvm,nets,nete,tl%n0,n0_qdp,'dBD')
+ call tot_energy_dyn(elem,fvm,nets,nete,tl%n0,n0_qdp,'dBD')
do r=1,rsplit
if (r.ne.1) call TimeLevel_update(tl,"leapfrog")
call prim_step(elem, fvm, hybrid,nets,nete, dt, tl, hvcoord,r)
@@ -300,7 +300,7 @@ subroutine prim_run_subcycle(elem, fvm, hybrid,nets,nete, dt, tl, hvcoord,nsubst
! always for tracers
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- call calc_tot_energy_dynamics(elem,fvm,nets,nete,tl%np1,np1_qdp,'dAD')
+ call tot_energy_dyn(elem,fvm,nets,nete,tl%np1,np1_qdp,'dAD')
if (variable_nsplit.or.compute_diagnostics) then
!
@@ -317,7 +317,7 @@ subroutine prim_run_subcycle(elem, fvm, hybrid,nets,nete, dt, tl, hvcoord,nsubst
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! time step is complete.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- call calc_tot_energy_dynamics(elem,fvm,nets,nete,tl%np1,np1_qdp,'dAR')
+ call tot_energy_dyn(elem,fvm,nets,nete,tl%np1,np1_qdp,'dAR')
if (nsubstep==nsplit) then
call compute_omega(hybrid,tl%np1,np1_qdp,elem,deriv,nets,nete,dt_remap,hvcoord)
@@ -378,7 +378,7 @@ subroutine prim_run_subcycle(elem, fvm, hybrid,nets,nete, dt, tl, hvcoord,nsubst
call prim_printstate(elem, tl, hybrid,nets,nete, fvm, omega_cn)
end if
- if (ntrac>0.and.nsubstep==nsplit.and.nc.ne.fv_nphys) then
+ if (use_cslam.and.nsubstep==nsplit.and.nc.ne.fv_nphys) then
!
! fill the fvm halo for mapping in d_p_coupling if
! physics grid resolution is different than fvm resolution
@@ -414,7 +414,7 @@ subroutine prim_step(elem, fvm, hybrid,nets,nete, dt, tl, hvcoord, rstep)
use prim_advection_mod, only: prim_advec_tracers_remap, prim_advec_tracers_fvm, deriv
use derivative_mod, only: subcell_integration
use hybrid_mod, only: set_region_num_threads, config_thread_region, get_loop_ranges
- use dimensions_mod, only: ntrac,fvm_supercycling,fvm_supercycling_jet
+ use dimensions_mod, only: use_cslam,fvm_supercycling,fvm_supercycling_jet
use dimensions_mod, only: kmin_jet, kmax_jet
use fvm_mod, only: ghostBufQnhc_vh,ghostBufQ1_vh, ghostBufFlux_vh
use fvm_mod, only: ghostBufQ1_h,ghostBufQnhcJet_h, ghostBufFluxJet_h
@@ -493,7 +493,7 @@ subroutine prim_step(elem, fvm, hybrid,nets,nete, dt, tl, hvcoord, rstep)
! defer final timelevel update until after Q update.
enddo
#ifdef HOMME_TEST_SUB_ELEMENT_MASS_FLUX
- if (ntrac>0.and.rstep==1) then
+ if (use_cslam.and.rstep==1) then
do ie=nets,nete
do k=1,nlev
tempdp3d = elem(ie)%state%dp3d(:,:,k,tl%np1) - &
@@ -540,7 +540,7 @@ subroutine prim_step(elem, fvm, hybrid,nets,nete, dt, tl, hvcoord, rstep)
if (qsize > 0) then
call t_startf('prim_advec_tracers_remap')
- if(ntrac>0) then
+ if(use_cslam) then
! Deactivate threading in the tracer dimension if this is a CSLAM run
region_num_threads = 1
else
@@ -548,7 +548,7 @@ subroutine prim_step(elem, fvm, hybrid,nets,nete, dt, tl, hvcoord, rstep)
endif
call omp_set_nested(.true.)
!$OMP PARALLEL NUM_THREADS(region_num_threads), DEFAULT(SHARED), PRIVATE(hybridnew)
- if(ntrac>0) then
+ if(use_cslam) then
! Deactivate threading in the tracer dimension if this is a CSLAM run
hybridnew = config_thread_region(hybrid,'serial')
else
@@ -562,7 +562,7 @@ subroutine prim_step(elem, fvm, hybrid,nets,nete, dt, tl, hvcoord, rstep)
!
! only run fvm transport every fvm_supercycling rstep
!
- if (ntrac>0) then
+ if (use_cslam) then
!
! FVM transport
!
diff --git a/src/dynamics/se/dycore/prim_state_mod.F90 b/src/dynamics/se/dycore/prim_state_mod.F90
index f01ffbd049..2f4bcbb2db 100644
--- a/src/dynamics/se/dycore/prim_state_mod.F90
+++ b/src/dynamics/se/dycore/prim_state_mod.F90
@@ -19,7 +19,7 @@ module prim_state_mod
CONTAINS
subroutine prim_printstate(elem, tl,hybrid,nets,nete, fvm, omega_cn)
- use dimensions_mod, only: ntrac
+ use dimensions_mod, only: use_cslam
use constituents, only: cnst_name
use air_composition, only: thermodynamic_active_species_idx_dycore, dry_air_species_num
use air_composition, only: thermodynamic_active_species_num,thermodynamic_active_species_idx
@@ -60,7 +60,7 @@ subroutine prim_printstate(elem, tl,hybrid,nets,nete, fvm, omega_cn)
n0=tl%n0
call TimeLevel_Qdp( tl, qsplit, n0_qdp)
! moist surface pressure
- if (ntrac>0) then
+ if (use_cslam) then
do ie=nets,nete
moist_ps_fvm(:,:,ie)=SUM(fvm(ie)%dp_fvm(1:nc,1:nc,:),DIM=3)
do q=dry_air_species_num+1,thermodynamic_active_species_num
@@ -86,7 +86,7 @@ subroutine prim_printstate(elem, tl,hybrid,nets,nete, fvm, omega_cn)
do ie=nets,nete
da_gll(:,:,ie) = elem(ie)%mp(:,:)*elem(ie)%metdet(:,:)
enddo
- if (ntrac>0) then
+ if (use_cslam) then
do ie=nets,nete
da_fvm(:,:,ie) = fvm(ie)%area_sphere(:,:)
enddo
@@ -103,7 +103,7 @@ subroutine prim_printstate(elem, tl,hybrid,nets,nete, fvm, omega_cn)
varname(3) = 'T '
varname(4) = 'OMEGA '
varname(5) = 'OMEGA CN '
- if (ntrac>0) then
+ if (use_cslam) then
varname(6) = 'PSDRY(fvm)'
varname(7) = 'PS(fvm) '
varname(8) = 'PSDRY(gll)'
@@ -133,7 +133,7 @@ subroutine prim_printstate(elem, tl,hybrid,nets,nete, fvm, omega_cn)
min_local(ie,5) = 0.0_r8
max_local(ie,5) = 0.0_r8
end if
- if (ntrac>0) then
+ if (use_cslam) then
min_local(ie,6) = MINVAL(SUM(fvm(ie)%dp_fvm(1:nc,1:nc,:),DIM=3))
max_local(ie,6) = MAXVAL(SUM(fvm(ie)%dp_fvm(1:nc,1:nc,:),DIM=3))
min_local(ie,7) = MINVAL(moist_ps_fvm(:,:,ie))
@@ -168,7 +168,7 @@ subroutine prim_printstate(elem, tl,hybrid,nets,nete, fvm, omega_cn)
max_local(ie,nm2+1) = MAXVAL(elem(ie)%derived%FT(:,:,:))
min_local(ie,nm2+2) = MINVAL(elem(ie)%derived%FM(:,:,:,:))
max_local(ie,nm2+2) = MAXVAL(elem(ie)%derived%FM(:,:,:,:))
- if (ntrac>0) then
+ if (use_cslam) then
do q=1,statediag_numtrac
varname(nm2+2+q) = TRIM('F'//TRIM(cnst_name(q)))
min_local(ie,nm2+2+q) = MINVAL(fvm(ie)%fc(1:nc,1:nc,:,q))
@@ -201,7 +201,7 @@ subroutine prim_printstate(elem, tl,hybrid,nets,nete, fvm, omega_cn)
! tracers
!
mass = -1.0_r8
- if (ntrac>0) then
+ if (use_cslam) then
do ie=nets,nete
do q=1,statediag_numtrac
tmp_fvm(:,:,q,ie) = SUM(fvm(ie)%c(1:nc,1:nc,:,q)*fvm(ie)%dp_fvm(1:nc,1:nc,:),DIM=3)
@@ -243,7 +243,7 @@ subroutine prim_printstate(elem, tl,hybrid,nets,nete, fvm, omega_cn)
if (tl%nstep==0.or..not. initial_run) then
mass_chg(:) = 0.0_R8
elem(nets)%derived%mass(nm+1:nm+statediag_numtrac) = mass(nm+1:nm+statediag_numtrac)
- if (ntrac>0) then
+ if (use_cslam) then
elem(nets)%derived%mass(6:9) = mass(6:9)
else
elem(nets)%derived%mass(6:7) = mass(6:7)
diff --git a/src/dynamics/se/dycore/viscosity_mod.F90 b/src/dynamics/se/dycore/viscosity_mod.F90
index 1240d4a15f..04b0a1a91d 100644
--- a/src/dynamics/se/dycore/viscosity_mod.F90
+++ b/src/dynamics/se/dycore/viscosity_mod.F90
@@ -52,7 +52,7 @@ module viscosity_mod
subroutine biharmonic_wk_dp3d(elem,dptens,dpflux,ttens,vtens,deriv,edge3,hybrid,nt,nets,nete,kbeg,kend,hvcoord)
use derivative_mod, only : subcell_Laplace_fluxes
- use dimensions_mod, only : ntrac, nu_div_lev,nu_lev
+ use dimensions_mod, only : use_cslam, nu_div_lev,nu_lev
use hybvcoord_mod, only : hvcoord_t
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! compute weak biharmonic operator
@@ -86,7 +86,7 @@ subroutine biharmonic_wk_dp3d(elem,dptens,dpflux,ttens,vtens,deriv,edge3,hybrid,
kblk = kend - kbeg + 1
- if (ntrac>0) dpflux = 0
+ if (use_cslam) dpflux = 0
!if tensor hyperviscosity with tensor V is used, then biharmonic operator is (\grad\cdot V\grad) (\grad \cdot \grad)
!so tensor is only used on second call to laplace_sphere_wk
var_coef1 = .true.
@@ -150,7 +150,7 @@ subroutine biharmonic_wk_dp3d(elem,dptens,dpflux,ttens,vtens,deriv,edge3,hybrid,
kptr = kbeg - 1 + 3*nlev
call edgeVunpack(edge3,dptens(:,:,kbeg:kend,ie),kblk,kptr,ie)
- if (ntrac>0) then
+ if (use_cslam) then
do k=1,nlev
!CLEAN tmp(:,:)= rspheremv(:,:)*dptens(:,:,k,ie)
tmp(:,:)= elem(ie)%rspheremp(:,:)*dptens(:,:,k,ie)
diff --git a/src/dynamics/se/dycore_budget.F90 b/src/dynamics/se/dycore_budget.F90
new file mode 100644
index 0000000000..d2bfe0fceb
--- /dev/null
+++ b/src/dynamics/se/dycore_budget.F90
@@ -0,0 +1,528 @@
+module dycore_budget
+use shr_kind_mod, only: r8=>shr_kind_r8
+implicit none
+
+public :: print_budget
+real(r8), parameter :: eps = 1.0E-7_r8
+real(r8), parameter :: eps_mass = 1.0E-12_r8
+
+real(r8), save :: previous_dEdt_adiabatic_dycore = 0.0_r8
+real(r8), save :: previous_dEdt_dry_mass_adjust = 0.0_r8
+real(r8), save :: previous_dEdt_phys_dyn_coupl_err = 0.0_r8
+!=========================================================================================
+contains
+!=========================================================================================
+
+subroutine print_budget(hstwr)
+
+ use spmd_utils, only: masterproc
+ use cam_abortutils, only: endrun
+ use cam_logfile, only: iulog
+ use cam_budget, only: cam_budget_get_global, is_cam_budget, thermo_budget_histfile_num, thermo_budget_history
+ use cam_thermo, only: thermo_budget_vars_descriptor, thermo_budget_num_vars, thermo_budget_vars_massv, &
+ teidx, seidx, keidx, poidx
+ use dimensions_mod, only: use_cslam
+ use control_mod, only: ftype
+
+ ! arguments
+ logical, intent(in) :: hstwr(:)
+
+ ! Local variables
+ character(len=*), parameter :: subname = 'dycore_budget:print_budgets:'
+ !
+ ! physics energy tendencies
+ !
+ integer :: idx(4)
+ real(r8) :: dEdt_param_physE(4) ! dE/dt CAM physics using physics E formula (phAP-phBP)
+ real(r8) :: dEdt_param_dynE(4) ! dE/dt CAM physics using dycore E (dyAP-dyBP)
+
+ real(r8) :: dEdt_efix_physE(4) ! dE/dt energy fixer using physics E formula (phBP-phBF)
+ real(r8) :: dEdt_efix_dynE(4) ! dE/dt energy fixer using dycore E formula (dyBP-dyBF)
+
+ real(r8) :: dEdt_dme_adjust_physE(4) ! dE/dt dry mass adjustment using physics E formula (phAM-phAP)
+ real(r8) :: dEdt_dme_adjust_dynE(4) ! dE/dt dry mass adjustment using dycore E (dyAM-dyAP)
+
+ real(r8) :: dEdt_param_efix_physE(4) ! dE/dt CAM physics + energy fixer using physics E formula (phAP-phBF)
+ real(r8) :: dEdt_param_efix_dynE(4) ! dE/dt CAM physics + energy fixer using dycore E formula (dyAP-dyBF)
+
+ real(r8) :: dEdt_phys_total_dynE(4) ! dE/dt physics total using dycore E (dyAM-dyBF)
+ ! physics total = parameterizations + efix + dry-mass adjustment
+ !
+ ! SE dycore specific energy tendencies
+ !
+ real(r8) :: dEdt_phys_total_in_dyn(4) ! dEdt of physics total in dynamical core
+ ! physics total = parameterizations + efix + dry-mass adjustment
+ real(r8) :: dEdt_dycore_phys ! dEdt dycore (estimated in physics)
+ !
+ ! mass budgets physics
+ !
+ real(r8) :: dMdt_efix ! mass tendency energy fixer
+ real(r8) :: dMdt_parameterizations ! mass tendency physics paramterizations
+ real(r8) :: dMdt_dme_adjust ! mass tendency dry-mass adjustment
+ real(r8) :: dMdt_phys_total ! mass tendency physics total (energy fixer + parameterizations + dry-mass adjustment)
+ !
+ ! mass budgets dynamics
+ !
+ real(r8) :: dMdt_floating_dyn ! mass tendency floating dynamics (dAD-dBD)
+ real(r8) :: dMdt_vert_remap ! mass tendency vertical remapping (dAR-dAD)
+ real(r8) :: dMdt_del4_fric_heat ! mass tendency del4 frictional heating (dAH-dCH)
+ real(r8) :: dMdt_del4_tot ! mass tendency del4 + del4 frictional heating (dAH-dBH)
+ real(r8) :: dMdt_residual ! mass tendency residual (time truncation errors)
+ real(r8) :: dMdt_phys_total_in_dyn ! mass tendency physics total in dycore
+ real(r8) :: dMdt_PDC ! mass tendency physics-dynamics coupling
+ !
+ ! energy budgets dynamics
+ !
+ real(r8) :: dEdt_floating_dyn ! dE/dt floating dynamics (dAD-dBD)
+ real(r8) :: dEdt_vert_remap ! dE/dt vertical remapping (dAR-dAD)
+ real(r8) :: dEdt_del4 ! dE/dt del4 (dCH-dBH)
+ real(r8) :: dEdt_del4_fric_heat ! dE/dt del4 frictional heating (dAH-dCH)
+ real(r8) :: dEdt_del4_tot ! dE/dt del4 + del4 fricitional heating (dAH-dBH)
+ real(r8) :: dEdt_del2_sponge ! dE/dt del2 sponge (dAS-dBS)
+ real(r8) :: dEdt_del2_del4_tot ! dE/dt explicit diffusion total
+ real(r8) :: dEdt_residual ! dE/dt residual (dEdt_floating_dyn-dEdt_del2_del4_tot)
+ real(r8) :: dEdt_dycore_dyn ! dE/dt adiabatic dynamical core (calculated in dycore)
+ !
+ ! physics-dynamics coupling variables
+ !
+ real(r8) :: E_dBF(4) ! E of dynamics state at the end of dycore integration (on dycore deomposition)
+ real(r8) :: E_dyBF(4) ! E of physics state using dycore E
+
+
+ real(r8) :: diff, tmp ! dummy variables
+ integer :: m_cnst, i
+ character(LEN=*), parameter :: fmt = "(a40,a15,a1,F6.2,a1,F6.2,a1,E10.2,a5)"
+ character(LEN=*), parameter :: fmtf = "(a48,F8.4,a6)"
+ character(LEN=*), parameter :: fmtm = "(a48,E8.2,a9)"
+ character(LEN=15) :: str(4)
+ character(LEN=5) :: pf ! pass or fail identifier
+ !--------------------------------------------------------------------------------------
+
+ if (masterproc .and. thermo_budget_history .and. hstwr(thermo_budget_histfile_num)) then
+ idx(1) = teidx !total energy index
+ idx(2) = seidx !enthaly index
+ idx(3) = keidx !kinetic energy index
+ idx(4) = poidx !surface potential energy index
+ str(1) = "(total )"
+ str(2) = "(enthalpy )"
+ str(3) = "(kinetic )"
+ str(4) = "(srf potential)"
+ do i=1,4
+ !
+ ! CAM physics energy tendencies
+ !
+ call cam_budget_get_global('phAP-phBP',idx(i),dEdt_param_physE(i))
+ call cam_budget_get_global('phBP-phBF',idx(i),dEdt_efix_physE(i))
+ call cam_budget_get_global('phAM-phAP',idx(i),dEdt_dme_adjust_physE(i))
+ call cam_budget_get_global('phAP-phBF',idx(i),dEdt_param_efix_physE(i))
+ !
+ ! CAM physics energy tendencies using dycore energy formula scaling
+ ! temperature tendencies for consistency with CAM physics
+ !
+ call cam_budget_get_global('dyAP-dyBP',idx(i),dEdt_param_dynE(i))
+ call cam_budget_get_global('dyBP-dyBF',idx(i),dEdt_efix_dynE(i))
+ call cam_budget_get_global('dyAM-dyAP',idx(i),dEdt_dme_adjust_dynE(i))
+ call cam_budget_get_global('dyAP-dyBF',idx(i),dEdt_param_efix_dynE(i))
+ call cam_budget_get_global('dyAM-dyBF',idx(i),dEdt_phys_total_dynE(i))
+ call cam_budget_get_global('dyBF' ,idx(i),E_dyBF(i))!state beginning physics
+ !
+ ! CAM physics energy tendencies in dynamical core
+ !
+ call cam_budget_get_global('dBD-dAF',idx(i),dEdt_phys_total_in_dyn(i))
+ call cam_budget_get_global('dBF' ,idx(i),E_dBF(i)) !state passed to physics
+ end do
+
+ call cam_budget_get_global('dAD-dBD',teidx,dEdt_floating_dyn)
+ call cam_budget_get_global('dAR-dAD',teidx,dEdt_vert_remap)
+ dEdt_dycore_dyn = dEdt_floating_dyn+dEdt_vert_remap
+
+ call cam_budget_get_global('dCH-dBH',teidx,dEdt_del4)
+ call cam_budget_get_global('dAH-dCH',teidx,dEdt_del4_fric_heat)
+ call cam_budget_get_global('dAH-dBH',teidx,dEdt_del4_tot)
+ call cam_budget_get_global('dAS-dBS',teidx,dEdt_del2_sponge)
+ dEdt_del2_del4_tot = dEdt_del4_tot+dEdt_del2_sponge
+ dEdt_residual = dEdt_floating_dyn-dEdt_del2_del4_tot
+
+ write(iulog,*)" "
+ write(iulog,*)"======================================================================"
+ write(iulog,*)"Total energy diagnostics introduced in Lauritzen and Williamson (2019)"
+ write(iulog,*)"(DOI:10.1029/2018MS001549)"
+ write(iulog,*)"======================================================================"
+ write(iulog,*)" "
+ write(iulog,*)"Globally and vertically integrated total energy (E) diagnostics are"
+ write(iulog,*)"computed at various points in the physics and dynamics loops to compute"
+ write(iulog,*)"energy tendencies (dE/dt) and check for consistency (e.g., is E of"
+ write(iulog,*)"state passed to physics computed using dycore state variables the same"
+ write(iulog,*)"E of the state in the beginning of physics computed using the physics"
+ write(iulog,*)"representation of the state)"
+ write(iulog,*)" "
+ write(iulog,*)"Energy stages in physics:"
+ write(iulog,*)"-------------------------"
+ write(iulog,*)" "
+ write(iulog,*)" xxBF: state passed to parameterizations, before energy fixer"
+ write(iulog,*)" xxBP: after energy fixer, before parameterizations"
+ write(iulog,*)" xxAP: after last phys_update in parameterizations and state "
+ write(iulog,*)" saved for energy fixer"
+ write(iulog,*)" xxAM: after dry mass adjustment"
+ write(iulog,*)" history files saved off here"
+ write(iulog,*)" "
+ write(iulog,*)"where xx='ph','dy' "
+ write(iulog,*)" "
+ write(iulog,*)"Suffix ph is CAM physics total energy"
+ write(iulog,*)"(eq. 111 in Lauritzen et al. 2022; 10.1029/2022MS003117)"
+ write(iulog,*)" "
+ write(iulog,*)"Suffix dy is dycore energy computed in CAM physics using"
+ write(iulog,*)"CAM physics state variables"
+ write(iulog,*)" "
+ write(iulog,*)" "
+ write(iulog,*)"Energy stages in dynamics (specific to the SE dycore)"
+ write(iulog,*)"-----------------------------------------------------"
+ write(iulog,*)" "
+ write(iulog,*)"suffix (d)"
+ write(iulog,*)"dED: state from end of previous dynamics (= pBF + time sampling)"
+ write(iulog,*)" loop over vertical remapping and physics dribbling -------- (nsplit) -------"
+ write(iulog,*)" (dribbling and remapping always done together) |"
+ write(iulog,*)" dAF: state from previous remapping |"
+ write(iulog,*)" dBD: state after physics dribble, before dynamics |"
+ write(iulog,*)" loop over vertical Lagrangian dynamics --------rsplit------------- |"
+ write(iulog,*)" dynamics here | |"
+ write(iulog,*)" loop over hyperviscosity ----------hypervis_sub------------ | |"
+ write(iulog,*)" dBH state before hyperviscosity | | |"
+ write(iulog,*)" dCH state after hyperviscosity | | |"
+ write(iulog,*)" dAH state after hyperviscosity momentum heating | | |"
+ write(iulog,*)" end hyperviscosity loop ----------------------------------- | |"
+ write(iulog,*)" dBS state before del2 sponge | | |"
+ write(iulog,*)" dAS state after del2+mom heating sponge | | |"
+ write(iulog,*)" end of vertical Lagrangian dynamics loop ------------------------- |"
+ write(iulog,*)" dAD state after dynamics, before vertical remapping |"
+ write(iulog,*)" dAR state after vertical remapping |"
+ write(iulog,*)" end of remapping loop ------------------------------------------------------"
+ write(iulog,*)"dBF state passed to parameterizations = state after last remapping "
+ write(iulog,*)" "
+ write(iulog,*)" "
+ write(iulog,*)"FYI: all difference (diff) below are absolute normalized differences"
+ write(iulog,*)" "
+ write(iulog,*)"Consistency check 0:"
+ write(iulog,*)"--------------------"
+ write(iulog,*)" "
+ write(iulog,*)"For energetic consistency we require that dE/dt [W/m^2] from energy "
+ write(iulog,*)"fixer and all parameterizations computed using physics E and"
+ write(iulog,*)"dycore in physics E are the same! Checking:"
+ write(iulog,*)" "
+ write(iulog,*) " xx=ph xx=dy norm. diff."
+ write(iulog,*) " ----- ----- -----------"
+ do i=1,4
+ diff = abs_diff(dEdt_efix_physE(i),dEdt_efix_dynE(i),pf=pf)
+ write(iulog,fmt)"dE/dt energy fixer (xxBP-xxBF) ",str(i)," ",dEdt_efix_physE(i), " ", &
+ dEdt_efix_dynE(i)," ",diff,pf
+ diff = abs_diff(dEdt_param_physE(i),dEdt_param_dynE(i),pf=pf)
+ write(iulog,fmt)"dE/dt all parameterizations (xxAP-xxBP) ",str(i)," ",dEdt_param_physE(i)," ", &
+ dEdt_param_dynE(i)," ",diff,pf
+ write(iulog,*) " "
+ if (diff>eps) then
+ write(iulog,*)"FAIL"
+ call endrun(subname//"dE/dt's in physics inconsistent")
+ end if
+ end do
+ write(iulog,*)" "
+ write(iulog,*)" "
+ write(iulog,*)"dE/dt from dry-mass adjustment will differ if dynamics and physics use"
+ write(iulog,*)"different energy definitions! Checking:"
+ write(iulog,*)" "
+ write(iulog,*) " xx=ph xx=dy diff"
+ write(iulog,*) " ----- ----- ----"
+ do i=1,4
+ diff = dEdt_dme_adjust_physE(i)-dEdt_dme_adjust_dynE(i)
+ write(iulog,fmt)"dE/dt dry mass adjustment (xxAM-xxAP) ",str(i)," ",dEdt_dme_adjust_physE(i)," ", &
+ dEdt_dme_adjust_dynE(i)," ",diff
+ end do
+ write(iulog,*)" "
+ write(iulog,*)" "
+ !
+ ! these diagnostics only make sense time-step to time-step
+ !
+ write(iulog,*)" "
+ write(iulog,*)"Some energy budget observations:"
+ write(iulog,*)"--------------------------------"
+ write(iulog,*)" "
+ write(iulog,*)"Note that total energy fixer fixes:"
+ write(iulog,*) " "
+ write(iulog,*) "-dE/dt energy fixer(t=n) = dE/dt dry mass adjustment (t=n-1) +"
+ write(iulog,*) " dE/dt adiabatic dycore (t=n-1) +"
+ write(iulog,*) " dE/dt physics-dynamics coupling errors (t=n-1)"
+ write(iulog,*) " "
+ write(iulog,*) "(equation 23 in Lauritzen and Williamson (2019))"
+ write(iulog,*) " "
+
+ tmp = previous_dEdt_phys_dyn_coupl_err+previous_dEdt_adiabatic_dycore+previous_dEdt_dry_mass_adjust
+ diff = abs_diff(-dEdt_efix_dynE(1),tmp,pf)
+ if (.not.use_cslam) then
+ write(iulog,*) "Check if that is the case:", pf, diff
+ write(iulog,*) " "
+ if (abs(diff)>eps) then
+ write(iulog,*) "dE/dt energy fixer(t=n) = ",dEdt_efix_dynE(1)
+ write(iulog,*) "dE/dt dry mass adjustment (t=n-1) = ",previous_dEdt_dry_mass_adjust
+ write(iulog,*) "dE/dt adiabatic dycore (t=n-1) = ",previous_dEdt_adiabatic_dycore
+ write(iulog,*) "dE/dt physics-dynamics coupling errors (t=n-1) = ",previous_dEdt_phys_dyn_coupl_err
+ end if
+ else
+ previous_dEdt_phys_dyn_coupl_err = dEdt_efix_dynE(1)+previous_dEdt_dry_mass_adjust+previous_dEdt_adiabatic_dycore
+ write(iulog,*) "dE/dt energy fixer(t=n) = ",dEdt_efix_dynE(1)
+ write(iulog,*) "dE/dt dry mass adjustment (t=n-1) = ",previous_dEdt_dry_mass_adjust
+ write(iulog,*) "dE/dt adiabatic dycore (t=n-1) = ",previous_dEdt_adiabatic_dycore
+ write(iulog,*) "dE/dt physics-dynamics coupling errors (t=n-1) = ",previous_dEdt_phys_dyn_coupl_err
+ write(iulog,*) " "
+ write(iulog,*) "Note: when running CSLAM the physics-dynamics coupling error is diagnosed"
+ write(iulog,*) " (using equation above) rather than explicitly computed"
+ write(iulog,*) " "
+ write(iulog,*) " "
+ write(iulog,*) "Physics-dynamics coupling errors include: "
+ write(iulog,*) " "
+ write(iulog,*) " -dE/dt adiabatic dycore is computed on GLL grid;"
+ write(iulog,*) " error in mapping to physics grid"
+ write(iulog,*) " -dE/dt physics tendencies mapped to GLL grid"
+ write(iulog,*) " (tracer tendencies mapped non-conservatively!)"
+ write(iulog,*) " -dE/dt dynamics state mapped to GLL grid"
+ end if
+ write(iulog,*) ""
+ if (.not.use_cslam) then
+ dEdt_dycore_phys = -dEdt_efix_dynE(1)-previous_dEdt_phys_dyn_coupl_err-previous_dEdt_dry_mass_adjust
+ write(iulog,*) "Hence the dycore E dissipation estimated from energy fixer "
+ write(iulog,'(A39,F6.2,A6)') "based on previous time-step values is ",dEdt_dycore_phys," W/M^2"
+ write(iulog,*) " "
+ end if
+ write(iulog,*) " "
+ write(iulog,*) "-------------------------------------------------------------------"
+ write(iulog,*) " Consistency check 1: state passed to physics same as end dynamics?"
+ write(iulog,*) "-------------------------------------------------------------------"
+ write(iulog,*) " "
+ write(iulog,*) "Is globally integrated total energy of state at the end of dynamics (dBF)"
+ write(iulog,*) "and beginning of physics (using dynamics in physics energy; dyBF) the same?"
+ write(iulog,*) ""
+ if (.not.use_cslam) then
+ if (abs(E_dyBF(1))>eps) then
+ diff = abs_diff(E_dBF(1),E_dyBF(1))
+ if (abs(diff)eps) then
+ !
+ ! if errors print details
+ !
+ if (ftype==1) then
+ write(iulog,*) ""
+ write(iulog,*) " You are using ftype==1 so physics-dynamics coupling errors should be round-off!"
+ write(iulog,*) ""
+ write(iulog,*) " Because of failure provide detailed diagnostics below:"
+ write(iulog,*) ""
+ else
+ write(iulog,*) ""
+ write(iulog,*) " Since ftype<>1 there are physics dynamics coupling errors"
+ write(iulog,*) ""
+ write(iulog,*) " Break-down below:"
+ write(iulog,*) ""
+ end if
+
+ do i=1,4
+ write(iulog,*) str(i),":"
+ write(iulog,*) "======"
+ diff = abs_diff(dEdt_phys_total_dynE(i),dEdt_phys_total_in_dyn(i),pf=pf)
+ write(iulog,*) "dE/dt physics-dynamics coupling errors (diff) ",diff
+ write(iulog,*) "dE/dt physics total in dynamics (dBD-dAF) ",dEdt_phys_total_in_dyn(i)
+ write(iulog,*) "dE/dt physics total in physics (dyAM-dyBF) ",dEdt_phys_total_dynE(i)
+ write(iulog,*) " "
+ write(iulog,*) " physics total = parameterizations + efix + dry-mass adjustment"
+ write(iulog,*) " "
+ end do
+! Temporarily disable endrun until energy bias for consistancy check 2 is better understood.
+! if (ftype==1) then
+! call endrun(subname//"Physics-dynamics coupling error. See atm.log")
+! end if
+ end if
+ else
+ write(iulog,'(a47,F6.2,a6)')" dE/dt physics tendency in dynamics (dBD-dAF) ",dEdt_phys_total_in_dyn(1)," W/M^2"
+ write(iulog,'(a47,F6.2,a6)')" dE/dt physics tendency in physics (dyAM-dyBF) ",dEdt_phys_total_dynE(1)," W/M^2"
+ write(iulog,*)" "
+ write(iulog,*) " When runnig with a physics grid this consistency check does not make sense"
+ write(iulog,*) " since it is computed on the GLL grid whereas we enforce energy conservation"
+ write(iulog,*) " on the physics grid. To assess the errors of running dynamics on GLL"
+ write(iulog,*) " grid, tracers on CSLAM grid and physics on physics grid we use the energy"
+ write(iulog,*) " fixer check from above:"
+ write(iulog,*) " "
+ write(iulog,*) " dE/dt physics-dynamics coupling errors (t=n-1) =",previous_dEdt_phys_dyn_coupl_err
+ write(iulog,*) ""
+ end if
+ write(iulog,*)" "
+ write(iulog,*)"------------------------------------------------------------"
+ write(iulog,*)" SE dycore energy tendencies"
+ write(iulog,*)"------------------------------------------------------------"
+ write(iulog,*)" "
+ write(iulog,fmtf)" dE/dt dycore ",dEdt_dycore_dyn," W/M^2"
+ write(iulog,*)" "
+ write(iulog,*)"Adiabatic dynamics can be divided into quasi-horizontal and vertical remapping: "
+ write(iulog,*)" "
+ write(iulog,fmtf)" dE/dt floating dynamics (dAD-dBD) ",dEdt_floating_dyn," W/M^2"
+ write(iulog,fmtf)" dE/dt vertical remapping (dAR-dAD) ",dEdt_vert_remap," W/M^2"
+
+ write(iulog,*) " "
+ write(iulog,*) "Breakdown of floating dynamics:"
+ write(iulog,*) " "
+ write(iulog,fmtf)" dE/dt hypervis del4 (dCH-dBH) ",dEdt_del4, " W/M^2"
+ write(iulog,fmtf)" dE/dt hypervis frictional heating (dAH-dCH) ",dEdt_del4_fric_heat," W/M^2"
+ write(iulog,fmtf)" dE/dt hypervis del4 total (dAH-dBH) ",dEdt_del4_tot, " W/M^2"
+ write(iulog,fmtf)" dE/dt hypervis sponge del2 (dAS-dBS) ",dEdt_del2_sponge, " W/M^2"
+ write(iulog,fmtf)" dE/dt explicit diffusion total ",dEdt_del2_del4_tot, " W/M^2"
+ write(iulog,*) " "
+ write(iulog,fmtf)" dE/dt residual (time-truncation errors,...) ",dEdt_residual, " W/M^2"
+ write(iulog,*)" "
+ write(iulog,*)" "
+ write(iulog,*)"------------------------------------------------------------"
+ write(iulog,*)"Tracer mass budgets"
+ write(iulog,*)"------------------------------------------------------------"
+ write(iulog,*)" "
+ write(iulog,*)"Below the physics-dynamics coupling error is computed as "
+ write(iulog,*)"dMASS/dt physics tendency in dycore (dBD-dAF) minus"
+ write(iulog,*)"dMASS/dt total physics (pAM-pBF)"
+ write(iulog,*)" "
+ write(iulog,*)" "
+ do m_cnst=1,thermo_budget_num_vars
+ if (thermo_budget_vars_massv(m_cnst)) then
+ write(iulog,*)thermo_budget_vars_descriptor(m_cnst)
+ write(iulog,*)"------------------------------"
+ call cam_budget_get_global('phBP-phBF',m_cnst,dMdt_efix)
+ call cam_budget_get_global('phAM-phAP',m_cnst,dMdt_dme_adjust)
+ call cam_budget_get_global('phAP-phBP',m_cnst,dMdt_parameterizations)
+ call cam_budget_get_global('phAM-phBF',m_cnst,dMdt_phys_total)
+ !
+ ! total energy fixer should not affect mass - checking
+ !
+ if (abs(dMdt_efix)>eps_mass) then
+ write(iulog,*) "dMASS/dt energy fixer (pBP-pBF) ",dMdt_efix," Pa/m^2/s"
+ write(iulog,*) "ERROR: Mass not conserved in energy fixer. ABORT"
+ call endrun(subname//"Mass not conserved in energy fixer. See atm.log")
+ endif
+ !
+ ! dry-mass adjustmnt should not affect mass - checking
+ !
+ if (abs(dMdt_dme_adjust)>eps_mass) then
+ write(iulog,*)"dMASS/dt dry mass adjustment (pAM-pAP) ",dMdt_dme_adjust," Pa/m^2/s"
+ write(iulog,*) "ERROR: Mass not conserved in dry mass adjustment. ABORT"
+ call endrun(subname//"Mass not conserved in dry mass adjustment. See atm.log")
+ end if
+ !
+ ! all of the mass-tendency should come from parameterization - checking
+ !
+ if (abs(dMdt_parameterizations-dMdt_phys_total)>eps_mass) then
+ write(iulog,*) "Error: dMASS/dt parameterizations (pAP-pBP) .ne. dMASS/dt physics total (pAM-pBF)"
+ write(iulog,*) "dMASS/dt parameterizations (pAP-pBP) ",dMdt_parameterizations," Pa/m^2/s"
+ write(iulog,*) "dMASS/dt physics total (pAM-pBF) ",dMdt_phys_total," Pa/m^2/s"
+ call endrun(subname//"mass change not only due to parameterizations. See atm.log")
+ end if
+ write(iulog,*)" "
+ !
+ ! detailed mass budget in dynamical core
+ !
+ if (is_cam_budget('dAD').and.is_cam_budget('dBD').and.is_cam_budget('dAR').and.is_cam_budget('dCH')) then
+ call cam_budget_get_global('dAD-dBD',m_cnst,dMdt_floating_dyn)
+ call cam_budget_get_global('dAR-dAD',m_cnst,dMdt_vert_remap)
+ tmp = dMdt_floating_dyn+dMdt_vert_remap
+ diff = abs_diff(tmp,0.0_r8,pf=pf)
+ write(iulog,fmtm)" dMASS/dt total adiabatic dynamics ",diff,pf
+ !
+ ! check for mass-conservation in the adiabatic dynamical core -
+ ! if not conserved provide detailed break-down
+ !
+ if (abs(diff)>eps_mass) then
+ write(iulog,*) "Error: mass non-conservation in dynamical core"
+ write(iulog,*) "(detailed budget below)"
+ write(iulog,*) " "
+ write(iulog,*)"dMASS/dt 2D dynamics (dAD-dBD) ",dMdt_floating_dyn," Pa/m^2/s"
+ write(iulog,*)"dE/dt vertical remapping (dAR-dAD) ",dMdt_vert_remap
+ write(iulog,*)" "
+ write(iulog,*)"Breakdown of 2D dynamics:"
+ write(iulog,*)" "
+ call cam_budget_get_global('dAH-dCH',m_cnst,dMdt_del4_fric_heat)
+ call cam_budget_get_global('dAH-dBH',m_cnst,dMdt_del4_tot)
+ write(iulog,*)"dMASS/dt hypervis (dAH-dBH) ",dMdt_del4_tot," Pa/m^2/s"
+ write(iulog,*)"dMASS/dt frictional heating (dAH-dCH) ",dMdt_del4_fric_heat," Pa/m^2/s"
+ dMdt_residual = dMdt_floating_dyn-dMdt_del4_tot
+ write(iulog,*)"dMASS/dt residual (time truncation errors)",dMdt_residual," Pa/m^2/s"
+ end if
+ end if
+ if (is_cam_budget('dBD').and.is_cam_budget('dAF')) then
+ !
+ ! check if mass change in physics is the same as dynamical core
+ !
+ call cam_budget_get_global('dBD-dAF',m_cnst,dMdt_phys_total_in_dyn)
+ dMdt_PDC = dMdt_phys_total-dMdt_phys_total_in_dyn
+ write(iulog,fmtm)" Mass physics-dynamics coupling error ",dMdt_PDC," Pa/m^2/s"
+ write(iulog,*)" "
+ if (abs(dMdt_PDC)>eps_mass) then
+ write(iulog,fmtm)" dMASS/dt physics tendency in dycore (dBD-dAF) ",dMdt_phys_total_in_dyn," Pa/m^2/s"
+ write(iulog,fmtm)" dMASS/dt total physics ",dMdt_phys_total," Pa/m^2/s"
+ end if
+ end if
+ end if
+ end do
+ !
+ ! save adiabatic dycore dE/dt and dry-mass adjustment to avoid samping error
+ !
+ previous_dEdt_adiabatic_dycore = dEdt_dycore_dyn
+ previous_dEdt_dry_mass_adjust = dEdt_dme_adjust_dynE(1)
+ end if
+end subroutine print_budget
+!=========================================================================================
+function abs_diff(a,b,pf)
+ real(r8), intent(in) :: a,b
+ character(LEN=5), optional, intent(out):: pf
+ real(r8) :: abs_diff
+ if (abs(b)>eps) then
+ abs_diff = abs((b-a)/b)
+ else
+ abs_diff = abs(b-a)
+ end if
+ If (present(pf)) then
+ if (abs_diff>eps) then
+ pf = ' FAIL'
+ else
+ pf = ' PASS'
+ end if
+ end if
+end function abs_diff
+end module dycore_budget
diff --git a/src/dynamics/se/dyn_comp.F90 b/src/dynamics/se/dyn_comp.F90
index f0d42d6ed2..6504eb75cd 100644
--- a/src/dynamics/se/dyn_comp.F90
+++ b/src/dynamics/se/dyn_comp.F90
@@ -15,7 +15,7 @@ module dyn_comp
ini_grid_hdim_name
use cam_grid_support, only: cam_grid_id, cam_grid_get_gcid, &
- cam_grid_dimensions, cam_grid_get_dim_names, &
+ cam_grid_dimensions, &
cam_grid_get_latvals, cam_grid_get_lonvals, &
max_hcoordname_len
use cam_map_utils, only: iMap
@@ -38,8 +38,8 @@ module dyn_comp
use parallel_mod, only: par
use hybrid_mod, only: hybrid_t
-use dimensions_mod, only: nelemd, nlev, np, npsq, ntrac, nc, fv_nphys, &
- qsize
+use dimensions_mod, only: nelemd, nlev, np, npsq, ntrac, nc, fv_nphys
+use dimensions_mod, only: qsize, use_cslam
use element_mod, only: element_t, elem_state_t
use fvm_control_volume_mod, only: fvm_struct
use time_mod, only: nsplit
@@ -84,6 +84,7 @@ module dyn_comp
real(r8), parameter :: rad2deg = 180.0_r8 / pi
real(r8), parameter :: deg2rad = pi / 180.0_r8
+real(r8), parameter :: rarea_sphere = 1.0_r8 / (4.0_r8*PI)
!===============================================================================
contains
@@ -106,13 +107,12 @@ subroutine dyn_readnl(NLFileName)
use control_mod, only: vert_remap_uvTq_alg, vert_remap_tracer_alg
use control_mod, only: tstep_type, rk_stage_user
use control_mod, only: ftype, limiter_option, partmethod
- use control_mod, only: topology, phys_dyn_cp, variable_nsplit
+ use control_mod, only: topology, variable_nsplit
use control_mod, only: fine_ne, hypervis_power, hypervis_scaling
use control_mod, only: max_hypervis_courant, statediag_numtrac,refined_mesh
use control_mod, only: molecular_diff
use control_mod, only: sponge_del4_nu_div_fac, sponge_del4_nu_fac, sponge_del4_lev
use dimensions_mod, only: ne, npart
- use dimensions_mod, only: lcp_moist
use dimensions_mod, only: large_Courant_incr
use dimensions_mod, only: fvm_supercycling, fvm_supercycling_jet
use dimensions_mod, only: kmin_jet, kmax_jet
@@ -120,13 +120,11 @@ subroutine dyn_readnl(NLFileName)
use parallel_mod, only: initmpi
use thread_mod, only: initomp, max_num_threads
use thread_mod, only: horz_num_threads, vert_num_threads, tracer_num_threads
- use physconst, only: rearth
! Dummy argument
character(len=*), intent(in) :: NLFileName
! Local variables
integer :: unitn, ierr,k
- real(r8) :: uniform_res_hypervis_scaling,nu_fac
! SE Namelist variables
integer :: se_fine_ne
@@ -162,14 +160,12 @@ subroutine dyn_readnl(NLFileName)
integer :: se_horz_num_threads
integer :: se_vert_num_threads
integer :: se_tracer_num_threads
- logical :: se_lcp_moist
logical :: se_write_restart_unstruct
logical :: se_large_Courant_incr
integer :: se_fvm_supercycling
integer :: se_fvm_supercycling_jet
integer :: se_kmin_jet
integer :: se_kmax_jet
- integer :: se_phys_dyn_cp
real(r8) :: se_molecular_diff
namelist /dyn_se_inparm/ &
@@ -209,14 +205,12 @@ subroutine dyn_readnl(NLFileName)
se_horz_num_threads, &
se_vert_num_threads, &
se_tracer_num_threads, &
- se_lcp_moist, &
se_write_restart_unstruct, &
se_large_Courant_incr, &
se_fvm_supercycling, &
se_fvm_supercycling_jet, &
se_kmin_jet, &
se_kmax_jet, &
- se_phys_dyn_cp, &
se_molecular_diff
!--------------------------------------------------------------------------
@@ -284,14 +278,12 @@ subroutine dyn_readnl(NLFileName)
call MPI_bcast(se_horz_num_threads, 1, MPI_integer, masterprocid, mpicom,ierr)
call MPI_bcast(se_vert_num_threads, 1, MPI_integer, masterprocid, mpicom,ierr)
call MPI_bcast(se_tracer_num_threads, 1, MPI_integer, masterprocid, mpicom,ierr)
- call MPI_bcast(se_lcp_moist, 1, mpi_logical, masterprocid, mpicom, ierr)
call MPI_bcast(se_write_restart_unstruct, 1, mpi_logical, masterprocid, mpicom, ierr)
call MPI_bcast(se_large_Courant_incr, 1, mpi_logical, masterprocid, mpicom, ierr)
call MPI_bcast(se_fvm_supercycling, 1, mpi_integer, masterprocid, mpicom, ierr)
call MPI_bcast(se_fvm_supercycling_jet, 1, mpi_integer, masterprocid, mpicom, ierr)
call MPI_bcast(se_kmin_jet, 1, mpi_integer, masterprocid, mpicom, ierr)
call MPI_bcast(se_kmax_jet, 1, mpi_integer, masterprocid, mpicom, ierr)
- call MPI_bcast(se_phys_dyn_cp, 1, mpi_integer, masterprocid, mpicom, ierr)
call MPI_bcast(se_molecular_diff, 1, mpi_real8, masterprocid, mpicom, ierr)
if (se_npes <= 0) then
@@ -353,26 +345,26 @@ subroutine dyn_readnl(NLFileName)
vert_remap_uvTq_alg = set_vert_remap(se_vert_remap_T, se_vert_remap_uvTq_alg)
vert_remap_tracer_alg = set_vert_remap(se_vert_remap_T, se_vert_remap_tracer_alg)
fv_nphys = se_fv_nphys
- lcp_moist = se_lcp_moist
large_Courant_incr = se_large_Courant_incr
fvm_supercycling = se_fvm_supercycling
fvm_supercycling_jet = se_fvm_supercycling_jet
kmin_jet = se_kmin_jet
kmax_jet = se_kmax_jet
variable_nsplit = .false.
- phys_dyn_cp = se_phys_dyn_cp
molecular_diff = se_molecular_diff
if (fv_nphys > 0) then
! Use finite volume physics grid and CSLAM for tracer advection
nphys_pts = fv_nphys*fv_nphys
qsize = thermodynamic_active_species_num ! number tracers advected by GLL
- ntrac = pcnst ! number tracers advected by CSLAM
+ ntrac = pcnst ! number tracers advected by CSLAM
+ use_cslam = .true.
else
! Use GLL grid for physics and tracer advection
nphys_pts = npsq
qsize = pcnst
ntrac = 0
+ use_cslam = .false.
end if
if (rsplit < 1) then
@@ -431,7 +423,6 @@ subroutine dyn_readnl(NLFileName)
end if
write(iulog, '(a,i0)') 'dyn_readnl: se_npes = ',se_npes
write(iulog, '(a,i0)') 'dyn_readnl: se_nsplit = ',se_nsplit
- write(iulog, '(a,i0)') 'dyn_readnl: se_phys_dyn_cp = ',se_phys_dyn_cp
!
! se_nu<0 then coefficients are set automatically in module global_norms_mod
!
@@ -451,7 +442,6 @@ subroutine dyn_readnl(NLFileName)
write(iulog, '(a,a)') 'dyn_readnl: se_vert_remap_T = ',trim(se_vert_remap_T)
write(iulog, '(a,a)') 'dyn_readnl: se_vert_remap_uvTq_alg = ',trim(se_vert_remap_uvTq_alg)
write(iulog, '(a,a)') 'dyn_readnl: se_vert_remap_tracer_alg = ',trim(se_vert_remap_tracer_alg)
- write(iulog, '(a,l4)') 'dyn_readnl: lcp_moist = ',lcp_moist
write(iulog, '(a,i0)') 'dyn_readnl: se_fvm_supercycling = ',fvm_supercycling
write(iulog, '(a,i0)') 'dyn_readnl: se_fvm_supercycling_jet = ',fvm_supercycling_jet
write(iulog, '(a,i0)') 'dyn_readnl: se_kmin_jet = ',kmin_jet
@@ -584,7 +574,7 @@ subroutine dyn_init(dyn_in, dyn_out)
use prim_advance_mod, only: prim_advance_init
use dyn_grid, only: elem, fvm
use cam_pio_utils, only: clean_iodesc_list
- use physconst, only: rair, cpair, pstd
+ use physconst, only: cpair, pstd
use air_composition, only: thermodynamic_active_species_num, thermodynamic_active_species_idx
use air_composition, only: thermodynamic_active_species_idx_dycore
use air_composition, only: thermodynamic_active_species_liq_idx,thermodynamic_active_species_ice_idx
@@ -595,36 +585,37 @@ subroutine dyn_init(dyn_in, dyn_out)
use thread_mod, only: horz_num_threads
use hybrid_mod, only: get_loop_ranges, config_thread_region
- use dimensions_mod, only: nu_scale_top, nu_lev, nu_div_lev
+ use dimensions_mod, only: nu_scale_top
use dimensions_mod, only: ksponge_end, kmvis_ref, kmcnd_ref,rho_ref,km_sponge_factor
use dimensions_mod, only: cnst_name_gll, cnst_longname_gll
use dimensions_mod, only: irecons_tracer_lev, irecons_tracer, kord_tr, kord_tr_cslam
use prim_driver_mod, only: prim_init2
- use time_mod, only: time_at
- use control_mod, only: runtype, molecular_diff, nu_top
+ use control_mod, only: molecular_diff, nu_top
use test_fvm_mapping, only: test_mapping_addfld
use phys_control, only: phys_getopts
use cam_thermo, only: get_molecular_diff_coef_reference
use control_mod, only: vert_remap_uvTq_alg, vert_remap_tracer_alg
use std_atm_profile, only: std_atm_height
use dyn_tests_utils, only: vc_dycore, vc_dry_pressure, string_vc, vc_str_lgth
+ use cam_budget, only: cam_budget_em_snapshot, cam_budget_em_register, thermo_budget_history
+
! Dummy arguments:
type(dyn_import_t), intent(out) :: dyn_in
type(dyn_export_t), intent(out) :: dyn_out
! Local variables
- integer :: ithr, nets, nete, ie, k, kmol_end, mfound
+ integer :: nets, nete, ie, k, kmol_end, mfound
real(r8), parameter :: Tinit = 300.0_r8
real(r8) :: press(1), ptop, tref,z(1)
type(hybrid_t) :: hybrid
- integer :: ixcldice, ixcldliq, ixrain, ixsnow, ixgraupel
+ integer :: ixcldice, ixcldliq
integer :: m_cnst, m
! variables for initializing energy and axial angular momentum diagnostics
- integer, parameter :: num_stages = 12, num_vars = 8
- character (len = 3), dimension(num_stages) :: stage = (/"dED","dAF","dBD","dAD","dAR","dBF","dBH","dCH","dAH",'dBS','dAS','p2d'/)
+ integer, parameter :: num_stages = 12
+ character (len = 4), dimension(num_stages) :: stage = (/"dED","dAF","dBD","dAD","dAR","dBF","dBH","dCH","dAH","dBS","dAS","p2d"/)
character (len = 70),dimension(num_stages) :: stage_txt = (/&
" end of previous dynamics ",& !dED
" from previous remapping or state passed to dynamics",& !dAF - state in beginning of nsplit loop
@@ -639,28 +630,11 @@ subroutine dyn_init(dyn_in, dyn_out)
" state after sponge layer diffusion ",& !dAS - state after sponge del2
" phys2dyn mapping errors (requires ftype-1) " & !p2d - for assessing phys2dyn mapping errors
/)
- character (len = 2) , dimension(num_vars) :: vars = (/"WV" ,"WL" ,"WI" ,"SE" ,"KE" ,"MR" ,"MO" ,"TT" /)
- !if ntrac>0 then tracers should be output on fvm grid but not energy (SE+KE) and AAM diags
- logical , dimension(num_vars) :: massv = (/.true.,.true.,.true.,.false.,.false.,.false.,.false.,.false./)
- character (len = 70) , dimension(num_vars) :: vars_descriptor = (/&
- "Total column water vapor ",&
- "Total column cloud water ",&
- "Total column cloud ice ",&
- "Total column static energy ",&
- "Total column kinetic energy ",&
- "Total column wind axial angular momentum",&
- "Total column mass axial angular momentum",&
- "Total column test tracer "/)
- character (len = 14), dimension(num_vars) :: &
- vars_unit = (/&
- "kg/m2 ","kg/m2 ","kg/m2 ","J/m2 ",&
- "J/m2 ","kg*m2/s*rad2 ","kg*m2/s*rad2 ","kg/m2 "/)
-
- integer :: istage, ivars
- character (len=108) :: str1, str2, str3
+
+ integer :: istage
character (len=vc_str_lgth) :: vc_str
- logical :: history_budget ! output tendencies and state variables for budgets
+ logical :: history_budget ! output tendencies and state variables for budgets
integer :: budget_hfile_num
character(len=*), parameter :: sub = 'dyn_init'
@@ -678,7 +652,7 @@ subroutine dyn_init(dyn_in, dyn_out)
allocate(kord_tr(qsize))
kord_tr(:) = vert_remap_tracer_alg
- if (ntrac>0) then
+ if (use_cslam) then
allocate(kord_tr_cslam(ntrac))
kord_tr_cslam(:) = vert_remap_tracer_alg
end if
@@ -696,7 +670,7 @@ subroutine dyn_init(dyn_in, dyn_out)
! CSLAM tracers are always indexed as in physics
! of no CSLAM then SE tracers are always indexed as in physics
!
- if (ntrac>0) then
+ if (use_cslam) then
!
! note that in this case qsize = thermodynamic_active_species_num
!
@@ -720,7 +694,7 @@ subroutine dyn_init(dyn_in, dyn_out)
end do
do m=1,thermodynamic_active_species_liq_num
- if (ntrac>0) then
+ if (use_cslam) then
do mfound=1,qsize
if (TRIM(cnst_name(thermodynamic_active_species_liq_idx(m)))==TRIM(cnst_name_gll(mfound))) then
thermodynamic_active_species_liq_idx_dycore(m) = mfound
@@ -734,7 +708,7 @@ subroutine dyn_init(dyn_in, dyn_out)
end if
end do
do m=1,thermodynamic_active_species_ice_num
- if (ntrac>0) then
+ if (use_cslam) then
do mfound=1,qsize
if (TRIM(cnst_name(thermodynamic_active_species_ice_idx(m)))==TRIM(cnst_name_gll(mfound))) then
thermodynamic_active_species_ice_idx_dycore(m) = mfound
@@ -880,7 +854,7 @@ subroutine dyn_init(dyn_in, dyn_out)
call addfld ('FT', (/ 'lev' /), 'A', 'K/s', 'Temperature forcing term on GLL grid',gridname='GLL')
! Tracer forcing on fvm (CSLAM) grid and internal CSLAM pressure fields
- if (ntrac>0) then
+ if (use_cslam) then
do m = 1, ntrac
call addfld (trim(cnst_name(m))//'_fvm', (/ 'lev' /), 'I', 'kg/kg', &
trim(cnst_longname(m)), gridname='FVM')
@@ -902,7 +876,7 @@ subroutine dyn_init(dyn_in, dyn_out)
! Energy diagnostics and axial angular momentum diagnostics
call addfld ('ABS_dPSdt', horiz_only, 'A', 'Pa/s', 'Absolute surface pressure tendency',gridname='GLL')
- if (ntrac>0) then
+ if (use_cslam) then
#ifdef waccm_debug
call addfld ('CSLAM_gamma', (/ 'lev' /), 'A', '', 'Courant number from CSLAM', gridname='FVM')
#endif
@@ -917,23 +891,43 @@ subroutine dyn_init(dyn_in, dyn_out)
call addfld ('TT_PDC', horiz_only, 'A', 'kg/m2','Total column test tracer lost in physics-dynamics coupling',gridname='GLL')
end if
- do istage = 1, num_stages
- do ivars=1, num_vars
- write(str1,*) TRIM(ADJUSTL(vars(ivars))),"_",TRIM(ADJUSTL(stage(istage)))
- write(str2,*) TRIM(ADJUSTL(vars_descriptor(ivars)))," ", &
- TRIM(ADJUSTL(stage_txt(istage)))
- write(str3,*) TRIM(ADJUSTL(vars_unit(ivars)))
- if (ntrac>0.and.massv(ivars)) then
- call addfld (TRIM(ADJUSTL(str1)), horiz_only, 'A', TRIM(ADJUSTL(str3)),TRIM(ADJUSTL(str2)),gridname='FVM')
- else
- call addfld (TRIM(ADJUSTL(str1)), horiz_only, 'A', TRIM(ADJUSTL(str3)),TRIM(ADJUSTL(str2)),gridname='GLL')
- end if
+ if (thermo_budget_history) then
+ ! Register stages for budgets
+ do istage = 1, num_stages
+ call cam_budget_em_snapshot(TRIM(ADJUSTL(stage(istage))), 'dyn', &
+ longname=TRIM(ADJUSTL(stage_txt(istage))))
end do
- end do
+ !
+ ! Register tendency (difference) budgets
+ !
+ call cam_budget_em_register('dEdt_floating_dyn' ,'dAD','dBD','dyn','dif', &
+ longname="dE/dt floating dynamics (dAD-dBD)" )
+ call cam_budget_em_register('dEdt_vert_remap' ,'dAR','dAD','dyn','dif', &
+ longname="dE/dt vertical remapping (dAR-dAD)" )
+ call cam_budget_em_register('dEdt_phys_tot_in_dyn','dBD','dAF','dyn','dif', &
+ longname="dE/dt physics tendency in dynamics (dBD-dAF)" )
+ call cam_budget_em_register('dEdt_del4' ,'dCH','dBH','dyn','dif', &
+ longname="dE/dt del4 (dCH-dBH)" )
+ call cam_budget_em_register('dEdt_del4_fric_heat','dAH','dCH','dyn','dif', &
+ longname="dE/dt del4 frictional heating (dAH-dCH)" )
+ call cam_budget_em_register('dEdt_del4_tot' ,'dAH','dBH','dyn','dif', &
+ longname="dE/dt del4 + del4 frictional heating (dAH-dBH)" )
+ call cam_budget_em_register('dEdt_del2_sponge' ,'dAS','dBS','dyn','dif', &
+ longname="dE/dt del2 sponge (dAS-dBS)" )
+ !
+ ! Register derived budgets
+ !
+ call cam_budget_em_register('dEdt_dycore' ,'dEdt_floating_dyn','dEdt_vert_remap' ,'dyn','sum', &
+ longname="dE/dt adiabatic dynamics" )
+ call cam_budget_em_register('dEdt_del2_del4_tot' ,'dEdt_del4_tot' ,'dEdt_del2_sponge' ,'dyn','sum', &
+ longname="dE/dt explicit diffusion total" )
+ call cam_budget_em_register('dEdt_residual' ,'dEdt_floating_dyn','dEdt_del2_del4_tot','dyn','dif',&
+ longname="dE/dt residual (dEdt_floating_dyn-dEdt_del2_del4_tot)" )
+ end if
!
! add dynamical core tracer tendency output
!
- if (ntrac>0) then
+ if (use_cslam) then
do m = 1, pcnst
call addfld(tottnam(m),(/ 'lev' /),'A','kg/kg/s',trim(cnst_name(m))//' horz + vert', &
gridname='FVM')
@@ -961,7 +955,6 @@ end subroutine dyn_init
subroutine dyn_run(dyn_state)
use air_composition, only: thermodynamic_active_species_num, dry_air_species_num
use air_composition, only: thermodynamic_active_species_idx_dycore
- use prim_advance_mod, only: calc_tot_energy_dynamics
use prim_driver_mod, only: prim_run_subcycle
use dimensions_mod, only: cnst_name_gll
use time_mod, only: tstep, nsplit, timelevel_qdp
@@ -975,7 +968,7 @@ subroutine dyn_run(dyn_state)
type(hybrid_t) :: hybrid
integer :: tl_f
integer :: n
- integer :: nets, nete, ithr
+ integer :: nets, nete
integer :: i, ie, j, k, m, nq, m_cnst
integer :: n0_qdp, nsplit_local
logical :: ldiag
@@ -1078,7 +1071,7 @@ subroutine dyn_run(dyn_state)
end if
- if (ntrac > 0) then
+ if (use_cslam) then
do ie = nets, nete
do m = 1, ntrac
do k = 1, nlev
@@ -1126,8 +1119,6 @@ subroutine dyn_run(dyn_state)
end do
end if
-
- call calc_tot_energy_dynamics(dyn_state%elem,dyn_state%fvm, nets, nete, TimeLevel%n0, n0_qdp,'dBF')
!$OMP END PARALLEL
if (ldiag) then
@@ -1157,7 +1148,7 @@ subroutine read_inidat(dyn_in)
use element_mod, only: timelevels
use fvm_mapping, only: dyn2fvm_mass_vars
- use control_mod, only: runtype,initial_global_ave_dry_ps
+ use control_mod, only: runtype
use prim_driver_mod, only: prim_set_dry_mass
use air_composition, only: thermodynamic_active_species_idx
use cam_initfiles, only: scale_dry_air_mass
@@ -1180,8 +1171,8 @@ subroutine read_inidat(dyn_in)
logical, allocatable :: pmask(:) ! (npsq*nelemd) unique grid vals
character(len=max_hcoordname_len):: grid_name
- real(r8), allocatable :: latvals(:),latvals_phys(:)
- real(r8), allocatable :: lonvals(:),lonvals_phys(:)
+ real(r8), allocatable :: latvals(:)
+ real(r8), allocatable :: lonvals(:)
real(r8), pointer :: latvals_deg(:)
real(r8), pointer :: lonvals_deg(:)
@@ -1193,9 +1184,6 @@ subroutine read_inidat(dyn_in)
integer :: kptr, m_cnst
type(EdgeBuffer_t) :: edge
- character(len=max_fieldname_len) :: varname
- integer :: ierr
-
integer :: rndm_seed_sz
integer, allocatable :: rndm_seed(:)
integer :: dims(2)
@@ -1206,10 +1194,6 @@ subroutine read_inidat(dyn_in)
character(len=128) :: errmsg
character(len=*), parameter :: sub='READ_INIDAT'
- ! fvm vars
- real(r8), allocatable :: inv_dp_darea_fvm(:,:,:)
- real(r8) :: min_val, max_val
-
real(r8) :: dp_tmp, pstmp(np,np)
! Variables for analytic initial conditions
@@ -1701,7 +1685,7 @@ subroutine read_inidat(dyn_in)
! if CSLAM active then we only advect water vapor and condensate
! loading tracers in state%qdp
- if (ntrac > 0) then
+ if (use_cslam) then
do ie = 1, nelemd
do nq = 1, thermodynamic_active_species_num
m_cnst = thermodynamic_active_species_idx(nq)
@@ -1732,7 +1716,7 @@ subroutine read_inidat(dyn_in)
! interpolate fvm tracers and fvm pressure variables
- if (ntrac > 0) then
+ if (use_cslam) then
if (par%masterproc) then
write(iulog,*) 'Initializing dp_fvm from spectral element dp'
end if
@@ -1754,7 +1738,7 @@ subroutine read_inidat(dyn_in)
write(iulog,*) 'FVM tracers, FVM pressure variables and se_area_sphere initialized.'
end if
- end if ! (ntrac > 0)
+ end if ! (use_cslam)
! Cleanup
deallocate(qtmp)
@@ -2021,7 +2005,6 @@ subroutine check_file_layout(file, elem, dyn_cols, file_desc, dyn_ok)
integer :: ncol_did, ncol_size
integer :: ierr
integer :: ie, i, j
- integer :: grid_id
integer :: indx
real(r8) :: dbuf2(npsq, nelemd)
logical :: found
@@ -2300,7 +2283,7 @@ subroutine write_dyn_vars(dyn_out)
integer :: ie, m
!----------------------------------------------------------------------------
- if (ntrac > 0) then
+ if (use_cslam) then
do ie = 1, nelemd
call outfld('dp_fvm', RESHAPE(dyn_out%fvm(ie)%dp_fvm(1:nc,1:nc,:), &
(/nc*nc,nlev/)), nc*nc, ie)
diff --git a/src/dynamics/se/dyn_grid.F90 b/src/dynamics/se/dyn_grid.F90
index 77f3a27f2f..766fb893d7 100644
--- a/src/dynamics/se/dyn_grid.F90
+++ b/src/dynamics/se/dyn_grid.F90
@@ -41,7 +41,7 @@ module dyn_grid
use pio, only: file_desc_t
use dimensions_mod, only: globaluniquecols, nelem, nelemd, nelemdmax
-use dimensions_mod, only: ne, np, npsq, fv_nphys, nlev, ntrac
+use dimensions_mod, only: ne, np, npsq, fv_nphys, nlev, use_cslam
use element_mod, only: element_t
use fvm_control_volume_mod, only: fvm_struct
use hybvcoord_mod, only: hvcoord_t
@@ -59,7 +59,6 @@ module dyn_grid
integer, parameter :: fvm_decomp = 102 ! The FVM (CSLAM) grid
integer, parameter :: physgrid_d = 103 ! physics grid on dynamics decomp
integer, parameter :: ini_decomp = 104 ! alternate dynamics grid for reading initial file
-
character(len=3), protected :: ini_grid_name
! Name of horizontal grid dimension in initial file.
@@ -733,6 +732,7 @@ subroutine define_cam_grids()
use cam_grid_support, only: horiz_coord_t, horiz_coord_create
use cam_grid_support, only: cam_grid_register, cam_grid_attribute_register
use dimensions_mod, only: nc
+ use shr_const_mod, only: PI => SHR_CONST_PI
! Local variables
integer :: i, ii, j, k, ie, mapind
@@ -744,22 +744,40 @@ subroutine define_cam_grids()
real(r8), allocatable :: pelat_deg(:) ! pe-local latitudes (degrees)
real(r8), allocatable :: pelon_deg(:) ! pe-local longitudes (degrees)
- real(r8), pointer :: pearea(:) => null() ! pe-local areas
- real(r8) :: areaw(np,np)
+ real(r8), pointer :: pearea(:) ! pe-local areas
+ real(r8), pointer :: pearea_wt(:) ! pe-local areas normalized for unit sphere
integer(iMap) :: fdofP_local(npsq,nelemd) ! pe-local map for dynamics decomp
integer(iMap), allocatable :: pemap(:) ! pe-local map for PIO decomp
integer :: ncols_fvm, ngcols_fvm
real(r8), allocatable :: fvm_coord(:)
real(r8), pointer :: fvm_area(:)
+ real(r8), pointer :: fvm_areawt(:)
integer(iMap), pointer :: fvm_map(:)
integer :: ncols_physgrid, ngcols_physgrid
real(r8), allocatable :: physgrid_coord(:)
real(r8), pointer :: physgrid_area(:)
+ real(r8), pointer :: physgrid_areawt(:)
integer(iMap), pointer :: physgrid_map(:)
+
+ real(r8), parameter :: rarea_unit_sphere = 1.0_r8 / (4.0_r8*PI)
+
!----------------------------------------------------------------------------
+ !-----------------------
+ ! initialize pointers to null
+ !-----------------------
+ nullify(pearea_wt)
+ nullify(pearea)
+ nullify(fvm_area)
+ nullify(fvm_areawt)
+ nullify(fvm_map)
+ nullify(physgrid_area)
+ nullify(physgrid_areawt)
+ nullify(physgrid_map)
+ nullify(grid_map)
+
!-----------------------
! Create GLL grid object
!-----------------------
@@ -777,16 +795,17 @@ subroutine define_cam_grids()
allocate(pelat_deg(np*np*nelemd))
allocate(pelon_deg(np*np*nelemd))
allocate(pearea(np*np*nelemd))
+ allocate(pearea_wt(np*np*nelemd))
allocate(pemap(np*np*nelemd))
pemap = 0_iMap
ii = 1
do ie = 1, nelemd
- areaw = 1.0_r8 / elem(ie)%rspheremp(:,:)
- pearea(ii:ii+npsq-1) = reshape(areaw, (/ np*np /))
pemap(ii:ii+npsq-1) = fdofp_local(:,ie)
do j = 1, np
do i = 1, np
+ pearea(ii) = elem(ie)%mp(i,j)*elem(ie)%metdet(i,j)
+ pearea_wt(ii) = pearea(ii)*rarea_unit_sphere
pelat_deg(ii) = elem(ie)%spherep(i,j)%lat * rad2deg
pelon_deg(ii) = elem(ie)%spherep(i,j)%lon * rad2deg
ii = ii + 1
@@ -832,6 +851,8 @@ subroutine define_cam_grids()
grid_map, block_indexed=.false., unstruct=.true.)
call cam_grid_attribute_register('GLL', 'area_d', 'gll grid areas', &
'ncol_d', pearea, map=pemap)
+ call cam_grid_attribute_register('GLL', 'area_weight_gll', 'gll grid area weights', &
+ 'ncol_d', pearea_wt, map=pemap)
call cam_grid_attribute_register('GLL', 'np', '', np)
call cam_grid_attribute_register('GLL', 'ne', '', ne)
@@ -848,6 +869,8 @@ subroutine define_cam_grids()
grid_map, block_indexed=.false., unstruct=.true.)
call cam_grid_attribute_register('INI', 'area', 'ini grid areas', &
'ncol', pearea, map=pemap)
+ call cam_grid_attribute_register('INI', 'area_weight_ini', 'ini grid area weights', &
+ 'ncol', pearea_wt, map=pemap)
ini_grid_name = 'INI'
else
@@ -865,6 +888,7 @@ subroutine define_cam_grids()
! to that memory. It can be nullified since the attribute object has
! the reference.
nullify(pearea)
+ nullify(pearea_wt)
! grid_map cannot be deallocated as the cam_filemap_t object just points
! to it. It can be nullified.
@@ -874,13 +898,14 @@ subroutine define_cam_grids()
! Create FVM grid object for CSLAM
!---------------------------------
- if (ntrac > 0) then
+ if (use_cslam) then
ncols_fvm = nc * nc * nelemd
ngcols_fvm = nc * nc * nelem_d
allocate(fvm_coord(ncols_fvm))
allocate(fvm_map(ncols_fvm))
allocate(fvm_area(ncols_fvm))
+ allocate(fvm_areawt(ncols_fvm))
do ie = 1, nelemd
k = 1
@@ -890,6 +915,7 @@ subroutine define_cam_grids()
fvm_coord(mapind) = fvm(ie)%center_cart(i,j)%lon*rad2deg
fvm_map(mapind) = k + ((elem(ie)%GlobalId-1) * nc * nc)
fvm_area(mapind) = fvm(ie)%area_sphere(i,j)
+ fvm_areawt(mapind) = fvm_area(mapind)*rarea_unit_sphere
k = k + 1
end do
end do
@@ -930,12 +956,15 @@ subroutine define_cam_grids()
grid_map, block_indexed=.false., unstruct=.true.)
call cam_grid_attribute_register('FVM', 'area_fvm', 'fvm grid areas', &
'ncol_fvm', fvm_area, map=fvm_map)
+ call cam_grid_attribute_register('FVM', 'area_weight_fvm', 'fvm grid area weights', &
+ 'ncol_fvm', fvm_areawt, map=fvm_map)
call cam_grid_attribute_register('FVM', 'nc', '', nc)
call cam_grid_attribute_register('FVM', 'ne', '', ne)
deallocate(fvm_coord)
deallocate(fvm_map)
nullify(fvm_area)
+ nullify(fvm_areawt)
nullify(grid_map)
end if
@@ -951,6 +980,7 @@ subroutine define_cam_grids()
allocate(physgrid_coord(ncols_physgrid))
allocate(physgrid_map(ncols_physgrid))
allocate(physgrid_area(ncols_physgrid))
+ allocate(physgrid_areawt(ncols_physgrid))
do ie = 1, nelemd
k = 1
@@ -960,6 +990,7 @@ subroutine define_cam_grids()
physgrid_coord(mapind) = fvm(ie)%center_cart_physgrid(i,j)%lon*rad2deg
physgrid_map(mapind) = k + ((elem(ie)%GlobalId-1) * fv_nphys * fv_nphys)
physgrid_area(mapind) = fvm(ie)%area_sphere_physgrid(i,j)
+ physgrid_areawt(mapind) = physgrid_area(mapind)*rarea_unit_sphere
k = k + 1
end do
end do
@@ -1000,12 +1031,15 @@ subroutine define_cam_grids()
grid_map, block_indexed=.false., unstruct=.true.)
call cam_grid_attribute_register('physgrid_d', 'area_physgrid', 'physics grid areas', &
'ncol', physgrid_area, map=physgrid_map)
+ call cam_grid_attribute_register('physgrid_d', 'area_weight_physgrid', 'physics grid area weight', &
+ 'ncol', physgrid_areawt, map=physgrid_map)
call cam_grid_attribute_register('physgrid_d', 'fv_nphys', '', fv_nphys)
call cam_grid_attribute_register('physgrid_d', 'ne', '', ne)
deallocate(physgrid_coord)
deallocate(physgrid_map)
nullify(physgrid_area)
+ nullify(physgrid_areawt)
nullify(grid_map)
end if
diff --git a/src/dynamics/se/restart_dynamics.F90 b/src/dynamics/se/restart_dynamics.F90
index d3b1aa28fa..f5b3c6a0d8 100644
--- a/src/dynamics/se/restart_dynamics.F90
+++ b/src/dynamics/se/restart_dynamics.F90
@@ -43,7 +43,7 @@ module restart_dynamics
use parallel_mod, only: par
use thread_mod, only: horz_num_threads
-use dimensions_mod, only: np, npsq, ne, nlev, qsize, nelemd, nc, ntrac
+use dimensions_mod, only: np, npsq, ne, nlev, qsize, nelemd, nc, ntrac, use_cslam
use dof_mod, only: UniquePoints
use element_mod, only: element_t
use time_mod, only: tstep, TimeLevel_Qdp
@@ -148,7 +148,7 @@ subroutine init_restart_dynamics(file, dyn_out)
! CSLAM restart fields
- if (ntrac > 0) then
+ if (use_cslam) then
grid_id = cam_grid_id('FVM')
call cam_grid_write_attr(File, grid_id, info)
@@ -223,7 +223,7 @@ subroutine write_restart_dynamics(File, dyn_out)
! write CSLAM fields
- if (ntrac > 0) then
+ if (use_cslam) then
grid_id = cam_grid_id('FVM')
@@ -621,7 +621,7 @@ subroutine read_restart_dynamics(File, dyn_in, dyn_out)
! read cslam fields
- if (ntrac > 0) then
+ if (use_cslam) then
! Checks that file and model dimensions agree.
diff --git a/src/dynamics/se/stepon.F90 b/src/dynamics/se/stepon.F90
index febda50539..88dda66c3d 100644
--- a/src/dynamics/se/stepon.F90
+++ b/src/dynamics/se/stepon.F90
@@ -154,7 +154,7 @@ subroutine stepon_run2(phys_state, phys_tend, dyn_in, dyn_out)
use time_mod, only: TimeLevel_Qdp
use control_mod, only: qsplit
- use prim_advance_mod, only: calc_tot_energy_dynamics
+ use prim_advance_mod, only: tot_energy_dyn
! arguments
@@ -194,7 +194,7 @@ subroutine stepon_run2(phys_state, phys_tend, dyn_in, dyn_out)
call t_stopf('p_d_coupling')
if (iam < par%nprocs) then
- call calc_tot_energy_dynamics(dyn_in%elem,dyn_in%fvm, 1, nelemd, tl_f, tl_fQdp,'dED')
+ call tot_energy_dyn(dyn_in%elem,dyn_in%fvm, 1, nelemd, tl_f, tl_fQdp,'dED')
end if
end subroutine stepon_run2
diff --git a/src/dynamics/se/test_fvm_mapping.F90 b/src/dynamics/se/test_fvm_mapping.F90
index ef0481b5e0..4a26484854 100644
--- a/src/dynamics/se/test_fvm_mapping.F90
+++ b/src/dynamics/se/test_fvm_mapping.F90
@@ -3,7 +3,7 @@ module test_fvm_mapping
use fvm_control_volume_mod, only: fvm_struct
use cam_history, only: outfld
use physconst, only: pi
- use dimensions_mod, only: np, nelemd, nlev, npsq, ntrac
+ use dimensions_mod, only: np, nelemd, nlev, npsq, ntrac, use_cslam
use element_mod, only: element_t
implicit none
private
@@ -147,10 +147,6 @@ subroutine test_mapping_overwrite_tendencies(phys_state,phys_tend,ncols,lchnk,q_
integer :: m_cnst, nq, ie
q_prev(:,:,ntrac) = 0.0_r8
- do ie=1,nelemd
-!xxx fvm(ie)%c(:,:,:,ntrac) = 0.0_r8
- end do
-
phys_state%pdel(1:ncols,:) = phys_state%pdeldry(1:ncols,:) !make sure there is no conversion from wet to dry
do nq=ntrac,ntrac
m_cnst = nq
@@ -243,7 +239,7 @@ subroutine test_mapping_output_mapped_tendencies(fvm,elem,nets,nete,tl_f,tl_qdp)
name = 'p2d_'//trim(cnst_name(m_cnst))//'_err_gll'
call outfld(TRIM(name), RESHAPE(elem(ie)%derived%fq(:,:,:,nq),(/npsq,nlev/)), npsq, ie)
end do
- if (ntrac>0) then
+ if (use_cslam) then
do nq=ntrac,ntrac
m_cnst = nq
name = 'p2f_'//trim(cnst_name(m_cnst))//'_fvm'
@@ -356,7 +352,6 @@ subroutine test_mapping_overwrite_dyn_state(elem,fvm)
end do
end if
end do
-! call fill_halo_fvm_noprealloc(elem,fvm,hybrid,nets,nete,nhc,1,nlev)!xxx nhr chould be a function of interp_method
#endif
end subroutine test_mapping_overwrite_dyn_state
@@ -370,15 +365,11 @@ subroutine test_mapping_output_phys_state(phys_state,fvm)
integer :: lchnk, ncol,k,icol,m_cnst,nq,ie
character(LEN=128) :: name
- do ie=1,nelemd
-!xxx fvm(ie)%c(:,:,:,ntrac) = 0.0_r8
- end do
-
do lchnk = begchunk, endchunk
call outfld('d2p_scalar', phys_state(lchnk)%omega(1:pcols,1:pver), pcols, lchnk)
call outfld('d2p_u', phys_state(lchnk)%U(1:pcols,1:pver), pcols, lchnk)
call outfld('d2p_v', phys_state(lchnk)%V(1:pcols,1:pver), pcols, lchnk)
- if (ntrac>0) then
+ if (use_cslam) then
do nq=ntrac,ntrac
m_cnst = nq
name = 'f2p_'//trim(cnst_name(m_cnst))
diff --git a/src/infrastructure/phys_grid.F90 b/src/infrastructure/phys_grid.F90
index 505fdb0c26..3426c86f27 100644
--- a/src/infrastructure/phys_grid.F90
+++ b/src/infrastructure/phys_grid.F90
@@ -190,6 +190,7 @@ subroutine phys_grid_init()
use cam_grid_support, only: iMap, hclen => max_hcoordname_len
use cam_grid_support, only: horiz_coord_t, horiz_coord_create
use cam_grid_support, only: cam_grid_attribute_copy, cam_grid_attr_exists
+ use shr_const_mod, only: PI => SHR_CONST_PI
! Local variables
integer :: index
@@ -206,6 +207,7 @@ subroutine phys_grid_init()
type(horiz_coord_t), pointer :: lat_coord
type(horiz_coord_t), pointer :: lon_coord
real(r8), pointer :: area_d(:)
+ real(r8), pointer :: areawt_d(:)
real(r8) :: mem_hw_beg, mem_hw_end
real(r8) :: mem_beg, mem_end
logical :: unstructured
@@ -214,6 +216,7 @@ subroutine phys_grid_init()
character(len=hclen), pointer :: copy_attributes(:)
character(len=hclen) :: copy_gridname
character(len=*), parameter :: subname = 'phys_grid_init: '
+ real(r8), parameter :: rarea_sphere = 1.0_r8 / (4.0_r8*PI)
nullify(lonvals)
nullify(latvals)
@@ -221,6 +224,7 @@ subroutine phys_grid_init()
nullify(lat_coord)
nullify(lon_coord)
nullify(area_d)
+ nullify(areawt_d)
nullify(copy_attributes)
if (calc_memory_increase) then
@@ -416,6 +420,14 @@ subroutine phys_grid_init()
call cam_grid_attribute_register('physgrid', 'area', &
'physics column areas', 'ncol', area_d, map=grid_map(3,:))
nullify(area_d) ! Belongs to attribute now
+
+ allocate(areawt_d(size(grid_map, 2)))
+ do col_index = 1, columns_on_task
+ areawt_d(col_index) = phys_columns(col_index)%weight*rarea_sphere
+ end do
+ call cam_grid_attribute_register('physgrid', 'areawt', &
+ 'physics column area weight', 'ncol', areawt_d, map=grid_map(3,:))
+ nullify(areawt_d) ! Belongs to attribute now
else
call endrun(subname//"No 'area' attribute from dycore")
end if
diff --git a/src/physics/cam/cam_diagnostics.F90 b/src/physics/cam/cam_diagnostics.F90
index f0131dab0e..10612edfa9 100644
--- a/src/physics/cam/cam_diagnostics.F90
+++ b/src/physics/cam/cam_diagnostics.F90
@@ -13,8 +13,9 @@ module cam_diagnostics
use physics_buffer, only: dyn_time_lvls, pbuf_get_field, pbuf_get_index, pbuf_old_tim_idx
use cam_history, only: outfld, write_inithist, hist_fld_active, inithist_all
+use cam_history_support, only: max_fieldname_len
use constituents, only: pcnst, cnst_name, cnst_longname, cnst_cam_outfld
-use constituents, only: ptendnam, dmetendnam, apcnst, bpcnst, cnst_get_ind
+use constituents, only: ptendnam, apcnst, bpcnst, cnst_get_ind
use dycore, only: dycore_is
use phys_control, only: phys_getopts
use wv_saturation, only: qsat, qsat_water, svp_ice_vect
@@ -46,6 +47,18 @@ module cam_diagnostics
diag_physvar_ic, &
nsurf
+integer, public, parameter :: num_stages = 8
+character (len = max_fieldname_len), dimension(num_stages) :: stage = (/"phBF","phBP","phAP","phAM","dyBF","dyBP","dyAP","dyAM"/)
+character (len = 45),dimension(num_stages) :: stage_txt = (/&
+ " before energy fixer ",& !phBF - physics energy
+ " before parameterizations ",& !phBF - physics energy
+ " after parameterizations ",& !phAP - physics energy
+ " after dry mass correction ",& !phAM - physics energy
+ " before energy fixer (dycore) ",& !dyBF - dynamics energy
+ " before parameterizations (dycore) ",& !dyBF - dynamics energy
+ " after parameterizations (dycore) ",& !dyAP - dynamics energy
+ " after dry mass correction (dycore) " & !dyAM - dynamics energy
+ /)
! Private data
@@ -176,46 +189,12 @@ subroutine diag_init_dry(pbuf2d)
use cam_history, only: addfld, add_default, horiz_only
use cam_history, only: register_vector_field
- use constituent_burden, only: constituent_burden_init
- use physics_buffer, only: pbuf_set_field
use tidal_diag, only: tidal_diag_init
+ use cam_budget, only: cam_budget_em_snapshot, cam_budget_em_register, thermo_budget_history
type(physics_buffer_desc), pointer, intent(in) :: pbuf2d(:,:)
- integer :: k, m
- integer :: ierr
- !
- ! variables for energy diagnostics
- !
- integer :: istage, ivars
- character (len=108) :: str1, str2, str3
- integer, parameter :: num_stages = 8, num_vars = 8
- character (len = 4), dimension(num_stages) :: stage = (/"phBF","phBP","phAP","phAM","dyBF","dyBP","dyAP","dyAM"/)
- character (len = 45),dimension(num_stages) :: stage_txt = (/&
- " before energy fixer ",& !phBF - physics energy
- " before parameterizations ",& !phBF - physics energy
- " after parameterizations ",& !phAP - physics energy
- " after dry mass correction ",& !phAM - physics energy
- " before energy fixer (dycore) ",& !dyBF - dynamics energy
- " before parameterizations (dycore) ",& !dyBF - dynamics energy
- " after parameterizations (dycore) ",& !dyAP - dynamics energy
- " after dry mass correction (dycore) " & !dyAM - dynamics energy
- /)
- character (len = 2) , dimension(num_vars) :: vars = (/"WV" ,"WL" ,"WI" ,"SE" ,"KE" ,"MR" ,"MO" ,"TT" /)
- character (len = 45) , dimension(num_vars) :: vars_descriptor = (/&
- "Total column water vapor ",&
- "Total column liquid water ",&
- "Total column frozen water ",&
- "Total column dry static energy ",&
- "Total column kinetic energy ",&
- "Total column wind axial angular momentum",&
- "Total column mass axial angular momentum",&
- "Total column test tracer "/)
- character (len = 14), dimension(num_vars) :: &
- vars_unit = (/&
- "kg/m2 ","kg/m2 ","kg/m2 ","J/m2 ",&
- "J/m2 ","kg*m2/s*rad2 ","kg*m2/s*rad2 ","kg/m2 "/)
-
+ integer :: istage
! outfld calls in diag_phys_writeout
call addfld (cnst_name(1), (/ 'lev' /), 'A', 'kg/kg', cnst_longname(1))
call addfld ('NSTEP', horiz_only, 'A', 'timestep', 'Model timestep')
@@ -242,7 +221,7 @@ subroutine diag_init_dry(pbuf2d)
call register_vector_field('UAP','VAP')
call addfld (apcnst(1), (/ 'lev' /), 'A','kg/kg', trim(cnst_longname(1))//' (after physics)')
- if ( dycore_is('LR') .or. dycore_is('SE') .or. dycore_is('FV3') ) then
+ if (.not.dycore_is('EUL')) then
call addfld ('TFIX', horiz_only, 'A', 'K/s', 'T fixer (T equivalent of Energy correction)')
end if
call addfld ('TTEND_TOT', (/ 'lev' /), 'A', 'K/s', 'Total temperature tendency')
@@ -276,8 +255,8 @@ subroutine diag_init_dry(pbuf2d)
call addfld ('UU', (/ 'lev' /), 'A', 'm2/s2', 'Zonal velocity squared' )
call addfld ('WSPEED', (/ 'lev' /), 'X', 'm/s', 'Horizontal total wind speed maximum' )
- call addfld ('WSPDSRFMX', horiz_only, 'X', 'm/s', 'Horizontal total wind speed maximum at the surface' )
- call addfld ('WSPDSRFAV', horiz_only, 'A', 'm/s', 'Horizontal total wind speed average at the surface' )
+ call addfld ('WSPDSRFMX', horiz_only, 'X', 'm/s', 'Horizontal total wind speed maximum at surface layer midpoint' )
+ call addfld ('WSPDSRFAV', horiz_only, 'A', 'm/s', 'Horizontal total wind speed average at surface layer midpoint' )
call addfld ('OMEGA', (/ 'lev' /), 'A', 'Pa/s', 'Vertical velocity (pressure)')
call addfld ('OMEGAT', (/ 'lev' /), 'A', 'K Pa/s ', 'Vertical heat flux' )
@@ -386,7 +365,7 @@ subroutine diag_init_dry(pbuf2d)
call add_default ('UAP ' , history_budget_histfile_num, ' ')
call add_default ('VAP ' , history_budget_histfile_num, ' ')
call add_default (apcnst(1) , history_budget_histfile_num, ' ')
- if ( dycore_is('LR') .or. dycore_is('SE') .or. dycore_is('FV3') ) then
+ if (.not.dycore_is('EUL')) then
call add_default ('TFIX ' , history_budget_histfile_num, ' ')
end if
end if
@@ -412,22 +391,30 @@ subroutine diag_init_dry(pbuf2d)
! and semidiurnal tide in T, U, V, and Z3
call tidal_diag_init()
- !
- ! energy diagnostics
- !
- do istage = 1, num_stages
- do ivars=1, num_vars
- write(str1,*) TRIM(ADJUSTL(vars(ivars))),"_",TRIM(ADJUSTL(stage(istage)))
- write(str2,*) TRIM(ADJUSTL(vars_descriptor(ivars)))," ", &
- TRIM(ADJUSTL(stage_txt(istage)))
- write(str3,*) TRIM(ADJUSTL(vars_unit(ivars)))
- call addfld (TRIM(ADJUSTL(str1)), horiz_only, 'A', TRIM(ADJUSTL(str3)),TRIM(ADJUSTL(str2)))
- end do
- end do
-
call addfld( 'CPAIRV', (/ 'lev' /), 'I', 'J/K/kg', 'Variable specific heat cap air' )
call addfld( 'RAIRV', (/ 'lev' /), 'I', 'J/K/kg', 'Variable dry air gas constant' )
+ if (thermo_budget_history) then
+ !
+ ! energy diagnostics addflds for vars_stage combinations plus e_m_snapshots
+ !
+ do istage = 1, num_stages
+ call cam_budget_em_snapshot(TRIM(ADJUSTL(stage(istage))),'phy',longname=TRIM(ADJUSTL(stage_txt(istage))))
+ end do
+
+ ! Create budgets that are a sum/dif of 2 stages
+
+ call cam_budget_em_register('dEdt_param_efix_physE','phAP','phBF','phy','dif',longname='dE/dt CAM physics + energy fixer using physics E formula (phAP-phBF)')
+ call cam_budget_em_register('dEdt_param_efix_dynE' ,'dyAP','dyBF','phy','dif',longname='dE/dt CAM physics + energy fixer using dycore E formula (dyAP-dyBF)')
+ call cam_budget_em_register('dEdt_param_physE' ,'phAP','phBP','phy','dif',longname='dE/dt CAM physics using physics E formula (phAP-phBP)')
+ call cam_budget_em_register('dEdt_param_dynE' ,'dyAP','dyBP','phy','dif',longname='dE/dt CAM physics using dycore E (dyAP-dyBP)')
+ call cam_budget_em_register('dEdt_dme_adjust_physE','phAM','phAP','phy','dif',longname='dE/dt dry mass adjustment using physics E formula (phAM-phAP)')
+ call cam_budget_em_register('dEdt_dme_adjust_dynE' ,'dyAM','dyAP','phy','dif',longname='dE/dt dry mass adjustment using dycore E (dyAM-dyAP)')
+ call cam_budget_em_register('dEdt_efix_physE' ,'phBP','phBF','phy','dif',longname='dE/dt energy fixer using physics E formula (phBP-phBF)')
+ call cam_budget_em_register('dEdt_efix_dynE' ,'dyBP','dyBF','phy','dif',longname='dE/dt energy fixer using dycore E formula (dyBP-dyBF)')
+ call cam_budget_em_register('dEdt_phys_tot_physE' ,'phAM','phBF','phy','dif',longname='dE/dt physics total using physics E formula (phAM-phBF)')
+ call cam_budget_em_register('dEdt_phys_tot_dynE' ,'dyAM','dyBF','phy','dif',longname='dE/dt physics total using dycore E (dyAM-dyBF)')
+ endif
end subroutine diag_init_dry
subroutine diag_init_moist(pbuf2d)
@@ -440,7 +427,7 @@ subroutine diag_init_moist(pbuf2d)
type(physics_buffer_desc), pointer, intent(in) :: pbuf2d(:,:)
- integer :: k, m
+ integer :: m
integer :: ixcldice, ixcldliq ! constituent indices for cloud liquid and ice water.
integer :: ierr
! column burdens for all constituents except water vapor
@@ -547,18 +534,6 @@ subroutine diag_init_moist(pbuf2d)
if (ixcldice > 0) then
call addfld (ptendnam(ixcldice),(/ 'lev' /), 'A', 'kg/kg/s',trim(cnst_name(ixcldice))//' total physics tendency ')
end if
- if ( dycore_is('LR') .or. dycore_is('FV3') )then
- call addfld (dmetendnam( 1),(/ 'lev' /), 'A','kg/kg/s', &
- trim(cnst_name( 1))//' dme adjustment tendency (FV) ')
- if (ixcldliq > 0) then
- call addfld (dmetendnam(ixcldliq),(/ 'lev' /), 'A','kg/kg/s', &
- trim(cnst_name(ixcldliq))//' dme adjustment tendency (FV) ')
- end if
- if (ixcldice > 0) then
- call addfld (dmetendnam(ixcldice),(/ 'lev' /), 'A','kg/kg/s', &
- trim(cnst_name(ixcldice))//' dme adjustment tendency (FV) ')
- end if
- end if
! outfld calls in diag_physvar_ic
@@ -649,15 +624,6 @@ subroutine diag_init_moist(pbuf2d)
if (ixcldice > 0) then
call add_default (ptendnam(ixcldice), history_budget_histfile_num, ' ')
end if
- if ( dycore_is('LR') .or. dycore_is('FV3') )then
- call add_default(dmetendnam(1) , history_budget_histfile_num, ' ')
- if (ixcldliq > 0) then
- call add_default(dmetendnam(ixcldliq), history_budget_histfile_num, ' ')
- end if
- if (ixcldice > 0) then
- call add_default(dmetendnam(ixcldice), history_budget_histfile_num, ' ')
- end if
- end if
if( history_budget_histfile_num > 1 ) then
call add_default ('DTCOND ' , history_budget_histfile_num, ' ')
end if
@@ -753,7 +719,6 @@ subroutine diag_init_moist(pbuf2d)
end subroutine diag_init_moist
subroutine diag_init(pbuf2d)
- use cam_history, only: addfld
! Declare the history fields for which this module contains outfld calls.
@@ -934,15 +899,11 @@ subroutine diag_phys_writeout_dry(state, pbuf, p_surf_t)
! Purpose: output dry physics diagnostics
!
!-----------------------------------------------------------------------
- use physconst, only: gravit, rga, rair, cpair, latvap, rearth, pi, cappa
+ use physconst, only: gravit, rga, rair, cappa
use time_manager, only: get_nstep
use interpolate_data, only: vertinterp
- use constituent_burden, only: constituent_burden_comp
- use co2_cycle, only: c_i, co2_transport
-
use tidal_diag, only: tidal_diag_write
use air_composition, only: cpairv, rairv
-
!-----------------------------------------------------------------------
!
! Arguments
@@ -954,15 +915,9 @@ subroutine diag_phys_writeout_dry(state, pbuf, p_surf_t)
!---------------------------Local workspace-----------------------------
!
real(r8) :: ftem(pcols,pver) ! temporary workspace
- real(r8) :: ftem1(pcols,pver) ! another temporary workspace
- real(r8) :: ftem2(pcols,pver) ! another temporary workspace
real(r8) :: z3(pcols,pver) ! geo-potential height
real(r8) :: p_surf(pcols) ! data interpolated to a pressure surface
- real(r8) :: tem2(pcols,pver) ! temporary workspace
real(r8) :: timestep(pcols) ! used for outfld call
- real(r8) :: esl(pcols,pver) ! saturation vapor pressures
- real(r8) :: esi(pcols,pver) !
- real(r8) :: dlon(pcols) ! width of grid cell (meters)
real(r8), pointer :: psl(:) ! Sea Level Pressure
@@ -1276,8 +1231,7 @@ subroutine diag_phys_writeout_moist(state, pbuf, p_surf_t)
! Purpose: record dynamics variables on physics grid
!
!-----------------------------------------------------------------------
- use physconst, only: gravit, rga, rair, cpair, latvap, rearth, pi, cappa, &
- epsilo, rh2o
+ use physconst, only: gravit, rga, rair, cpair, latvap, rearth, cappa
use interpolate_data, only: vertinterp
use constituent_burden, only: constituent_burden_comp
use co2_cycle, only: c_i, co2_transport
@@ -1294,7 +1248,6 @@ subroutine diag_phys_writeout_moist(state, pbuf, p_surf_t)
real(r8) :: ftem(pcols,pver) ! temporary workspace
real(r8) :: ftem1(pcols,pver) ! another temporary workspace
real(r8) :: ftem2(pcols,pver) ! another temporary workspace
- real(r8) :: z3(pcols,pver) ! geo-potential height
real(r8) :: p_surf(pcols) ! data interpolated to a pressure surface
real(r8) :: p_surf_q1(pcols) ! data interpolated to a pressure surface
real(r8) :: p_surf_q2(pcols) ! data interpolated to a pressure surface
@@ -1611,7 +1564,6 @@ subroutine diag_conv(state, ztodt, pbuf)
! Output diagnostics associated with all convective processes.
!
!-----------------------------------------------------------------------
- use physconst, only: cpair
use tidal_diag, only: get_tidal_coeffs
! Arguments:
@@ -1973,7 +1925,6 @@ subroutine diag_physvar_ic (lchnk, pbuf, cam_out, cam_in)
!
!---------------------------Local workspace-----------------------------
!
- integer :: k ! indices
integer :: itim_old ! indices
real(r8), pointer, dimension(:,:) :: cwat_var
@@ -2104,7 +2055,7 @@ subroutine diag_phys_tend_writeout_dry(state, pbuf, tend, ztodt)
! Total physics tendency for Temperature
! (remove global fixer tendency from total for FV and SE dycores)
- if (dycore_is('LR') .or. dycore_is('SE') .or. dycore_is('FV3') ) then
+ if (.not.dycore_is('EUL')) then
call check_energy_get_integrals( heat_glob_out=heat_glob )
ftem2(:ncol) = heat_glob/cpair
call outfld('TFIX', ftem2, pcols, lchnk )
@@ -2144,7 +2095,7 @@ end subroutine diag_phys_tend_writeout_dry
!#######################################################################
subroutine diag_phys_tend_writeout_moist(state, pbuf, tend, ztodt, &
- tmp_q, tmp_cldliq, tmp_cldice, qini, cldliqini, cldiceini)
+ qini, cldliqini, cldiceini)
!---------------------------------------------------------------
!
@@ -2159,9 +2110,6 @@ subroutine diag_phys_tend_writeout_moist(state, pbuf, tend, ztodt, &
type(physics_buffer_desc), pointer :: pbuf(:)
type(physics_tend ), intent(in) :: tend
real(r8), intent(in) :: ztodt ! physics timestep
- real(r8), intent(inout) :: tmp_q (pcols,pver) ! As input, holds pre-adjusted tracers (FV)
- real(r8), intent(inout) :: tmp_cldliq(pcols,pver) ! As input, holds pre-adjusted tracers (FV)
- real(r8), intent(inout) :: tmp_cldice(pcols,pver) ! As input, holds pre-adjusted tracers (FV)
real(r8), intent(in) :: qini (pcols,pver) ! tracer fields at beginning of physics
real(r8), intent(in) :: cldliqini (pcols,pver) ! tracer fields at beginning of physics
real(r8), intent(in) :: cldiceini (pcols,pver) ! tracer fields at beginning of physics
@@ -2194,35 +2142,6 @@ subroutine diag_phys_tend_writeout_moist(state, pbuf, tend, ztodt, &
end if
end if
- ! Tendency for dry mass adjustment of q (FV only)
-
- if (dycore_is('LR') .or. dycore_is('FV3') ) then
- tmp_q (:ncol,:pver) = (state%q(:ncol,:pver, 1) - tmp_q (:ncol,:pver))*rtdt
- if (ixcldliq > 0) then
- tmp_cldliq(:ncol,:pver) = (state%q(:ncol,:pver,ixcldliq) - tmp_cldliq(:ncol,:pver))*rtdt
- else
- tmp_cldliq(:ncol,:pver) = 0.0_r8
- end if
- if (ixcldice > 0) then
- tmp_cldice(:ncol,:pver) = (state%q(:ncol,:pver,ixcldice) - tmp_cldice(:ncol,:pver))*rtdt
- else
- tmp_cldice(:ncol,:pver) = 0.0_r8
- end if
- if ( cnst_cam_outfld( 1) ) then
- call outfld (dmetendnam( 1), tmp_q , pcols, lchnk)
- end if
- if (ixcldliq > 0) then
- if ( cnst_cam_outfld(ixcldliq) ) then
- call outfld (dmetendnam(ixcldliq), tmp_cldliq, pcols, lchnk)
- end if
- end if
- if (ixcldice > 0) then
- if ( cnst_cam_outfld(ixcldice) ) then
- call outfld (dmetendnam(ixcldice), tmp_cldice, pcols, lchnk)
- end if
- end if
- end if
-
! Total physics tendency for moisture and other tracers
if ( cnst_cam_outfld( 1) ) then
@@ -2247,7 +2166,7 @@ end subroutine diag_phys_tend_writeout_moist
!#######################################################################
subroutine diag_phys_tend_writeout(state, pbuf, tend, ztodt, &
- tmp_q, tmp_cldliq, tmp_cldice, qini, cldliqini, cldiceini)
+ qini, cldliqini, cldiceini)
!---------------------------------------------------------------
!
@@ -2262,9 +2181,6 @@ subroutine diag_phys_tend_writeout(state, pbuf, tend, ztodt, &
type(physics_buffer_desc), pointer :: pbuf(:)
type(physics_tend ), intent(in) :: tend
real(r8), intent(in) :: ztodt ! physics timestep
- real(r8) , intent(inout) :: tmp_q (pcols,pver) ! As input, holds pre-adjusted tracers (FV)
- real(r8), intent(inout) :: tmp_cldliq(pcols,pver) ! As input, holds pre-adjusted tracers (FV)
- real(r8), intent(inout) :: tmp_cldice(pcols,pver) ! As input, holds pre-adjusted tracers (FV)
real(r8), intent(in) :: qini (pcols,pver) ! tracer fields at beginning of physics
real(r8), intent(in) :: cldliqini (pcols,pver) ! tracer fields at beginning of physics
real(r8), intent(in) :: cldiceini (pcols,pver) ! tracer fields at beginning of physics
@@ -2274,7 +2190,7 @@ subroutine diag_phys_tend_writeout(state, pbuf, tend, ztodt, &
call diag_phys_tend_writeout_dry(state, pbuf, tend, ztodt)
if (moist_physics) then
call diag_phys_tend_writeout_moist(state, pbuf, tend, ztodt, &
- tmp_q, tmp_cldliq, tmp_cldice, qini, cldliqini, cldiceini)
+ qini, cldliqini, cldiceini)
end if
end subroutine diag_phys_tend_writeout
diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90
index 4e55c3de58..7615f0e432 100644
--- a/src/physics/cam/check_energy.F90
+++ b/src/physics/cam/check_energy.F90
@@ -25,8 +25,8 @@ module check_energy
use spmd_utils, only: masterproc
use gmean_mod, only: gmean
- use physconst, only: gravit, latvap, latice, cpair, rair
- use air_composition, only: cpairv, rairv
+ use physconst, only: gravit, rga, latvap, latice, cpair, rair
+ use air_composition, only: cpairv, rairv, cp_or_cv_dycore
use physics_types, only: physics_state, physics_tend, physics_ptend, physics_ptend_init
use constituents, only: cnst_get_ind, pcnst, cnst_name, cnst_get_type_byind
use time_manager, only: is_first_step
@@ -50,7 +50,7 @@ module check_energy
public :: check_tracers_init ! initialize tracer integrals and cumulative boundary fluxes
public :: check_tracers_chng ! check changes in integrals against cumulative boundary fluxes
- public :: calc_te_and_aam_budgets ! calculate and output total energy and axial angular momentum diagnostics
+ public :: tot_energy_phys ! calculate and output total energy and axial angular momentum diagnostics
! Private module data
@@ -221,7 +221,7 @@ subroutine check_energy_timestep_init(state, tend, pbuf, col_type)
use cam_thermo, only: get_hydrostatic_energy
use physics_buffer, only: physics_buffer_desc, pbuf_set_field
use cam_abortutils, only: endrun
- use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height
+ use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure
use physics_types, only: phys_te_idx, dyn_te_idx
!-----------------------------------------------------------------------
! Compute initial values of energy and water integrals,
@@ -237,7 +237,6 @@ subroutine check_energy_timestep_init(state, tend, pbuf, col_type)
real(r8) :: cp_or_cv(state%psetcols,pver)
integer lchnk ! chunk identifier
integer ncol ! number of atmospheric columns
- integer i,k ! column, level indices
!-----------------------------------------------------------------------
lchnk = state%lchnk
@@ -250,17 +249,17 @@ subroutine check_energy_timestep_init(state, tend, pbuf, col_type)
if (state%psetcols == pcols) then
cp_or_cv(:,:) = cpairv(:,:,lchnk)
else if (state%psetcols > pcols .and. all(cpairv(:,:,lchnk) == cpair)) then
- cp_or_cv(:,:) = cpair
+ cp_or_cv(1:ncol,:) = cpair
else
call endrun('check_energy_timestep_init: cpairv is not allowed to vary when subcolumns are turned on')
end if
!
! CAM physics total energy
!
- call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),&
+ call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., &
state%pdel(1:ncol,1:pver), cp_or_cv(1:ncol,1:pver), &
state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), state%T(1:ncol,1:pver), &
- vc_physics, ps = state%ps(1:ncol), phis = state%phis(1:ncol), &
+ vc_physics, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol),&
te = state%te_ini(1:ncol,phys_te_idx), H2O = state%tw_ini(1:ncol,phys_te_idx))
!
! Dynamical core total energy
@@ -269,25 +268,41 @@ subroutine check_energy_timestep_init(state, tend, pbuf, col_type)
state%z_ini(:ncol,:) = state%zm(:ncol,:)
if (vc_dycore == vc_height) then
!
- ! compute cv if vertical coordinate is height: cv = cp - R
+ ! MPAS specific hydrostatic energy computation (internal energy)
!
if (state%psetcols == pcols) then
- cp_or_cv(:,:) = cpairv(:,:,lchnk)-rairv(:,:,lchnk)
+ cp_or_cv(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk)
else
- cp_or_cv(:,:) = cpair-rair
+ cp_or_cv(:ncol,:) = cpair-rair
endif
- call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),&
+ call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., &
+ state%pdel(1:ncol,1:pver), cp_or_cv(1:ncol,1:pver), &
+ state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), state%T(1:ncol,1:pver), &
+ vc_dycore, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol), &
+ z_mid = state%z_ini(1:ncol,:), &
+ te = state%te_ini(1:ncol,dyn_te_idx), H2O = state%tw_ini(1:ncol,dyn_te_idx))
+ else if (vc_dycore == vc_dry_pressure) then
+ !
+ ! SE specific hydrostatic energy (enthalpy)
+ !
+ if (state%psetcols == pcols) then
+ cp_or_cv(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk)
+ else
+ cp_or_cv(:ncol,:) = cpair
+ endif
+ call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., &
state%pdel(1:ncol,1:pver), cp_or_cv(1:ncol,1:pver), &
state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), state%T(1:ncol,1:pver), &
- vc_dycore, ps = state%ps(1:ncol), phis = state%phis(1:ncol), &
- z_mid = state%z_ini(1:ncol,:), &
+ vc_dry_pressure, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol), &
te = state%te_ini(1:ncol,dyn_te_idx), H2O = state%tw_ini(1:ncol,dyn_te_idx))
else
+ !
+ ! dycore energy is the same as physics
+ !
state%te_ini(1:ncol,dyn_te_idx) = state%te_ini(1:ncol,phys_te_idx)
state%tw_ini(1:ncol,dyn_te_idx) = state%tw_ini(1:ncol,phys_te_idx)
end if
-
state%te_cur(:ncol,:) = state%te_ini(:ncol,:)
state%tw_cur(:ncol,:) = state%tw_ini(:ncol,:)
@@ -309,7 +324,7 @@ end subroutine check_energy_timestep_init
subroutine check_energy_chng(state, tend, name, nstep, ztodt, &
flx_vap, flx_cnd, flx_ice, flx_sen)
use cam_thermo, only: get_hydrostatic_energy
- use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height
+ use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure
use cam_abortutils, only: endrun
use physics_types, only: phys_te_idx, dyn_te_idx
!-----------------------------------------------------------------------
@@ -351,12 +366,16 @@ subroutine check_energy_chng(state, tend, name, nstep, ztodt, &
real(r8) :: scaling(state%psetcols,pver) ! scaling for conversion of temperature increment
real(r8) :: temp(state%ncol,pver) ! temperature
+ real(r8) :: se(state%ncol) ! enthalpy or internal energy (J/m2)
+ real(r8) :: po(state%ncol) ! surface potential or potential energy (J/m2)
+ real(r8) :: ke(state%ncol) ! kinetic energy (J/m2)
+ real(r8) :: wv(state%ncol) ! column integrated vapor (kg/m2)
+ real(r8) :: liq(state%ncol) ! column integrated liquid (kg/m2)
+ real(r8) :: ice(state%ncol) ! column integrated ice (kg/m2)
+
integer lchnk ! chunk identifier
integer ncol ! number of atmospheric columns
- integer i,k ! column, level indices
- integer :: ixcldice, ixcldliq ! CLDICE and CLDLIQ indices
- integer :: ixrain, ixsnow ! RAINQM and SNOWQM indices
- integer :: ixgrau ! GRAUQM index
+ integer i ! column index
!-----------------------------------------------------------------------
lchnk = state%lchnk
@@ -373,12 +392,12 @@ subroutine check_energy_chng(state, tend, name, nstep, ztodt, &
call endrun('check_energy_chng: cpairv is not allowed to vary when subcolumns are turned on')
end if
- call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),&
+ call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., &
state%pdel(1:ncol,1:pver), cp_or_cv(1:ncol,1:pver), &
state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), state%T(1:ncol,1:pver), &
- vc_physics, ps = state%ps(1:ncol), phis = state%phis(1:ncol), &
- te = te, H2O = tw)
-
+ vc_physics, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol), &
+ te = te(1:ncol), H2O = tw(1:ncol), se=se(1:ncol),po=po(1:ncol), &
+ ke=ke(1:ncol),wv=wv(1:ncol),liq=liq(1:ncol),ice=ice(1:ncol))
! compute expected values and tendencies
do i = 1, ncol
! change in static energy and total water
@@ -447,20 +466,37 @@ subroutine check_energy_chng(state, tend, name, nstep, ztodt, &
! compute cv if vertical coordinate is height: cv = cp - R
!
! Note: cp_or_cv set above for pressure coordinate
- !
if (state%psetcols == pcols) then
- cp_or_cv(:,:) = cpairv(:,:,lchnk)-rairv(:,:,lchnk)
+ cp_or_cv(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk)
else
- cp_or_cv(:,:) = cpair-rair
+ cp_or_cv(:ncol,:) = cpair-rair
endif
- scaling(:,:) = cpairv(:,:,lchnk)/cp_or_cv(:,:) !cp/cv scaling
-
+ scaling(:,:) = cpairv(:,:,lchnk)/cp_or_cv(:,:) !cp/cv scaling
temp(1:ncol,:) = state%temp_ini(1:ncol,:)+scaling(1:ncol,:)*(state%T(1:ncol,:)-state%temp_ini(1:ncol,:))
- call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),&
+ call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., &
+ state%pdel(1:ncol,1:pver), cp_or_cv(1:ncol,1:pver), &
+ state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), temp(1:ncol,1:pver), &
+ vc_dycore, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol), &
+ z_mid = state%z_ini(1:ncol,:), &
+ te = state%te_cur(1:ncol,dyn_te_idx), H2O = state%tw_cur(1:ncol,dyn_te_idx))
+ else if (vc_dycore == vc_dry_pressure) then
+ !
+ ! SE specific hydrostatic energy
+ !
+ if (state%psetcols == pcols) then
+ cp_or_cv(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk)
+ else
+ cp_or_cv(:ncol,:) = cpair
+ endif
+ !
+ ! enthalpy scaling for energy consistency
+ !
+ scaling(:ncol,:) = cpairv(:ncol,:,lchnk)/cp_or_cv_dycore(:ncol,:,lchnk)
+ temp(1:ncol,:) = state%temp_ini(1:ncol,:)+scaling(1:ncol,:)*(state%T(1:ncol,:)-state%temp_ini(1:ncol,:))
+ call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., &
state%pdel(1:ncol,1:pver), cp_or_cv(1:ncol,1:pver), &
state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), temp(1:ncol,1:pver), &
- vc_dycore, ps = state%ps(1:ncol), phis = state%phis(1:ncol), &
- z_mid = state%z_ini(1:ncol,:), &
+ vc_dry_pressure, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol), &
te = state%te_cur(1:ncol,dyn_te_idx), H2O = state%tw_cur(1:ncol,dyn_te_idx))
else
state%te_cur(1:ncol,dyn_te_idx) = te(1:ncol)
@@ -472,7 +508,6 @@ end subroutine check_energy_chng
subroutine check_energy_gmean(state, pbuf2d, dtime, nstep)
use physics_buffer, only : physics_buffer_desc, pbuf_get_field, pbuf_get_chunk
- use dyn_tests_utils, only: vc_dycore, vc_height
use physics_types, only: dyn_te_idx
!-----------------------------------------------------------------------
! Compute global mean total energy of physics input and output states
@@ -563,13 +598,11 @@ subroutine check_energy_fix(state, ptend, nstep, eshflx)
#endif
! add (-) global mean total energy difference as heating
ptend%s(:ncol,:pver) = heat_glob
-!!$ write(iulog,*) "chk_fix: heat", state%lchnk, ncol, heat_glob
! compute effective sensible heat flux
do i = 1, ncol
- eshflx(i) = heat_glob * (state%pint(i,pver+1) - state%pint(i,1)) / gravit
+ eshflx(i) = heat_glob * (state%pint(i,pver+1) - state%pint(i,1)) * rga
end do
-!!! if (nstep > 0) write(iulog,*) "heat", heat_glob, eshflx(1)
return
end subroutine check_energy_fix
@@ -624,7 +657,7 @@ subroutine check_tracers_init(state, tracerint)
tr = 0._r8
do k = 1, pver
do i = 1, ncol
- tr(i) = tr(i) + state%q(i,k,m)*trpdel(i,k)/gravit
+ tr(i) = tr(i) + state%q(i,k,m)*trpdel(i,k)*rga
end do
end do
@@ -687,7 +720,6 @@ subroutine check_tracers_chng(state, tracerint, name, nstep, ztodt, cflx)
integer :: m ! tracer index
character(len=8) :: tracname ! tracername
!-----------------------------------------------------------------------
-!!$ if (.true.) return
lchnk = state%lchnk
ncol = state%ncol
@@ -713,7 +745,7 @@ subroutine check_tracers_chng(state, tracerint, name, nstep, ztodt, cflx)
tr = 0._r8
do k = 1, pver
do i = 1, ncol
- tr(i) = tr(i) + state%q(i,k,m)*trpdel(i,k)/gravit
+ tr(i) = tr(i) + state%q(i,k,m)*trpdel(i,k)*rga
end do
end do
@@ -785,12 +817,16 @@ end subroutine check_tracers_chng
!#######################################################################
- subroutine calc_te_and_aam_budgets(state, outfld_name_suffix,vc)
- use physconst, only: gravit,cpair,pi,rearth,omega
- use cam_thermo, only: get_hydrostatic_energy
- use cam_history, only: hist_fld_active, outfld
- use dyn_tests_utils, only: vc_physics, vc_height
+ subroutine tot_energy_phys(state, outfld_name_suffix,vc)
+ use physconst, only: rga,rearth,omega
+ use cam_thermo, only: get_hydrostatic_energy,thermo_budget_num_vars,thermo_budget_vars, &
+ wvidx,wlidx,wiidx,seidx,poidx,keidx,moidx,mridx,ttidx,teidx
+ use cam_history, only: outfld
+ use dyn_tests_utils, only: vc_physics, vc_height, vc_dry_pressure
+
use cam_abortutils, only: endrun
+ use cam_history_support, only: max_fieldname_len
+ use cam_budget, only: thermo_budget_history
!------------------------------Arguments--------------------------------
type(physics_state), intent(inout) :: state
@@ -799,6 +835,7 @@ subroutine calc_te_and_aam_budgets(state, outfld_name_suffix,vc)
!---------------------------Local storage-------------------------------
real(r8) :: se(pcols) ! Dry Static energy (J/m2)
+ real(r8) :: po(pcols) ! surface potential or potential energy (J/m2)
real(r8) :: ke(pcols) ! kinetic energy (J/m2)
real(r8) :: wv(pcols) ! column integrated vapor (kg/m2)
real(r8) :: liq(pcols) ! column integrated liquid (kg/m2)
@@ -817,88 +854,81 @@ subroutine calc_te_and_aam_budgets(state, outfld_name_suffix,vc)
integer :: i,k ! column, level indices
integer :: vc_loc ! local vertical coordinate variable
integer :: ixtt ! test tracer index
- character(len=16) :: name_out1,name_out2,name_out3,name_out4,name_out5,name_out6
-!-----------------------------------------------------------------------
+ character(len=max_fieldname_len) :: name_out(thermo_budget_num_vars)
- name_out1 = 'SE_' //trim(outfld_name_suffix)
- name_out2 = 'KE_' //trim(outfld_name_suffix)
- name_out3 = 'WV_' //trim(outfld_name_suffix)
- name_out4 = 'WL_' //trim(outfld_name_suffix)
- name_out5 = 'WI_' //trim(outfld_name_suffix)
- name_out6 = 'TT_' //trim(outfld_name_suffix)
+!-----------------------------------------------------------------------
- if ( hist_fld_active(name_out1).or.hist_fld_active(name_out2).or.hist_fld_active(name_out3).or.&
- hist_fld_active(name_out4).or.hist_fld_active(name_out5).or.hist_fld_active(name_out6)) then
+ if (.not.thermo_budget_history) return
- lchnk = state%lchnk
- ncol = state%ncol
+ do i=1,thermo_budget_num_vars
+ name_out(i)=trim(thermo_budget_vars(i))//'_'//trim(outfld_name_suffix)
+ end do
- if (present(vc)) then
- vc_loc = vc
- else
- vc_loc = vc_physics
- end if
+ lchnk = state%lchnk
+ ncol = state%ncol
- if (state%psetcols == pcols) then
- if (vc_loc == vc_height) then
- !
- ! compute cv if vertical coordinate is height: cv = cp - R
- !
- cp_or_cv(:,:) = cpairv(:,:,lchnk)-rairv(:,:,lchnk)!cv
- else
- cp_or_cv(:,:) = cpairv(:,:,lchnk) !cp
- end if
- else
- call endrun('calc_te_and_aam_budgets: energy diagnostics not implemented/tested for subcolumns')
- end if
+ if (present(vc)) then
+ vc_loc = vc
+ else
+ vc_loc = vc_physics
+ end if
- if (vc_loc == vc_height) then
- scaling(:,:) = cpairv(:,:,lchnk)/cp_or_cv(:,:) !cp/cv scaling for temperature increment under constant volume
+ if (state%psetcols == pcols) then
+ if (vc_loc == vc_height .or. vc_loc == vc_dry_pressure) then
+ cp_or_cv(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk)
else
- scaling(:,:) = 1.0_r8
+ cp_or_cv(:ncol,:) = cpairv(:ncol,:,lchnk)
end if
- ! scale accumulated temperature increment for constant volume (otherwise effectively do nothing)
- temp(1:ncol,:) = state%temp_ini(1:ncol,:)+scaling(1:ncol,:)*(state%T(1:ncol,:)- state%temp_ini(1:ncol,:))
+ else
+ call endrun('tot_energy_phys: energy diagnostics not implemented/tested for subcolumns')
+ end if
- call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),&
- state%pdel(1:ncol,1:pver), cp_or_cv, &
- state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), temp(1:ncol,1:pver), &
- vc_loc, ps = state%ps(1:ncol), phis = state%phis(1:ncol), &
- z_mid = state%z_ini(1:ncol,:), se = se, ke = ke, wv = wv, liq = liq, ice = ice)
-
- call cnst_get_ind('TT_LW' , ixtt , abort=.false.)
-
- tt = 0._r8
- if (ixtt > 1) then
- if (name_out6 == 'TT_pAM'.or.name_out6 == 'TT_zAM') then
- !
- ! after dme_adjust mixing ratios are all wet
- !
- do k = 1, pver
- do i = 1, ncol
- tt_tmp = state%q(i,k,ixtt)*state%pdel(i,k)/gravit
- tt (i) = tt(i) + tt_tmp
- end do
+ if (vc_loc == vc_height .or. vc_loc == vc_dry_pressure) then
+ scaling(:ncol,:) = cpairv(:ncol,:,lchnk)/cp_or_cv(:ncol,:)!scaling for energy consistency
+ else
+ scaling(:ncol,:) = 1.0_r8 !internal energy / enthalpy same as CAM physics
+ end if
+ ! scale accumulated temperature increment for internal energy / enthalpy consistency
+ temp(1:ncol,:) = state%temp_ini(1:ncol,:)+scaling(1:ncol,:)*(state%T(1:ncol,:)- state%temp_ini(1:ncol,:))
+ call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., &
+ state%pdel(1:ncol,1:pver), cp_or_cv(1:ncol,1:pver), &
+ state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), temp(1:ncol,1:pver), &
+ vc_loc, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol), &
+ z_mid = state%z_ini(1:ncol,:), se = se(1:ncol), &
+ po = po(1:ncol), ke = ke(1:ncol), wv = wv(1:ncol), liq = liq(1:ncol), &
+ ice = ice(1:ncol))
+
+ call cnst_get_ind('TT_LW' , ixtt , abort=.false.)
+ tt = 0._r8
+ if (ixtt > 1) then
+ if (name_out(ttidx) == 'TT_pAM'.or.name_out(ttidx) == 'TT_zAM') then
+ !
+ ! after dme_adjust mixing ratios are all wet
+ !
+ do k = 1, pver
+ do i = 1, ncol
+ tt_tmp = state%q(i,k,ixtt)*state%pdel(i,k)*rga
+ tt (i) = tt(i) + tt_tmp
end do
- else
- do k = 1, pver
- do i = 1, ncol
- tt_tmp = state%q(i,k,ixtt)*state%pdeldry(i,k)/gravit
- tt (i) = tt(i) + tt_tmp
- end do
+ end do
+ else
+ do k = 1, pver
+ do i = 1, ncol
+ tt_tmp = state%q(i,k,ixtt)*state%pdeldry(i,k)*rga
+ tt (i) = tt(i) + tt_tmp
end do
- end if
+ end do
end if
-
- ! Output energy diagnostics
-
- call outfld(name_out1 ,se , pcols ,lchnk )
- call outfld(name_out2 ,ke , pcols ,lchnk )
- call outfld(name_out3 ,wv , pcols ,lchnk )
- call outfld(name_out4 ,liq , pcols ,lchnk )
- call outfld(name_out5 ,ice , pcols ,lchnk )
- call outfld(name_out6 ,tt , pcols ,lchnk )
end if
+
+ call outfld(name_out(seidx) ,se , pcols ,lchnk )
+ call outfld(name_out(poidx) ,po , pcols ,lchnk )
+ call outfld(name_out(keidx) ,ke , pcols ,lchnk )
+ call outfld(name_out(wvidx) ,wv , pcols ,lchnk )
+ call outfld(name_out(wlidx) ,liq , pcols ,lchnk )
+ call outfld(name_out(wiidx) ,ice , pcols ,lchnk )
+ call outfld(name_out(ttidx) ,tt , pcols ,lchnk )
+ call outfld(name_out(teidx) ,se+ke+po, pcols ,lchnk )
!
! Axial angular momentum diagnostics
!
@@ -912,32 +942,27 @@ subroutine calc_te_and_aam_budgets(state, outfld_name_suffix,vc)
! MR is equation (6) without \Delta A and sum over areas (areas are in units of radians**2)
! MO is equation (7) without \Delta A and sum over areas (areas are in units of radians**2)
!
- name_out1 = 'MR_' //trim(outfld_name_suffix)
- name_out2 = 'MO_' //trim(outfld_name_suffix)
-
- if ( hist_fld_active(name_out1).or.hist_fld_active(name_out2)) then
- lchnk = state%lchnk
- ncol = state%ncol
-
- mr_cnst = rearth**3/gravit
- mo_cnst = omega*rearth**4/gravit
-
- mr = 0.0_r8
- mo = 0.0_r8
- do k = 1, pver
- do i = 1, ncol
+
+ mr_cnst = rga*rearth**3
+ mo_cnst = rga*omega*rearth**4
+
+ mr = 0.0_r8
+ mo = 0.0_r8
+ do k = 1, pver
+ do i = 1, ncol
cos_lat = cos(state%lat(i))
mr_tmp = mr_cnst*state%u(i,k)*state%pdel(i,k)*cos_lat
mo_tmp = mo_cnst*state%pdel(i,k)*cos_lat**2
-
+
mr(i) = mr(i) + mr_tmp
mo(i) = mo(i) + mo_tmp
- end do
- end do
- call outfld(name_out1 ,mr, pcols,lchnk )
- call outfld(name_out2 ,mo, pcols,lchnk )
- end if
- end subroutine calc_te_and_aam_budgets
+ end do
+ end do
+
+ call outfld(name_out(mridx) ,mr, pcols,lchnk )
+ call outfld(name_out(moidx) ,mo, pcols,lchnk )
+
+ end subroutine tot_energy_phys
end module check_energy
diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90
index 8a9c35bfd2..07444cbfa3 100644
--- a/src/physics/cam/clubb_intr.F90
+++ b/src/physics/cam/clubb_intr.F90
@@ -17,23 +17,24 @@ module clubb_intr
! !
!----------------------------------------------------------------------------------------------------- !
- use shr_kind_mod, only: r8=>shr_kind_r8
- use ppgrid, only: pver, pverp, pcols, begchunk, endchunk
- use phys_control, only: phys_getopts
- use physconst, only: cpair, gravit, rga, latvap, latice, zvir, rh2o, karman
- use air_composition, only: rairv, cpairv
-
- use spmd_utils, only: masterproc
- use constituents, only: pcnst, cnst_add
- use pbl_utils, only: calc_ustar, calc_obklen
- use ref_pres, only: top_lev => trop_cloud_top_lev
- use zm_conv_intr, only: zmconv_microp
+ use shr_kind_mod, only: r8=>shr_kind_r8
+ use ppgrid, only: pver, pverp, pcols, begchunk, endchunk
+ use phys_control, only: phys_getopts
+ use physconst, only: cpair, gravit, rga, latvap, latice, zvir, rh2o, karman
+ use air_composition, only: rairv, cpairv
+ use cam_history_support, only: max_fieldname_len
+
+ use spmd_utils, only: masterproc
+ use constituents, only: pcnst, cnst_add
+ use pbl_utils, only: calc_ustar, calc_obklen
+ use ref_pres, only: top_lev => trop_cloud_top_lev
+ use zm_conv_intr, only: zmconv_microp
#ifdef CLUBB_SGS
- use clubb_api_module, only: pdf_parameter, implicit_coefs_terms
- use clubb_api_module, only: clubb_config_flags_type, grid, stats, nu_vertical_res_dep
- use clubb_api_module, only: nparams
- use clubb_mf, only: do_clubb_mf, do_clubb_mf_diag
- use cloud_fraction, only: dp1, dp2
+ use clubb_api_module, only: pdf_parameter, implicit_coefs_terms
+ use clubb_api_module, only: clubb_config_flags_type, grid, stats, nu_vertical_res_dep
+ use clubb_api_module, only: nparams
+ use clubb_mf, only: do_clubb_mf, do_clubb_mf_diag
+ use cloud_fraction, only: dp1, dp2
#endif
implicit none
@@ -4305,7 +4306,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, &
temp1 = trim(stats_zt(1)%file%grid_avg_var(j)%name)
sub = temp1
- if (len(temp1) > 16) sub = temp1(1:16)
+ if (len(temp1) > max_fieldname_len) sub = temp1(1:max_fieldname_len)
call outfld(trim(sub), out_zt(:,:,j), pcols, lchnk )
enddo
@@ -4314,7 +4315,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, &
temp1 = trim(stats_zm(1)%file%grid_avg_var(j)%name)
sub = temp1
- if (len(temp1) > 16) sub = temp1(1:16)
+ if (len(temp1) > max_fieldname_len) sub = temp1(1:max_fieldname_len)
call outfld(trim(sub),out_zm(:,:,j), pcols, lchnk)
enddo
@@ -5020,7 +5021,7 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, &
temp1 = trim(stats_zt%file%grid_avg_var(i)%name)
sub = temp1
- if (len(temp1) > 16) sub = temp1(1:16)
+ if (len(temp1) > max_fieldname_len) sub = temp1(1:max_fieldname_len)
call addfld(trim(sub),(/ 'ilev' /),&
'A',trim(stats_zt%file%grid_avg_var(i)%units),trim(stats_zt%file%grid_avg_var(i)%description))
@@ -5030,7 +5031,7 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, &
temp1 = trim(stats_zm%file%grid_avg_var(i)%name)
sub = temp1
- if (len(temp1) > 16) sub = temp1(1:16)
+ if (len(temp1) > max_fieldname_len) sub = temp1(1:max_fieldname_len)
call addfld(trim(sub),(/ 'ilev' /),&
'A',trim(stats_zm%file%grid_avg_var(i)%units),trim(stats_zm%file%grid_avg_var(i)%description))
diff --git a/src/physics/cam/constituents.F90 b/src/physics/cam/constituents.F90
index 9d47652318..cda9c82db4 100644
--- a/src/physics/cam/constituents.F90
+++ b/src/physics/cam/constituents.F90
@@ -72,7 +72,6 @@ module constituents
character(len=16), public :: fixcnam (pcnst) ! names of species slt fixer tendencies
character(len=16), public :: tendnam (pcnst) ! names of total tendencies of species
character(len=16), public :: ptendnam (pcnst) ! names of total physics tendencies of species
-character(len=16), public :: dmetendnam(pcnst) ! names of dme adjusted tracers (FV)
character(len=16), public :: sflxnam (pcnst) ! names of surface fluxes of species
character(len=16), public :: tottnam (pcnst) ! names for horz + vert + fixer tendencies
@@ -497,7 +496,6 @@ subroutine cnst_chk_dim
fixcnam (m) = 'DF'//cnst_name(m)
tendnam (m) = 'TE'//cnst_name(m)
ptendnam (m) = 'PTE'//cnst_name(m)
- dmetendnam(m) = 'DME'//cnst_name(m)
tottnam (m) = 'TA'//cnst_name(m)
sflxnam(m) = 'SF'//cnst_name(m)
end do
diff --git a/src/physics/cam/cospsimulator_intr.F90 b/src/physics/cam/cospsimulator_intr.F90
index 7dea97d94e..855a8e82d5 100644
--- a/src/physics/cam/cospsimulator_intr.F90
+++ b/src/physics/cam/cospsimulator_intr.F90
@@ -220,7 +220,7 @@ module cospsimulator_intr
! pbuf indices
integer :: cld_idx, concld_idx, lsreffrain_idx, lsreffsnow_idx, cvreffliq_idx
integer :: cvreffice_idx, dpcldliq_idx, dpcldice_idx
- integer :: shcldliq_idx, shcldice_idx, shcldliq1_idx, shcldice1_idx, dpflxprc_idx
+ integer :: shcldliq1_idx, shcldice1_idx, dpflxprc_idx
integer :: dpflxsnw_idx, shflxprc_idx, shflxsnw_idx, lsflxprc_idx, lsflxsnw_idx
integer :: rei_idx, rel_idx
@@ -687,7 +687,7 @@ subroutine cospsimulator_intr_init()
use mod_cosp_config, only : R_UNDEF
integer :: ncid,latid,lonid,did,hrid,minid,secid, istat
- integer :: i
+ integer :: i, ierr
! ISCCP OUTPUTS
if (lisccp_sim) then
@@ -1164,14 +1164,12 @@ subroutine cospsimulator_intr_init()
cvreffice_idx = pbuf_get_index('CV_REFFICE')
dpcldliq_idx = pbuf_get_index('DP_CLDLIQ')
dpcldice_idx = pbuf_get_index('DP_CLDICE')
- shcldliq_idx = pbuf_get_index('SH_CLDLIQ')
- shcldice_idx = pbuf_get_index('SH_CLDICE')
shcldliq1_idx = pbuf_get_index('SH_CLDLIQ1')
shcldice1_idx = pbuf_get_index('SH_CLDICE1')
dpflxprc_idx = pbuf_get_index('DP_FLXPRC')
dpflxsnw_idx = pbuf_get_index('DP_FLXSNW')
- shflxprc_idx = pbuf_get_index('SH_FLXPRC')
- shflxsnw_idx = pbuf_get_index('SH_FLXSNW')
+ shflxprc_idx = pbuf_get_index('SH_FLXPRC', errcode=ierr)
+ shflxsnw_idx = pbuf_get_index('SH_FLXSNW', errcode=ierr)
lsflxprc_idx = pbuf_get_index('LS_FLXPRC')
lsflxsnw_idx = pbuf_get_index('LS_FLXSNW')
@@ -1411,6 +1409,7 @@ subroutine cospsimulator_intr_run(state,pbuf, cam_in,emis,coszrs,cld_swtau_in,sn
real(r8), pointer, dimension(:,:) :: cv_reffice ! convective cld ice effective drop size (microns)
!! precip flux pointers (use for cam4 or cam5)
+ real(r8), target, dimension(pcols,pverp) :: zero_ifc ! zero array for interface fields not in the pbuf
! Added pointers; pbuff in zm_conv_intr.F90, calc in zm_conv.F90
real(r8), pointer, dimension(:,:) :: dp_flxprc ! deep interface gbm flux_convective_cloud_rain+snow (kg m^-2 s^-1)
real(r8), pointer, dimension(:,:) :: dp_flxsnw ! deep interface gbm flux_convective_cloud_snow (kg m^-2 s^-1)
@@ -1567,6 +1566,8 @@ subroutine cospsimulator_intr_run(state,pbuf, cam_in,emis,coszrs,cld_swtau_in,sn
lchnk = state%lchnk ! state variable contains a number of columns, one chunk
ncol = state%ncol ! number of columns in the chunk
+ zero_ifc = 0._r8
+
! Initialize temporary variables as R_UNDEF - need to do this otherwise array expansion puts garbage in history
! file for columns over which COSP did make calculations.
tmp(1:pcols) = R_UNDEF
@@ -1807,8 +1808,16 @@ subroutine cospsimulator_intr_run(state,pbuf, cam_in,emis,coszrs,cld_swtau_in,sn
!! precipitation fluxes (use for both cam4 and cam5 for now....)
call pbuf_get_field(pbuf, dpflxprc_idx, dp_flxprc )
call pbuf_get_field(pbuf, dpflxsnw_idx, dp_flxsnw )
- call pbuf_get_field(pbuf, shflxprc_idx, sh_flxprc )
- call pbuf_get_field(pbuf, shflxsnw_idx, sh_flxsnw )
+ if (shflxprc_idx > 0) then
+ call pbuf_get_field(pbuf, shflxprc_idx, sh_flxprc )
+ else
+ sh_flxprc => zero_ifc
+ end if
+ if (shflxsnw_idx > 0) then
+ call pbuf_get_field(pbuf, shflxsnw_idx, sh_flxsnw )
+ else
+ sh_flxsnw => zero_ifc
+ end if
call pbuf_get_field(pbuf, lsflxprc_idx, ls_flxprc )
call pbuf_get_field(pbuf, lsflxsnw_idx, ls_flxsnw )
diff --git a/src/physics/cam/geopotential.F90 b/src/physics/cam/geopotential.F90
index b06b145e51..93e99644ac 100644
--- a/src/physics/cam/geopotential.F90
+++ b/src/physics/cam/geopotential.F90
@@ -20,102 +20,9 @@ module geopotential
private
save
- public geopotential_dse
public geopotential_t
contains
-!===============================================================================
- subroutine geopotential_dse( &
- piln , pmln , pint , pmid , pdel , rpdel , &
- dse , q , phis , rair , gravit , cpair , &
- zvir , t , zi , zm , ncol )
-!-----------------------------------------------------------------------
-!
-! Purpose:
-! Compute the temperature and geopotential height (above the surface) at the
-! midpoints and interfaces from the input dry static energy and pressures.
-!
-!-----------------------------------------------------------------------
-!------------------------------Arguments--------------------------------
-!
-! Input arguments
- integer, intent(in) :: ncol ! Number of longitudes
-
- ! rair, and cpair are passed in as slices of rank 3 arrays allocated
- ! at runtime. Don't specify size to avoid temporary copy.
- real(r8), intent(in) :: piln (:,:) ! (pcols,pverp) - Log interface pressures
- real(r8), intent(in) :: pmln (:,:) ! (pcols,pver) - Log midpoint pressures
- real(r8), intent(in) :: pint (:,:) ! (pcols,pverp) - Interface pressures
- real(r8), intent(in) :: pmid (:,:) ! (pcols,pver) - Midpoint pressures
- real(r8), intent(in) :: pdel (:,:) ! (pcols,pver) - layer thickness
- real(r8), intent(in) :: rpdel(:,:) ! (pcols,pver) - inverse of layer thickness
- real(r8), intent(in) :: dse (:,:) ! (pcols,pver) - dry static energy
- real(r8), intent(in) :: q (:,:) ! (pcols,pver) - specific humidity
- real(r8), intent(in) :: phis (:) ! (pcols) - surface geopotential
- real(r8), intent(in) :: rair (:,:) ! - Gas constant for dry air
- real(r8), intent(in) :: gravit ! - Acceleration of gravity
- real(r8), intent(in) :: cpair(:,:) ! - specific heat at constant p for dry air
- real(r8), intent(in) :: zvir (:,:) ! (pcols,pver) - rh2o/rair - 1
-
-! Output arguments
-
- real(r8), intent(out) :: t(:,:) ! (pcols,pver) - temperature
- real(r8), intent(out) :: zi(:,:) ! (pcols,pverp) - Height above surface at interfaces
- real(r8), intent(out) :: zm(:,:) ! (pcols,pver) - Geopotential height at mid level
-!
-!---------------------------Local variables-----------------------------------------
-!
- logical :: calc1 ! switch for calculation method
- integer :: i,k ! Lon, level, level indices
- real(r8) :: hkk(ncol) ! diagonal element of hydrostatic matrix
- real(r8) :: hkl(ncol) ! off-diagonal element
- real(r8) :: rog(ncol,pver) ! Rair / gravit
- real(r8) :: tv ! virtual temperature
- real(r8) :: tvfac ! Tv/T
-!
-!----------------------------------------------------------------------------------
- rog(:ncol,:) = rair(:ncol,:) / gravit
-
-! set calculation method based on dycore type
- calc1 = dycore_is ('LR').or.dycore_is('FV3')
-
-! The surface height is zero by definition.
- do i = 1,ncol
- zi(i,pverp) = 0.0_r8
- end do
-
-! Compute the virtual temperature, zi, zm from bottom up
-! Note, zi(i,k) is the interface above zm(i,k)
- do k = pver, 1, -1
-
-! First set hydrostatic elements consistent with dynamics
- if (calc1) then
- do i = 1,ncol
- hkl(i) = piln(i,k+1) - piln(i,k)
- hkk(i) = 1._r8 - pint(i,k) * hkl(i) * rpdel(i,k)
- end do
- else
- do i = 1,ncol
- hkl(i) = pdel(i,k) / pmid(i,k)
- hkk(i) = 0.5_r8 * hkl(i)
- end do
- end if
-
-! Now compute tv, t, zm, zi
- do i = 1,ncol
- tvfac = 1._r8 + zvir(i,k) * q(i,k)
- tv = (dse(i,k) - phis(i) - gravit*zi(i,k+1)) / ((cpair(i,k) / tvfac) + &
- rair(i,k)*hkk(i))
-
- t (i,k) = tv / tvfac
-
- zm(i,k) = zi(i,k+1) + rog(i,k) * tv * hkk(i)
- zi(i,k) = zi(i,k+1) + rog(i,k) * tv * hkl(i)
- end do
- end do
-
- return
- end subroutine geopotential_dse
!===============================================================================
subroutine geopotential_t( &
@@ -132,7 +39,7 @@ subroutine geopotential_t( &
!-----------------------------------------------------------------------
use ppgrid, only : pcols
-
+use air_composition, only: thermodynamic_active_species_num,thermodynamic_active_species_idx
!------------------------------Arguments--------------------------------
!
! Input arguments
@@ -146,7 +53,7 @@ subroutine geopotential_t( &
real(r8), intent(in) :: pdel (:,:) ! (pcols,pver) - layer thickness
real(r8), intent(in) :: rpdel(:,:) ! (pcols,pver) - inverse of layer thickness
real(r8), intent(in) :: t (:,:) ! (pcols,pver) - temperature
- real(r8), intent(in) :: q (:,:) ! (pcols,pver) - specific humidity
+ real(r8), intent(in) :: q (:,:,:) ! (pcols,pver,:)- tracers (moist mixing ratios)
real(r8), intent(in) :: rair (:,:) ! (pcols,pver) - Gas constant for dry air
real(r8), intent(in) :: gravit ! - Acceleration of gravity
real(r8), intent(in) :: zvir (:,:) ! (pcols,pver) - rh2o/rair - 1
@@ -158,12 +65,15 @@ subroutine geopotential_t( &
!
!---------------------------Local variables-----------------------------
!
- integer :: i,k ! Lon, level indices
+ integer :: i,k,idx ! Lon, level indices, water species index
real(r8) :: hkk(ncol) ! diagonal element of hydrostatic matrix
real(r8) :: hkl(ncol) ! off-diagonal element
real(r8) :: rog(ncol,pver) ! Rair / gravit
real(r8) :: tv ! virtual temperature
real(r8) :: tvfac ! Tv/T
+ real(r8) :: qfac(ncol,pver) ! factor to convert from wet to dry mixing ratio
+ real(r8) :: sum_dry_mixing_ratio(ncol,pver)! sum of dry water mixing ratios
+
!
!-----------------------------------------------------------------------
!
@@ -175,40 +85,105 @@ subroutine geopotential_t( &
zi(i,pverp) = 0.0_r8
end do
-! Compute zi, zm from bottom up.
-! Note, zi(i,k) is the interface above zm(i,k)
-
- do k = pver, 1, -1
-
-! First set hydrostatic elements consistent with dynamics
-
- if ((dycore_is('LR') .or. dycore_is('FV3'))) then
+ ! Compute zi, zm from bottom up.
+ ! Note, zi(i,k) is the interface above zm(i,k)
+
+ !
+ ! original code for backwards compatability with FV and EUL
+ !
+ if (.not.(dycore_is('MPAS') .or. dycore_is('SE'))) then
+ do k = pver, 1, -1
+
+ ! First set hydrostatic elements consistent with dynamics
+
+ if ((dycore_is('LR') .or. dycore_is('FV3'))) then
+ do i = 1,ncol
+ hkl(i) = piln(i,k+1) - piln(i,k)
+ hkk(i) = 1._r8 - pint(i,k) * hkl(i) * rpdel(i,k)
+ end do
+ else
+ do i = 1,ncol
+ hkl(i) = pdel(i,k) / pmid(i,k)
+ hkk(i) = 0.5_r8 * hkl(i)
+ end do
+ end if
+
+ ! Now compute tv, zm, zi
+
do i = 1,ncol
- hkl(i) = piln(i,k+1) - piln(i,k)
- hkk(i) = 1._r8 - pint(i,k) * hkl(i) * rpdel(i,k)
+ tvfac = 1._r8 + zvir(i,k) * q(i,k,1)
+ tv = t(i,k) * tvfac
+
+ zm(i,k) = zi(i,k+1) + rog(i,k) * tv * hkk(i)
+ zi(i,k) = zi(i,k+1) + rog(i,k) * tv * hkl(i)
+ end do
+ end do
+ else
+ !
+ ! For the computation of generalized virtual temperature (equation 16
+ ! in Lauritzen et al. (2018); https://doi.org/10.1029/2017MS001257)
+ !
+ ! Compute factor for converting wet to dry mixing ratio (eq.7)
+ !
+ qfac = 1.0_r8
+ do idx = 1,thermodynamic_active_species_num
+ do k = 1,pver
+ do i = 1,ncol
+ qfac(i,k) = qfac(i,k)-q(i,k,thermodynamic_active_species_idx(idx))
+ end do
+ end do
+ end do
+ qfac = 1.0_r8/qfac
+
+ ! Compute sum of dry water mixing ratios
+ sum_dry_mixing_ratio = 1.0_r8
+ do idx = 1,thermodynamic_active_species_num
+ do k = 1,pver
+ do i = 1,ncol
+ sum_dry_mixing_ratio(i,k) = sum_dry_mixing_ratio(i,k)&
+ +q(i,k,thermodynamic_active_species_idx(idx))*qfac(i,k)
+ end do
end do
- else!MPAS, SE or EUL
+ end do
+ sum_dry_mixing_ratio(:,:) = 1.0_r8/sum_dry_mixing_ratio(:,:)
+ ! Compute zi, zm from bottom up.
+ ! Note, zi(i,k) is the interface above zm(i,k)
+ do k = pver, 1, -1
+
+ ! First set hydrostatic elements consistent with dynamics
+
!
- ! For EUL and SE: pmid = 0.5*(pint(k+1)+pint(k))
- ! For MPAS : pmid is computed from theta_m, rhodry, etc.
+ ! the outcommented code is left for when/if we will support
+ ! FV3 and/or FV with condensate loading
!
+
+! if ((dycore_is('LR') .or. dycore_is('FV3'))) then
+! do i = 1,ncol
+! hkl(i) = piln(i,k+1) - piln(i,k)
+! hkk(i) = 1._r8 - pint(i,k) * hkl(i) * rpdel(i,k)
+! end do
+! else!MPAS, SE or EUL
+ !
+ ! For SE : pmid = 0.5*(pint(k+1)+pint(k))
+ ! For MPAS : pmid is computed from theta_m, rhodry, etc.
+ !
+ do i = 1,ncol
+ hkl(i) = pdel(i,k) / pmid(i,k)
+ hkk(i) = 0.5_r8 * hkl(i)
+ end do
+! end if
+
+ ! Now compute tv, zm, zi
+
do i = 1,ncol
- hkl(i) = pdel(i,k) / pmid(i,k)
- hkk(i) = 0.5_r8 * hkl(i)
- end do
- end if
-
-! Now compute tv, zm, zi
-
- do i = 1,ncol
- tvfac = 1._r8 + zvir(i,k) * q(i,k)
+ tvfac = (1._r8 + (zvir(i,k)+1.0_r8) * q(i,k,1)*qfac(i,k))*sum_dry_mixing_ratio(i,k)
tv = t(i,k) * tvfac
-
+
zm(i,k) = zi(i,k+1) + rog(i,k) * tv * hkk(i)
zi(i,k) = zi(i,k+1) + rog(i,k) * tv * hkl(i)
- end do
- end do
-
+ end do
+ end do
+ end if
return
end subroutine geopotential_t
end module geopotential
diff --git a/src/physics/cam/hetfrz_classnuc.F90 b/src/physics/cam/hetfrz_classnuc.F90
index f0afa46525..effb978718 100644
--- a/src/physics/cam/hetfrz_classnuc.F90
+++ b/src/physics/cam/hetfrz_classnuc.F90
@@ -9,11 +9,11 @@ module hetfrz_classnuc
! hetfrz_classnuc_init
! hetfrz_classnuc_calc
!
-! Author:
+! Author:
! Corinna Hoose, UiO, May 2009
-! Yong Wang and Xiaohong Liu, UWyo, 12/2012,
+! Yong Wang and Xiaohong Liu, UWyo, 12/2012,
! implement in CAM5 and constrain uncertain parameters using natural dust and
-! BC(soot) datasets.
+! BC(soot) datasets.
! Yong Wang and Xiaohong Liu, UWyo, 05/2013, implement the PDF-contact angle
! approach: Y. Wang et al., Atmos. Chem. Phys., 2014.
! Jack Chen, NCAR, 09/2015, modify calculation of dust activation fraction.
@@ -39,7 +39,7 @@ module hetfrz_classnuc
real(r8) :: pi
!*****************************************************************************
-! PDF theta model
+! PDF theta model
!*****************************************************************************
! some variables for PDF theta model
! immersion freezing
@@ -64,13 +64,16 @@ module hetfrz_classnuc
integer :: iulog
+real(r8) :: limfacbc = -huge(1._r8) ! soot ice nucleating fraction
+real(r8) :: limfacdst = -huge(1._r8) ! dust ice nucleating fraction
+
!===================================================================================================
contains
!===================================================================================================
subroutine hetfrz_classnuc_init( &
rair_in, cpair_in, rh2o_in, rhoh2o_in, mwh2o_in, &
- tmelt_in, pi_in, iulog_in)
+ tmelt_in, pi_in, iulog_in, bc_limfac_in, dust_limfac_in)
real(r8), intent(in) :: rair_in
real(r8), intent(in) :: cpair_in
@@ -80,6 +83,8 @@ subroutine hetfrz_classnuc_init( &
real(r8), intent(in) :: tmelt_in
real(r8), intent(in) :: pi_in
integer, intent(in) :: iulog_in
+ real(r8), intent(in) :: bc_limfac_in
+ real(r8), intent(in) :: dust_limfac_in
rair = rair_in
cpair = cpair_in
@@ -89,6 +94,8 @@ subroutine hetfrz_classnuc_init( &
tmelt = tmelt_in
pi = pi_in
iulog = iulog_in
+ limfacbc = bc_limfac_in
+ limfacdst = dust_limfac_in
! Initialize all the PDF theta variables:
if (pdf_imm_in) then
@@ -150,48 +157,47 @@ subroutine hetfrz_classnuc_calc( &
logical :: do_bc, do_dst1, do_dst3
real(r8), parameter :: n1 = 1.e19_r8 ! number of water molecules in contact with unit area of substrate [m-2]
- real(r8), parameter :: kboltz = 1.38e-23_r8
+ real(r8), parameter :: kboltz = 1.38e-23_r8
real(r8), parameter :: hplanck = 6.63e-34_r8
real(r8), parameter :: rhplanck = 1._r8/hplanck
- real(r8), parameter :: amu = 1.66053886e-27_r8
- real(r8), parameter :: nus = 1.e13_r8 ! frequ. of vibration [s-1] higher freq. (as in P&K, consistent with Anupam's data)
+ real(r8), parameter :: amu = 1.66053886e-27_r8
+ real(r8), parameter :: nus = 1.e13_r8 ! frequ. of vibration [s-1] higher freq. (as in P&K, consistent with Anupam's data)
real(r8), parameter :: taufrz = 195.435_r8 ! time constant for falloff of freezing rate [s]
real(r8), parameter :: rhwincloud = 0.98_r8 ! 98% RH in mixed-phase clouds (Korolev & Isaac, JAS 2006)
- real(r8), parameter :: limfacbc = 0.01_r8 ! max. ice nucleating fraction soot
- real(r8) :: tc
- real(r8) :: vwice
- real(r8) :: rhoice
- real(r8) :: sigma_iw ! [J/m2]
- real(r8) :: sigma_iv ! [J/m2]
- real(r8) :: esice ! [Pa]
- real(r8) :: eswtr ! [Pa]
- real(r8) :: rgimm
- real(r8) :: rgdep
- real(r8) :: dg0dep
- real(r8) :: Adep
- real(r8) :: dg0cnt
- real(r8) :: Acnt
- real(r8) :: rgimm_bc
- real(r8) :: rgimm_dust_a1, rgimm_dust_a3
- real(r8) :: dg0imm_bc
- real(r8) :: dg0imm_dust_a1, dg0imm_dust_a3
+ real(r8) :: tc
+ real(r8) :: vwice
+ real(r8) :: rhoice
+ real(r8) :: sigma_iw ! [J/m2]
+ real(r8) :: sigma_iv ! [J/m2]
+ real(r8) :: esice ! [Pa]
+ real(r8) :: eswtr ! [Pa]
+ real(r8) :: rgimm
+ real(r8) :: rgdep
+ real(r8) :: dg0dep
+ real(r8) :: Adep
+ real(r8) :: dg0cnt
+ real(r8) :: Acnt
+ real(r8) :: rgimm_bc
+ real(r8) :: rgimm_dust_a1, rgimm_dust_a3
+ real(r8) :: dg0imm_bc
+ real(r8) :: dg0imm_dust_a1, dg0imm_dust_a3
real(r8) :: Aimm_bc
real(r8) :: Aimm_dust_a1, Aimm_dust_a3
- real(r8) :: q, m, phi
- real(r8) :: r_bc ! model radii of BC modes [m]
- real(r8) :: r_dust_a1, r_dust_a3 ! model radii of dust modes [m]
- real(r8) :: f_imm_bc
- real(r8) :: f_imm_dust_a1, f_imm_dust_a3
+ real(r8) :: q, m, phi
+ real(r8) :: r_bc ! model radii of BC modes [m]
+ real(r8) :: r_dust_a1, r_dust_a3 ! model radii of dust modes [m]
+ real(r8) :: f_imm_bc
+ real(r8) :: f_imm_dust_a1, f_imm_dust_a3
real(r8) :: Jimm_bc
real(r8) :: Jimm_dust_a1, Jimm_dust_a3
- real(r8) :: f_dep_bc
- real(r8) :: f_dep_dust_a1, f_dep_dust_a3
- real(r8) :: Jdep_bc
- real(r8) :: Jdep_dust_a1, Jdep_dust_a3
- real(r8) :: f_cnt_bc
- real(r8) :: f_cnt_dust_a1,f_cnt_dust_a3
+ real(r8) :: f_dep_bc
+ real(r8) :: f_dep_dust_a1, f_dep_dust_a3
+ real(r8) :: Jdep_bc
+ real(r8) :: Jdep_dust_a1, Jdep_dust_a3
+ real(r8) :: f_cnt_bc
+ real(r8) :: f_cnt_dust_a1,f_cnt_dust_a3
real(r8) :: Jcnt_bc
- real(r8) :: Jcnt_dust_a1,Jcnt_dust_a3
+ real(r8) :: Jcnt_dust_a1,Jcnt_dust_a3
integer :: i
!********************************************************
@@ -245,9 +251,9 @@ subroutine hetfrz_classnuc_calc( &
sigma_iv = (76.1_r8-0.155_r8*tc + 28.5_r8+0.25_r8*tc)*1E-3_r8
! get mass mean radius
- r_bc = hetraer(1)
- r_dust_a1 = hetraer(2)
- r_dust_a3 = hetraer(3)
+ r_bc = hetraer(1)
+ r_dust_a1 = hetraer(2)
+ r_dust_a3 = hetraer(3)
! calculate collision kernels as a function of environmental parameters and aerosol/droplet sizes
call collkernel(t, p, eswtr, rhwincloud, r3lx, &
@@ -255,9 +261,9 @@ subroutine hetfrz_classnuc_calc( &
r_dust_a1, r_dust_a3, & ! dust modes
Kcoll_bc, & ! collision kernel [cm3 s-1]
Kcoll_dust_a1, Kcoll_dust_a3)
-
+
!*****************************************************************************
- ! take water activity into account
+ ! take water activity into account
!*****************************************************************************
! solute effect
aw(:) = 1._r8
@@ -267,9 +273,9 @@ subroutine hetfrz_classnuc_calc( &
! increasing total solute mole fraction. Therefore, the large solution concentration
! will cause the freezing point depression and the ice freezing temperatures of all
! IN will get close to the homogeneous ice freezing temperatures. Since we take into
- ! account water activity for three heterogeneous freezing modes(immersion, deposition,
- ! and contact), we utilize interstitial aerosols(not cloudborne aerosols) to calculate
- ! water activity.
+ ! account water activity for three heterogeneous freezing modes(immersion, deposition,
+ ! and contact), we utilize interstitial aerosols(not cloudborne aerosols) to calculate
+ ! water activity.
! If the index of IN is 0, it means three freezing modes of this aerosol are depressed.
do i = 1, 3
@@ -282,8 +288,8 @@ subroutine hetfrz_classnuc_calc( &
end do
!*****************************************************************************
- ! immersion freezing begin
- !*****************************************************************************
+ ! immersion freezing begin
+ !*****************************************************************************
frzbcimm = 0._r8
frzduimm = 0._r8
@@ -321,7 +327,7 @@ subroutine hetfrz_classnuc_calc( &
else
do_dst3 = .false.
end if
-
+
! form factor
! only consider flat surfaces due to uncertainty of curved surfaces
@@ -352,7 +358,7 @@ subroutine hetfrz_classnuc_calc( &
! 1/sqrt(f)
! the expression of Chen et al. (sqrt(f)) may however lead to unphysical
! behavior as it implies J->0 when f->0 (i.e. ice nucleation would be
- ! more difficult on easily wettable materials).
+ ! more difficult on easily wettable materials).
Jimm_dust_a1 = Aimm_dust_a1*r_dust_a1**2/SQRT(f_imm_dust_a1)*EXP((-dga_imm_dust-f_imm_dust_a1*dg0imm_dust_a1)/(kboltz*T))
Jimm_dust_a3 = Aimm_dust_a3*r_dust_a3**2/SQRT(f_imm_dust_a3)*EXP((-dga_imm_dust-f_imm_dust_a3*dg0imm_dust_a3)/(kboltz*T))
end if
@@ -372,7 +378,7 @@ subroutine hetfrz_classnuc_calc( &
end do
end if
- ! Limit to 1% of available potential IN (for BC), no limit for dust
+ ! Limit to 1% of available potential IN (for BC), no limit for dust
if (pdf_imm_in) then
sum_imm_dust_a1 = 0._r8
sum_imm_dust_a3 = 0._r8
@@ -390,38 +396,38 @@ subroutine hetfrz_classnuc_calc( &
sum_imm_dust_a3 = 1.0_r8
end if
end do
-
+
end if
if (.not.tot_in) then
if (do_bc) frzbcimm = frzbcimm+MIN(limfacbc*total_cloudborne_aer_num(id_bc)/deltat, &
- total_cloudborne_aer_num(id_bc)/deltat*(1._r8-exp(-Jimm_bc*deltat)))
+ total_cloudborne_aer_num(id_bc)/deltat*(1._r8-exp(-Jimm_bc*deltat)))
if (.not. pdf_imm_in) then
- if (do_dst1) frzduimm = frzduimm+MIN(1*total_cloudborne_aer_num(id_dst1)/deltat, &
+ if (do_dst1) frzduimm = frzduimm+MIN(limfacdst*total_cloudborne_aer_num(id_dst1)/deltat, &
total_cloudborne_aer_num(id_dst1)/deltat*(1._r8-exp(-Jimm_dust_a1*deltat)))
- if (do_dst3) frzduimm = frzduimm+MIN(1*total_cloudborne_aer_num(id_dst3)/deltat, &
+ if (do_dst3) frzduimm = frzduimm+MIN(limfacdst*total_cloudborne_aer_num(id_dst3)/deltat, &
total_cloudborne_aer_num(id_dst3)/deltat*(1._r8-exp(-Jimm_dust_a3*deltat)))
else
- if (do_dst1) frzduimm = frzduimm+MIN(1*total_cloudborne_aer_num(id_dst1)/deltat, &
+ if (do_dst1) frzduimm = frzduimm+MIN(limfacdst*total_cloudborne_aer_num(id_dst1)/deltat, &
total_cloudborne_aer_num(id_dst1)/deltat*(1._r8-sum_imm_dust_a1))
- if (do_dst3) frzduimm = frzduimm+MIN(1*total_cloudborne_aer_num(id_dst3)/deltat, &
+ if (do_dst3) frzduimm = frzduimm+MIN(limfacdst*total_cloudborne_aer_num(id_dst3)/deltat, &
total_cloudborne_aer_num(id_dst3)/deltat*(1._r8-sum_imm_dust_a3))
end if
else
- if (do_bc) frzbcimm = frzbcimm+MIN(limfacbc*fn(id_bc)*total_aer_num(id_bc)/deltat, &
- fn(id_bc)*total_aer_num(id_bc)/deltat*(1._r8-exp(-Jimm_bc*deltat)))
+ if (do_bc) frzbcimm = frzbcimm+MIN(limfacbc*fn(id_bc)*total_aer_num(id_bc)/deltat, &
+ fn(id_bc)*total_aer_num(id_bc)/deltat*(1._r8-exp(-Jimm_bc*deltat)))
if (.not. pdf_imm_in) then
- if (do_dst1) frzduimm = frzduimm+MIN(1*fn(id_dst1)*total_aer_num(id_dst1)/deltat, &
+ if (do_dst1) frzduimm = frzduimm+MIN(limfacdst*fn(id_dst1)*total_aer_num(id_dst1)/deltat, &
fn(id_dst1)*total_aer_num(id_dst1)/deltat*(1._r8-exp(-Jimm_dust_a1*deltat)))
- if (do_dst3) frzduimm = frzduimm+MIN(1*fn(id_dst3)*total_aer_num(id_dst3)/deltat, &
+ if (do_dst3) frzduimm = frzduimm+MIN(limfacdst*fn(id_dst3)*total_aer_num(id_dst3)/deltat, &
fn(id_dst3)*total_aer_num(id_dst3)/deltat*(1._r8-exp(-Jimm_dust_a3*deltat)))
else
- if (do_dst1) frzduimm = frzduimm+MIN(1*fn(id_dst1)*total_aer_num(id_dst1)/deltat, &
+ if (do_dst1) frzduimm = frzduimm+MIN(limfacdst*fn(id_dst1)*total_aer_num(id_dst1)/deltat, &
fn(id_dst1)*total_aer_num(id_dst1)/deltat*(1._r8-sum_imm_dust_a1))
- if (do_dst3) frzduimm = frzduimm+MIN(1*fn(id_dst3)*total_aer_num(id_dst3)/deltat, &
+ if (do_dst3) frzduimm = frzduimm+MIN(limfacdst*fn(id_dst3)*total_aer_num(id_dst3)/deltat, &
fn(id_dst3)*total_aer_num(id_dst3)/deltat*(1._r8-sum_imm_dust_a3))
end if
end if
@@ -436,7 +442,7 @@ subroutine hetfrz_classnuc_calc( &
!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! critical germ size
! assume 98% RH in mixed-phase clouds (Korolev & Isaac, JAS 2006)
- rgdep=2*vwice*sigma_iv/(kboltz*t*LOG(rhwincloud*supersatice))
+ rgdep=2*vwice*sigma_iv/(kboltz*t*LOG(rhwincloud*supersatice))
! form factor
m = COS(theta_dep_bc*pi/180._r8)
@@ -466,30 +472,30 @@ subroutine hetfrz_classnuc_calc( &
Jdep_dust_a3 = 0._r8
end if
- ! Limit to 1% of available potential IN (for BC), no limit for dust
+ ! Limit available potential IN (for BC and dust)
if (.not.tot_in) then
if (do_bc) frzbcdep = frzbcdep+MIN(limfacbc*uncoated_aer_num(id_bc)/deltat, &
uncoated_aer_num(id_bc)/deltat &
- *(1._r8-exp(-Jdep_bc*deltat)))
- if (do_dst1) frzdudep = frzdudep+MIN(uncoated_aer_num(id_dst1)/deltat, &
+ *(1._r8-exp(-Jdep_bc*deltat)))
+ if (do_dst1) frzdudep = frzdudep+MIN(limfacdst*uncoated_aer_num(id_dst1)/deltat, &
uncoated_aer_num(id_dst1)/deltat &
*(1._r8-exp(-Jdep_dust_a1*deltat)))
- if (do_dst3) frzdudep = frzdudep+MIN(uncoated_aer_num(id_dst3)/deltat, &
+ if (do_dst3) frzdudep = frzdudep+MIN(limfacdst*uncoated_aer_num(id_dst3)/deltat, &
uncoated_aer_num(id_dst3)/deltat &
*(1._r8-exp(-Jdep_dust_a3*deltat)))
else
if (do_bc) frzbcdep = frzbcdep+MIN(limfacbc*(1._r8-fn(id_bc)) &
*(1._r8-dstcoat(1))*total_aer_num(id_bc)/deltat, &
(1._r8-fn(id_bc))*(1._r8-dstcoat(1))*total_aer_num(id_bc)/deltat &
- *(1._r8-exp(-Jdep_bc*deltat)))
- if (do_dst1) frzdudep = frzdudep+MIN((1._r8-fn(id_dst1)) &
+ *(1._r8-exp(-Jdep_bc*deltat)))
+ if (do_dst1) frzdudep = frzdudep+MIN(limfacdst*(1._r8-fn(id_dst1)) &
*(1._r8-dstcoat(2))*total_aer_num(id_dst1)/deltat, &
(1._r8-fn(id_dst1))*(1._r8-dstcoat(2))*total_aer_num(id_dst1)/deltat &
- *(1._r8-exp(-Jdep_dust_a1*deltat)))
- if (do_dst3) frzdudep = frzdudep+MIN((1._r8-fn(id_dst3)) &
+ *(1._r8-exp(-Jdep_dust_a1*deltat)))
+ if (do_dst3) frzdudep = frzdudep+MIN(limfacdst*(1._r8-fn(id_dst3)) &
*(1._r8-dstcoat(3))*total_aer_num(id_dst3)/deltat, &
(1._r8-fn(id_dst3))*(1._r8-dstcoat(3))*total_aer_num(id_dst3)/deltat &
- *(1._r8-exp(-Jdep_dust_a3*deltat)))
+ *(1._r8-exp(-Jdep_dust_a3*deltat)))
end if
!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -518,31 +524,31 @@ subroutine hetfrz_classnuc_calc( &
Jcnt_dust_a1 = Acnt*r_dust_a1**2*EXP((-dga_dep_dust-f_cnt_dust_a1*dg0cnt)/(kboltz*T))*Kcoll_dust_a1*icnlx
Jcnt_dust_a3 = Acnt*r_dust_a3**2*EXP((-dga_dep_dust-f_cnt_dust_a3*dg0cnt)/(kboltz*T))*Kcoll_dust_a3*icnlx
- ! Limit to 1% of available potential IN (for BC), no limit for dust
+ ! Limit available potential IN (for BC and dust)
if (.not.tot_in) then
if (do_bc) frzbccnt = frzbccnt+MIN(limfacbc*uncoated_aer_num(id_bc)/deltat, &
uncoated_aer_num(id_bc)/deltat &
- *(1._r8-exp(-Jcnt_bc*deltat)))
- if (do_dst1) frzducnt = frzducnt+MIN(uncoated_aer_num(id_dst1)/deltat, &
+ *(1._r8-exp(-Jcnt_bc*deltat)))
+ if (do_dst1) frzducnt = frzducnt+MIN(limfacdst*uncoated_aer_num(id_dst1)/deltat, &
uncoated_aer_num(id_dst1)/deltat &
*(1._r8-exp(-Jcnt_dust_a1*deltat)))
- if (do_dst3) frzducnt = frzducnt+MIN(uncoated_aer_num(id_dst3)/deltat, &
+ if (do_dst3) frzducnt = frzducnt+MIN(limfacdst*uncoated_aer_num(id_dst3)/deltat, &
uncoated_aer_num(id_dst3)/deltat &
*(1._r8-exp(-Jcnt_dust_a3*deltat)))
else
if (do_bc) frzbccnt = frzbccnt+MIN(limfacbc*(1._r8-fn(id_bc))*(1._r8-dstcoat(1))*total_aer_num(id_bc)/deltat, &
(1._r8-fn(id_bc))*(1._r8-dstcoat(1))*total_aer_num(id_bc)/deltat &
- *(1._r8-exp(-Jcnt_bc*deltat)))
- if (do_dst1) frzducnt = frzducnt+MIN((1._r8-fn(id_dst1))*(1._r8-dstcoat(2))*total_aer_num(id_dst1)/deltat, &
+ *(1._r8-exp(-Jcnt_bc*deltat)))
+ if (do_dst1) frzducnt = frzducnt+MIN(limfacdst*(1._r8-fn(id_dst1))*(1._r8-dstcoat(2))*total_aer_num(id_dst1)/deltat, &
(1._r8-fn(id_dst1))*(1._r8-dstcoat(2))*total_aer_num(id_dst1)/deltat &
*(1._r8-exp(-Jcnt_dust_a1*deltat)))
- if (do_dst3) frzducnt = frzducnt+MIN((1._r8-fn(id_dst3))*(1._r8-dstcoat(3))*total_aer_num(id_dst3)/deltat, &
+ if (do_dst3) frzducnt = frzducnt+MIN(limfacdst*(1._r8-fn(id_dst3))*(1._r8-dstcoat(3))*total_aer_num(id_dst3)/deltat, &
(1._r8-fn(id_dst3))*(1._r8-dstcoat(3))*total_aer_num(id_dst3)/deltat &
*(1._r8-exp(-Jcnt_dust_a3*deltat)))
end if
-
+
if (frzducnt <= -1._r8) then
- write(iulog,*) 'hetfrz_classnuc_calc: frzducnt', frzducnt, Jcnt_dust_a1,Jcnt_dust_a3, &
+ write(iulog,*) 'hetfrz_classnuc_calc: frzducnt', frzducnt, Jcnt_dust_a1,Jcnt_dust_a3, &
Kcoll_dust_a1, Kcoll_dust_a3
errstring = 'ERROR in hetfrz_classnuc_calc::frzducnt'
return
@@ -607,7 +613,7 @@ subroutine collkernel( &
real(r8) :: K_total ! total collision kernel [cm3 s-1]
integer :: i
!------------------------------------------------------------------------------------------------
-
+
Kcoll_bc = 0._r8
Kcoll_dust_a1 = 0._r8
Kcoll_dust_a3 = 0._r8
@@ -640,11 +646,11 @@ subroutine collkernel( &
! Prandtl number
Pr = viscos_air*cpair/Ktherm_air
! water vapor diffusivity: Pruppacher & Klett 13-3
- Dvap = 0.211e-4_r8*(t/273.15_r8)*(101325._r8/pres)
+ Dvap = 0.211e-4_r8*(t/273.15_r8)*(101325._r8/pres)
! G-factor = rhoh2o*Xi in Rogers & Yau, p. 104
G = rhoh2o/((latvap/(rh2o*t) - 1)*latvap*rhoh2o/(Ktherm_air*t) &
+ rhoh2o*rh2o*t/(Dvap*eswtr))
-
+
! variables depending on aerosol radius
! loop over 3 aerosol modes
do i = 1, 3
@@ -680,9 +686,9 @@ subroutine collkernel( &
if (i == 1) Kcoll_bc = K_total
if (i == 2) Kcoll_dust_a1 = K_total
if (i == 3) Kcoll_dust_a3 = K_total
-
+
end do
-
+
end subroutine collkernel
!===================================================================================================
diff --git a/src/physics/cam/hetfrz_classnuc_cam.F90 b/src/physics/cam/hetfrz_classnuc_cam.F90
index 83542f0281..9c5794eae7 100644
--- a/src/physics/cam/hetfrz_classnuc_cam.F90
+++ b/src/physics/cam/hetfrz_classnuc_cam.F90
@@ -39,11 +39,12 @@ module hetfrz_classnuc_cam
hetfrz_classnuc_cam_readnl, &
hetfrz_classnuc_cam_register, &
hetfrz_classnuc_cam_init, &
- hetfrz_classnuc_cam_calc, &
- hetfrz_classnuc_cam_save_cbaero
+ hetfrz_classnuc_cam_calc
! Namelist variables
logical :: hist_hetfrz_classnuc = .false.
+real(r8) :: hetfrz_bc_scalfac = -huge(1._r8) ! scaling factor for BC
+real(r8) :: hetfrz_dust_scalfac = -huge(1._r8) ! scaling factor for dust
! Vars set via init method.
real(r8) :: mincld ! minimum allowed cloud fraction
@@ -143,7 +144,7 @@ subroutine hetfrz_classnuc_cam_readnl(nlfile)
use namelist_utils, only: find_group_name
use units, only: getunit, freeunit
- use mpishorthand
+ use spmd_utils, only: mpicom, mstrid=>masterprocid, mpi_logical, mpi_real8, mpi_success
character(len=*), intent(in) :: nlfile ! filepath for file containing namelist input
@@ -151,7 +152,7 @@ subroutine hetfrz_classnuc_cam_readnl(nlfile)
integer :: unitn, ierr
character(len=*), parameter :: subname = 'hetfrz_classnuc_cam_readnl'
- namelist /hetfrz_classnuc_nl/ hist_hetfrz_classnuc
+ namelist /hetfrz_classnuc_nl/ hist_hetfrz_classnuc, hetfrz_bc_scalfac, hetfrz_dust_scalfac
!-----------------------------------------------------------------------------
@@ -167,13 +168,21 @@ subroutine hetfrz_classnuc_cam_readnl(nlfile)
end if
close(unitn)
call freeunit(unitn)
-
end if
-#ifdef SPMD
! Broadcast namelist variables
- call mpibcast(hist_hetfrz_classnuc, 1, mpilog, 0, mpicom)
-#endif
+ call mpi_bcast(hist_hetfrz_classnuc, 1, mpi_logical, mstrid, mpicom, ierr)
+ if (ierr /= mpi_success) call endrun(subname//" mpi_bcast: hist_hetfrz_classnuc")
+ call mpi_bcast(hetfrz_bc_scalfac, 1, mpi_real8, mstrid, mpicom, ierr)
+ if (ierr /= mpi_success) call endrun(subname//" mpi_bcast: hetfrz_bc_scalfac")
+ call mpi_bcast(hetfrz_dust_scalfac, 1, mpi_real8, mstrid, mpicom, ierr)
+ if (ierr /= mpi_success) call endrun(subname//" mpi_bcast: hetfrz_dust_scalfac")
+
+ if (masterproc) then
+ write(iulog,*) subname,': hist_hetfrz_classnuc = ',hist_hetfrz_classnuc
+ write(iulog,*) subname,': hetfrz_bc_scalfac = ',hetfrz_bc_scalfac
+ write(iulog,*) subname,': hetfrz_dust_scalfac = ',hetfrz_dust_scalfac
+ end if
end subroutine hetfrz_classnuc_cam_readnl
@@ -239,7 +248,7 @@ subroutine hetfrz_classnuc_cam_init(mincld_in)
call addfld('bc_c1_num', (/ 'lev' /), 'A', '#/cm3', 'cloud borne bc number')
call addfld('dst_c1_num', (/ 'lev' /), 'A', '#/cm3', 'cloud borne dst1 number')
call addfld('dst_c3_num', (/ 'lev' /), 'A', '#/cm3', 'cloud borne dst3 number')
-
+
call addfld('fn_bc_c1_num', (/ 'lev' /), 'A', '#/cm3', 'cloud borne bc number derived from fn')
call addfld('fn_dst_c1_num', (/ 'lev' /), 'A', '#/cm3', 'cloud borne dst1 number derived from fn')
call addfld('fn_dst_c3_num', (/ 'lev' /), 'A', '#/cm3', 'cloud borne dst3 number derived from fn')
@@ -306,7 +315,7 @@ subroutine hetfrz_classnuc_cam_init(mincld_in)
call add_default('bc_c1_num', 1, ' ')
call add_default('dst_c1_num', 1, ' ')
call add_default('dst_c3_num', 1, ' ')
-
+
call add_default('fn_bc_c1_num', 1, ' ')
call add_default('fn_dst_c1_num', 1, ' ')
call add_default('fn_dst_c3_num', 1, ' ')
@@ -328,7 +337,7 @@ subroutine hetfrz_classnuc_cam_init(mincld_in)
call add_default('BCFREZDEP', 1, ' ')
call add_default('NIMIX_IMM', 1, ' ')
- call add_default('NIMIX_CNT', 1, ' ')
+ call add_default('NIMIX_CNT', 1, ' ')
call add_default('NIMIX_DEP', 1, ' ')
call add_default('DSTNIDEP', 1, ' ')
@@ -391,7 +400,7 @@ subroutine hetfrz_classnuc_cam_init(mincld_in)
call rad_cnst_get_mode_props(0, mode_accum_idx, sigmag=sigma_logr_aer)
alnsg_mode_accum = log(sigma_logr_aer)
-
+
if (nmodes == MAM3_nmodes) then
call rad_cnst_get_mode_props(0, mode_coarse_idx, sigmag=sigma_logr_aer)
alnsg_mode_coarse = log(sigma_logr_aer)
@@ -415,7 +424,7 @@ subroutine hetfrz_classnuc_cam_init(mincld_in)
end if
! Set list indices for all constituents (mass and number) used in this module.
- ! The list is specific to the aerosol model used. Note that the order of the
+ ! The list is specific to the aerosol model used. Note that the order of the
! constituents in these lists is arbitrary.
if (nmodes == MAM3_nmodes) then
@@ -466,7 +475,7 @@ subroutine hetfrz_classnuc_cam_init(mincld_in)
num_pcarbon = 14
end if
- ! Allocate arrays to hold specie and mode indices for all constitutents (mass and number)
+ ! Allocate arrays to hold specie and mode indices for all constitutents (mass and number)
! needed in this module.
allocate(mode_idx(ncnst), spec_idx(ncnst), stat=istat)
call alloc_err(istat, routine, 'mode_idx, spec_idx', ncnst)
@@ -545,7 +554,7 @@ subroutine hetfrz_classnuc_cam_init(mincld_in)
spec_idx(pom_pcarbon) = rad_cnst_get_spec_idx(0, mode_pcarbon_idx, 'p-organic')
mode_idx(pom_pcarbon) = mode_pcarbon_idx
end if
-
+
! Check that all required specie types were found
if (any(spec_idx == -1)) then
write(iulog,*) routine//': ERROR required species type not found - indicies:', spec_idx
@@ -563,9 +572,8 @@ subroutine hetfrz_classnuc_cam_init(mincld_in)
call rad_cnst_get_aer_props(0, mode_idx(soa_accum), spec_idx(soa_accum), density_aer=specdens_soa)
call rad_cnst_get_aer_props(0, mode_idx(pom_accum), spec_idx(pom_accum), density_aer=specdens_pom)
- call hetfrz_classnuc_init( &
- rair, cpair, rh2o, rhoh2o, mwh2o, &
- tmelt, pi, iulog)
+ call hetfrz_classnuc_init(rair, cpair, rh2o, rhoh2o, mwh2o, tmelt, pi, iulog, &
+ hetfrz_bc_scalfac, hetfrz_dust_scalfac )
end subroutine hetfrz_classnuc_cam_init
@@ -579,7 +587,7 @@ subroutine hetfrz_classnuc_cam_calc( &
real(r8), intent(in) :: deltatin ! time step (s)
real(r8), intent(in) :: factnum(:,:,:) ! activation fraction for aerosol number
type(physics_buffer_desc), pointer :: pbuf(:)
-
+
! local workspace
! outputs shared with the microphysics via the pbuf
@@ -592,7 +600,7 @@ subroutine hetfrz_classnuc_cam_calc( &
real(r8) :: rho(pcols,pver) ! air density (kg m-3)
- real(r8), pointer :: ast(:,:)
+ real(r8), pointer :: ast(:,:)
real(r8) :: lcldm(pcols,pver)
@@ -611,7 +619,7 @@ subroutine hetfrz_classnuc_cam_calc( &
real(r8) :: fn_cloudborne_aer_num(pcols,pver,3)
- real(r8) :: esi(pcols), esl(pcols)
+ real(r8) :: esi(pcols), esl(pcols)
real(r8) :: con1, r3lx, supersatice
real(r8) :: qcic
@@ -664,8 +672,6 @@ subroutine hetfrz_classnuc_cam_calc( &
! Convert interstitial and cloud borne aerosols from a mass to a volume basis before
! being used in get_aer_num
do i = 1, ncnst
- aer_cb(:ncol,:,i,lchnk) = aer_cb(:ncol,:,i,lchnk) * rho(:ncol,:)
-
! Check whether constituent is a mass or number mixing ratio
if (spec_idx(i) == 0) then
call rad_cnst_get_mode_num(0, mode_idx(i), 'a', state, pbuf, ptr2d)
@@ -673,7 +679,15 @@ subroutine hetfrz_classnuc_cam_calc( &
call rad_cnst_get_aer_mmr(0, mode_idx(i), spec_idx(i), 'a', state, pbuf, ptr2d)
end if
aer(:ncol,:,i,lchnk) = ptr2d(:ncol,:) * rho(:ncol,:)
- end do
+
+ ! Check whether constituent is a mass or number mixing ratio
+ if (spec_idx(i) == 0) then
+ call rad_cnst_get_mode_num(0, mode_idx(i), 'c', state, pbuf, ptr2d)
+ else
+ call rad_cnst_get_aer_mmr(0, mode_idx(i), spec_idx(i), 'c', state, pbuf, ptr2d)
+ end if
+ aer_cb(:ncol,:,i,lchnk) = ptr2d(:ncol,:) * rho(:ncol,:)
+ end do
! Init top levels of outputs of get_aer_num
total_aer_num = 0._r8
@@ -702,8 +716,8 @@ subroutine hetfrz_classnuc_cam_calc( &
fn_cloudborne_aer_num(i,k,2) = total_aer_num(i,k,2)*factnum(i,k,mode_accum_idx) ! dst_a1
fn_cloudborne_aer_num(i,k,3) = total_aer_num(i,k,3)*factnum(i,k,mode_coarse_idx) ! dst_a3
else if (nmodes == MAM7_nmodes) then
- fn_cloudborne_aer_num(i,k,2) = total_aer_num(i,k,2)*factnum(i,k,mode_finedust_idx)
- fn_cloudborne_aer_num(i,k,3) = total_aer_num(i,k,3)*factnum(i,k,mode_coardust_idx)
+ fn_cloudborne_aer_num(i,k,2) = total_aer_num(i,k,2)*factnum(i,k,mode_finedust_idx)
+ fn_cloudborne_aer_num(i,k,3) = total_aer_num(i,k,3)*factnum(i,k,mode_coardust_idx)
end if
end do
end do
@@ -731,7 +745,7 @@ subroutine hetfrz_classnuc_cam_calc( &
call outfld('fn_bc_c1_num', fn_cloudborne_aer_num(:,:,1), pcols, lchnk)
call outfld('fn_dst_c1_num', fn_cloudborne_aer_num(:,:,2), pcols, lchnk)
call outfld('fn_dst_c3_num', fn_cloudborne_aer_num(:,:,3), pcols, lchnk)
-
+
call outfld('na500', na500, pcols, lchnk)
call outfld('totna500', tot_na500, pcols, lchnk)
@@ -739,7 +753,7 @@ subroutine hetfrz_classnuc_cam_calc( &
call pbuf_get_field(pbuf, frzimm_idx, frzimm)
call pbuf_get_field(pbuf, frzcnt_idx, frzcnt)
call pbuf_get_field(pbuf, frzdep_idx, frzdep)
-
+
frzimm(:ncol,:) = 0._r8
frzcnt(:ncol,:) = 0._r8
frzdep(:ncol,:) = 0._r8
@@ -795,8 +809,8 @@ subroutine hetfrz_classnuc_cam_calc( &
fn(2) = factnum(i,k,mode_accum_idx) ! dust_a1 accumulation mode
fn(3) = factnum(i,k,mode_coarse_idx) ! dust_a3 coarse mode
else if (nmodes == MAM7_nmodes) then
- fn(2) = factnum(i,k,mode_finedust_idx)
- fn(3) = factnum(i,k,mode_coardust_idx)
+ fn(2) = factnum(i,k,mode_finedust_idx)
+ fn(3) = factnum(i,k,mode_coardust_idx)
end if
call hetfrz_classnuc_calc( &
@@ -828,7 +842,7 @@ subroutine hetfrz_classnuc_cam_calc( &
nnudep_bc(i,k) = frzbcdep(i,k)*1.0e6_r8*ast(i,k)
nnuccc_dst(i,k) = frzduimm(i,k)*1.0e6_r8*ast(i,k)
- nnucct_dst(i,k) = frzducnt(i,k)*1.0e6_r8*ast(i,k)
+ nnucct_dst(i,k) = frzducnt(i,k)*1.0e6_r8*ast(i,k)
nnudep_dst(i,k) = frzdudep(i,k)*1.0e6_r8*ast(i,k)
niimm_bc(i,k) = frzbcimm(i,k)*1.0e6_r8*deltatin
@@ -859,7 +873,7 @@ subroutine hetfrz_classnuc_cam_calc( &
call outfld('BCFREZDEP', nnudep_bc, pcols, lchnk)
call outfld('NIMIX_IMM', niimm_bc+niimm_dst, pcols, lchnk)
- call outfld('NIMIX_CNT', nicnt_bc+nicnt_dst, pcols, lchnk)
+ call outfld('NIMIX_CNT', nicnt_bc+nicnt_dst, pcols, lchnk)
call outfld('NIMIX_DEP', nidep_bc+nidep_dst, pcols, lchnk)
call outfld('DSTNICNT', nicnt_dst, pcols, lchnk)
@@ -880,37 +894,6 @@ end subroutine hetfrz_classnuc_cam_calc
!====================================================================================================
-subroutine hetfrz_classnuc_cam_save_cbaero(state, pbuf)
-
- ! Save the required cloud borne aerosol constituents.
- type(physics_state), intent(in) :: state
- type(physics_buffer_desc), pointer :: pbuf(:)
-
- ! local variables
- integer :: i, lchnk
- real(r8), pointer :: ptr2d(:,:)
- !-------------------------------------------------------------------------------
-
- lchnk = state%lchnk
-
- ! loop over the cloud borne constituents required by this module and save
- ! a local copy
-
- do i = 1, ncnst
-
- ! Check whether constituent is a mass or number mixing ratio
- if (spec_idx(i) == 0) then
- call rad_cnst_get_mode_num(0, mode_idx(i), 'c', state, pbuf, ptr2d)
- else
- call rad_cnst_get_aer_mmr(0, mode_idx(i), spec_idx(i), 'c', state, pbuf, ptr2d)
- end if
- aer_cb(:,:,i,lchnk) = ptr2d
- end do
-
-end subroutine hetfrz_classnuc_cam_save_cbaero
-
-!====================================================================================================
-
subroutine get_aer_num(ii, kk, ncnst, aer, aer_cb, rhoair,&
total_aer_num, &
coated_aer_num, &
@@ -919,7 +902,7 @@ subroutine get_aer_num(ii, kk, ncnst, aer, aer_cb, rhoair,&
total_cloudborne_aer_num, &
hetraer, awcam, awfacm, dstcoat, &
na500, tot_na500)
-
+
!*****************************************************************************
! Purpose: Calculate BC and Dust number, including total number(interstitial+
! cloud borne), one monolayer coated number, and uncoated number
@@ -940,7 +923,7 @@ subroutine get_aer_num(ii, kk, ncnst, aer, aer_cb, rhoair,&
real(r8), intent(out) :: total_aer_num(3) ! #/cm^3
real(r8), intent(out) :: total_interstial_aer_num(3) ! #/cm^3
real(r8), intent(out) :: total_cloudborne_aer_num(3) ! #/cm^3
- real(r8), intent(out) :: coated_aer_num(3) ! #/cm^3
+ real(r8), intent(out) :: coated_aer_num(3) ! #/cm^3
real(r8), intent(out) :: uncoated_aer_num(3) ! #/cm^3
real(r8), intent(out) :: hetraer(3) ! BC and Dust mass mean radius [m]
real(r8), intent(out) :: awcam(3) ! modal added mass [mug m-3]
@@ -960,26 +943,26 @@ subroutine get_aer_num(ii, kk, ncnst, aer, aer_cb, rhoair,&
real(r8), parameter :: soa_equivso4_factor = spechygro_soa/spechygro_so4
real(r8), parameter :: pom_equivso4_factor = spechygro_pom/spechygro_so4
real(r8) :: vol_shell(3)
- real(r8) :: vol_core(3)
+ real(r8) :: vol_core(3)
real(r8) :: fac_volsfc_dust_a1, fac_volsfc_dust_a3, fac_volsfc_bc
real(r8) :: tmp1, tmp2
- real(r8) :: bc_num ! bc number in accumulation mode for MAM3
+ real(r8) :: bc_num ! bc number in accumulation mode for MAM3
! bc number in accumulation and primary carbon mode for MAM7 and MAM4
real(r8) :: dst1_num, dst3_num ! dust number in accumulation and corase mode for MAM3
! dust number in fine dust and corase dust mode for MAM7 and MAM4
- logical :: num_to_mass_in = .true.
+ logical :: num_to_mass_in = .false.
real(r8), parameter :: bc_num_to_mass = 4.669152e+17_r8 ! #/kg from emission
real(r8), parameter :: dst1_num_to_mass = 3.484e+15_r8 ! #/kg for dust in accumulation mode
- real(r8) :: dmc, ssmc
+ real(r8) :: dmc, ssmc, so4
real(r8) :: as_so4, as_du, as_soa
real(r8) :: dst1_num_imm, dst3_num_imm, bc_num_imm
- real(r8) :: dmc_imm, ssmc_imm
+ real(r8) :: dmc_imm, ssmc_imm, so4_imm
real(r8) :: as_bc, as_pom, as_ss
-
- real(r8) :: r_bc ! model radii of BC modes [m]
- real(r8) :: r_dust_a1, r_dust_a3 ! model radii of dust modes [m]
+ real(r8) :: bc4_num
+ real(r8) :: r_bc ! model radii of BC modes [m]
+ real(r8) :: r_dust_a1, r_dust_a3 ! model radii of dust modes [m]
integer :: i
real(r8) :: dst1_scale
@@ -999,9 +982,9 @@ subroutine get_aer_num(ii, kk, ncnst, aer, aer_cb, rhoair,&
tot_na500 = 0._r8
!*****************************************************************************
- ! calculate intersitial aerosol
+ ! calculate intersitial aerosol
!*****************************************************************************
-
+
if (nmodes == MAM3_nmodes .or. nmodes == MAM4_nmodes .or. nmodes == MAM5_nmodes) then
if (.not. num_to_mass_in) then
@@ -1034,26 +1017,34 @@ subroutine get_aer_num(ii, kk, ncnst, aer, aer_cb, rhoair,&
end if
dmc = aer(ii,kk,dst_coarse)
ssmc = aer(ii,kk,ncl_coarse)
-
+ so4 = aer(ii,kk,so4_coarse)
+
if (dmc > 0._r8 ) then
- dst3_num = dmc/(ssmc+dmc) * aer(ii,kk,num_coarse)*1.0e-6_r8 ! #/cm^3
+ dst3_num = dmc/(ssmc+dmc+so4) * aer(ii,kk,num_coarse)*1.0e-6_r8 ! #/cm^3
else
dst3_num = 0.0_r8
end if
if (nmodes == MAM4_nmodes .or. nmodes == MAM5_nmodes) then
- bc_num = bc_num+(aer(ii,kk,bc_pcarbon)) * bc_num_to_mass*1.0e-6_r8 ! #/cm^3
+ if (num_to_mass_in) then
+ bc_num = bc_num+(aer(ii,kk,bc_pcarbon)) * bc_num_to_mass*1.0e-6_r8 ! #/cm^3
+ else
+ as_bc = aer(ii,kk,bc_pcarbon)
+ as_pom = aer(ii,kk,pom_pcarbon)
+ bc4_num = as_bc/(as_bc+as_pom)*aer(ii,kk,num_pcarbon)*1.0e-6_r8 ! #/cm^3
+ bc_num = bc_num + bc4_num
+ end if
end if
else if (nmodes == MAM7_nmodes) then
bc_num = (aer(ii,kk,bc_accum)+aer(ii,kk,bc_pcarbon)) * bc_num_to_mass*1.0e-6_r8 ! #/cm^3
dst1_num = aer(ii,kk,num_finedust)*1.0e-6_r8 ! #/cm^3
- dst3_num = aer(ii,kk,num_coardust)*1.0e-6_r8 ! #/cm^3
+ dst3_num = aer(ii,kk,num_coardust)*1.0e-6_r8 ! #/cm^3
end if
!*****************************************************************************
- ! calculate cloud borne aerosol
- !*****************************************************************************
-
+ ! calculate cloud borne aerosol
+ !*****************************************************************************
+
if (nmodes == MAM3_nmodes .or. nmodes == MAM4_nmodes .or. nmodes == MAM5_nmodes) then
as_so4 = aer_cb(ii,kk,so4_accum)
@@ -1076,12 +1067,13 @@ subroutine get_aer_num(ii, kk, ncnst, aer, aer_cb, rhoair,&
else
bc_num_imm = 0.0_r8
end if
-
+
dmc_imm = aer_cb(ii,kk,dst_coarse)
ssmc_imm = aer_cb(ii,kk,ncl_coarse)
+ so4_imm = aer_cb(ii,kk,so4_coarse)
if (dmc_imm > 0._r8) then
- dst3_num_imm = dmc_imm/(ssmc_imm+dmc_imm) * aer_cb(ii,kk,num_coarse)*1.0e-6_r8 ! #/cm^3
+ dst3_num_imm = dmc_imm/(ssmc_imm+dmc_imm+so4_imm) * aer_cb(ii,kk,num_coarse)*1.0e-6_r8 ! #/cm^3
else
dst3_num_imm = 0.0_r8
end if
@@ -1105,16 +1097,16 @@ subroutine get_aer_num(ii, kk, ncnst, aer, aer_cb, rhoair,&
total_interstial_aer_num(1) = bc_num
total_interstial_aer_num(2) = dst1_num
- total_interstial_aer_num(3) = dst3_num
+ total_interstial_aer_num(3) = dst3_num
- total_cloudborne_aer_num(1) = bc_num_imm
- total_cloudborne_aer_num(2) = dst1_num_imm
+ total_cloudborne_aer_num(1) = bc_num_imm
+ total_cloudborne_aer_num(2) = dst1_num_imm
total_cloudborne_aer_num(3) = dst3_num_imm
-
- !*****************************************************************************
+
+ !*****************************************************************************
! calculate mass mean radius
- !*****************************************************************************
-
+ !*****************************************************************************
+
if (nmodes == MAM3_nmodes .or. nmodes == MAM4_nmodes .or. nmodes == MAM5_nmodes) then
if (nmodes == MAM3_nmodes) then
@@ -1157,7 +1149,7 @@ subroutine get_aer_num(ii, kk, ncnst, aer, aer_cb, rhoair,&
else
r_bc = 0.067e-6_r8 ! from emission size
end if
-
+
if (aer(ii,kk,dst_finedust)*1.0e-3_r8 > 1.0e-30_r8 .and. dst1_num > 1.0e-3_r8) then
r_dust_a1 = ( 3._r8/(4*pi*specdens_dust)*aer(ii,kk,dst_finedust)/(dst1_num*1.0e6_r8) )**(1._r8/3._r8)
else
@@ -1169,16 +1161,16 @@ subroutine get_aer_num(ii, kk, ncnst, aer, aer_cb, rhoair,&
else
r_dust_a3 = 1.576e-6_r8
end if
- end if
+ end if
hetraer(1) = r_bc
hetraer(2) = r_dust_a1
hetraer(3) = r_dust_a3
!*****************************************************************************
- ! calculate coated fraction
+ ! calculate coated fraction
!*****************************************************************************
-
+
if (nmodes == MAM3_nmodes .or. nmodes == MAM4_nmodes .or. nmodes == MAM5_nmodes) then
fac_volsfc_bc = exp(2.5_r8*alnsg_mode_accum**2)
@@ -1191,16 +1183,16 @@ subroutine get_aer_num(ii, kk, ncnst, aer, aer_cb, rhoair,&
vol_core(2) = aer(ii,kk,dst_accum)/(specdens_dust*rhoair)
- ! ratio1 = vol_shell/vol_core =
+ ! ratio1 = vol_shell/vol_core =
! actual hygroscopic-shell-volume/dust-core-volume
! ratio2 = 6.0_r8*dr_so4_monolayers_pcage/(dgncur_a*fac_volsfc_dust)
- ! = (shell-volume corresponding to n_so4_monolayers_pcage)/core-volume
+ ! = (shell-volume corresponding to n_so4_monolayers_pcage)/core-volume
! The 6.0/(dgncur_a*fac_volsfc_dust) = (mode-surface-area/mode-volume)
! Note that vol_shell includes both so4, pom, AND soa as "equivalent so4",
! The soa_equivso4_factor accounts for the lower hygroscopicity of soa.
!
! Define xferfrac_pcage = min( 1.0, ratio1/ratio2)
- ! But ratio1/ratio2 == tmp1/tmp2, and coding below avoids possible overflow
+ ! But ratio1/ratio2 == tmp1/tmp2, and coding below avoids possible overflow
! bc
if (nmodes == MAM3_nmodes) then
@@ -1255,10 +1247,10 @@ subroutine get_aer_num(ii, kk, ncnst, aer, aer_cb, rhoair,&
vol_shell(3) = aer(ii,kk,so4_coardust)/(specdens_so4*rhoair)
vol_core(3) = aer(ii,kk,dst_coardust)/(specdens_dust*rhoair)
- tmp1 = vol_shell(3)*(r_dust_a3*2._r8)*fac_volsfc_dust_a3
+ tmp1 = vol_shell(3)*(r_dust_a3*2._r8)*fac_volsfc_dust_a3
tmp2 = max(6.0_r8*dr_so4_monolayers_dust*vol_core(3), 0.0_r8)
dstcoat(3) = tmp1/tmp2
-
+
end if
if (dstcoat(1) > 1._r8) dstcoat(1) = 1._r8
@@ -1267,19 +1259,24 @@ subroutine get_aer_num(ii, kk, ncnst, aer, aer_cb, rhoair,&
if (dstcoat(2) < 0.001_r8) dstcoat(2) = 0.001_r8
if (dstcoat(3) > 1._r8) dstcoat(3) = 1._r8
if (dstcoat(3) < 0.001_r8) dstcoat(3) = 0.001_r8
-
+
do i = 1, 3
total_aer_num(i) = total_interstial_aer_num(i) + total_cloudborne_aer_num(i)
coated_aer_num(i) = total_interstial_aer_num(i)*dstcoat(i)
uncoated_aer_num(i) = total_interstial_aer_num(i)*(1._r8-dstcoat(i))
end do
-
+
if (nmodes == MAM4_nmodes .or. nmodes == MAM7_nmodes .or. nmodes == MAM5_nmodes) then
- coated_aer_num(1) = (aer(ii,kk,bc_pcarbon)*bc_num_to_mass*1.0e-6_r8)*dstcoat(1)+ &
- (aer(ii,kk,bc_accum)*bc_num_to_mass*1.0e-6_r8)
- uncoated_aer_num(1) = (aer(ii,kk,bc_pcarbon)*bc_num_to_mass*1.0e-6_r8)*(1._r8-dstcoat(1))
+ if (num_to_mass_in) then
+ coated_aer_num(1) = (aer(ii,kk,bc_pcarbon)*bc_num_to_mass*1.0e-6_r8)*dstcoat(1)+ &
+ (aer(ii,kk,bc_accum)*bc_num_to_mass*1.0e-6_r8)
+ uncoated_aer_num(1) = (aer(ii,kk,bc_pcarbon)*bc_num_to_mass*1.0e-6_r8)*(1._r8-dstcoat(1))
+ else
+ coated_aer_num(1) = bc4_num*dstcoat(1) + bc_num
+ uncoated_aer_num(1) = bc4_num*(1._r8-dstcoat(1))
+ end if
end if
-
+
if (nmodes == MAM3_nmodes .or. nmodes == MAM4_nmodes .or. nmodes == MAM5_nmodes) then
dst1_scale = 0.488_r8 ! scaled for D>0.5-1 um from 0.1-1 um
else if (nmodes == MAM7_nmodes) then
@@ -1293,12 +1290,12 @@ subroutine get_aer_num(ii, kk, ncnst, aer, aer_cb, rhoair,&
+ total_interstial_aer_num(2)*dst1_scale + total_interstial_aer_num(3)
!*****************************************************************************
- ! prepare some variables for water activity
+ ! prepare some variables for water activity
!*****************************************************************************
-
+
if (nmodes == MAM3_nmodes .or. nmodes == MAM4_nmodes .or. nmodes == MAM5_nmodes) then
- ! accumulation mode for dust_a1
- if (aer(ii,kk,num_accum) > 0._r8) then
+ ! accumulation mode for dust_a1
+ if (aer(ii,kk,num_accum) > 0._r8) then
awcam(2) = (dst1_num*1.0e6_r8)/aer(ii,kk,num_accum)* &
( aer(ii,kk,so4_accum) + aer(ii,kk,soa_accum) + &
aer(ii,kk,pom_accum) + aer(ii,kk,bc_accum) )*1.0e9_r8 ! [mug m-3]
@@ -1306,7 +1303,7 @@ subroutine get_aer_num(ii, kk, ncnst, aer, aer_cb, rhoair,&
awcam(2) = 0._r8
end if
- if (awcam(2) > 0._r8) then
+ if (awcam(2) > 0._r8) then
awfacm(2) = ( aer(ii,kk,bc_accum) + aer(ii,kk,soa_accum) + aer(ii,kk,pom_accum) )/ &
( aer(ii,kk,soa_accum) + aer(ii,kk,pom_accum) + aer(ii,kk,so4_accum) + aer(ii,kk,bc_accum) )
else
@@ -1356,13 +1353,13 @@ subroutine get_aer_num(ii, kk, ncnst, aer, aer_cb, rhoair,&
if (aer(ii,kk,num_coardust) > 0._r8) then
awcam(3) = (dst3_num*1.0e6_r8)/aer(ii,kk,num_coardust)* aer(ii,kk,so4_coardust)*1.0e9_r8
- else
+ else
awcam(3) = 0._r8
end if
awfacm(3) = 0._r8
end if
-
+
end subroutine get_aer_num
!====================================================================================================
diff --git a/src/physics/cam/microp_aero.F90 b/src/physics/cam/microp_aero.F90
index c65abd6157..226abf6ebb 100644
--- a/src/physics/cam/microp_aero.F90
+++ b/src/physics/cam/microp_aero.F90
@@ -42,7 +42,7 @@ module microp_aero
use ndrop_bam, only: ndrop_bam_init, ndrop_bam_run, ndrop_bam_ccn
use hetfrz_classnuc_cam, only: hetfrz_classnuc_cam_readnl, hetfrz_classnuc_cam_register, hetfrz_classnuc_cam_init, &
- hetfrz_classnuc_cam_save_cbaero, hetfrz_classnuc_cam_calc
+ hetfrz_classnuc_cam_calc
use cam_history, only: addfld, add_default, outfld
use cam_logfile, only: iulog
@@ -578,11 +578,6 @@ subroutine microp_aero_run ( &
rndst(1:ncol,1:pver,3) = rn_dst3
rndst(1:ncol,1:pver,4) = rn_dst4
- ! save copy of cloud borne aerosols for use in heterogeneous freezing
- if (use_hetfrz_classnuc) then
- call hetfrz_classnuc_cam_save_cbaero(state1, pbuf)
- end if
-
! initialize time-varying parameters
do k = top_lev, pver
do i = 1, ncol
diff --git a/src/physics/cam/nucleate_ice_cam.F90 b/src/physics/cam/nucleate_ice_cam.F90
index 4abd115826..922e871b72 100644
--- a/src/physics/cam/nucleate_ice_cam.F90
+++ b/src/physics/cam/nucleate_ice_cam.F90
@@ -482,11 +482,7 @@ subroutine nucleate_ice_cam_calc( &
ni => state%q(:,:,numice_idx)
pmid => state%pmid
- do k = top_lev, pver
- do i = 1, ncol
- rho(i,k) = pmid(i,k)/(rair*t(i,k))
- end do
- end do
+ rho(:ncol,:) = pmid(:ncol,:)/(rair*t(:ncol,:))
if (clim_modal_aero) then
diff --git a/src/physics/cam/phys_control.F90 b/src/physics/cam/phys_control.F90
index 08962c816a..8d0cad7ee3 100644
--- a/src/physics/cam/phys_control.F90
+++ b/src/physics/cam/phys_control.F90
@@ -56,9 +56,8 @@ module phys_control
logical :: history_aerosol = .false. ! output the MAM aerosol variables and tendencies
logical :: history_aero_optics = .false. ! output the aerosol
logical :: history_eddy = .false. ! output the eddy variables
-logical :: history_budget = .false. ! output tendencies and state variables for CAM4
- ! temperature, water vapor, cloud ice and cloud
- ! liquid budgets.
+logical :: history_budget = .false. ! output tendencies and state variables for T, water vapor,
+ ! cloud ice and cloud liquid budgets
logical :: convproc_do_aer = .false. ! switch for new convective scavenging treatment for modal aerosols
integer :: history_budget_histfile_num = 1 ! output history file number for budget fields
diff --git a/src/physics/cam/phys_grid.F90 b/src/physics/cam/phys_grid.F90
index 712421550d..ca1670e4c2 100644
--- a/src/physics/cam/phys_grid.F90
+++ b/src/physics/cam/phys_grid.F90
@@ -498,6 +498,9 @@ subroutine phys_grid_init( )
! column surface area (from dynamics)
real(r8), dimension(:), pointer :: area_d
+ ! column surface areawt (from dynamics)
+ real(r8), dimension(:), pointer :: areawt_d
+
! column integration weight (from dynamics)
real(r8), dimension(:), allocatable :: wght_d
@@ -1147,7 +1150,6 @@ subroutine phys_grid_init( )
! Note that if the dycore is using the same points as the physics grid,
! it will have already set up 'lat' and 'lon' axes for the physics grid
! However, these will be in the dynamics decomposition
-
if (unstructured) then
lon_coord => horiz_coord_create('lon', 'ncol', num_global_phys_cols, &
'longitude', 'degrees_east', 1, size(lonvals), lonvals, &
@@ -1188,13 +1190,13 @@ subroutine phys_grid_init( )
do i = 1, size(copy_attributes)
call cam_grid_attribute_copy(copy_gridname, 'physgrid', copy_attributes(i))
end do
-
if ((.not. cam_grid_attr_exists('physgrid', 'area')) .and. unstructured) then
! Physgrid always needs an area attribute. If we did not inherit one
! from the dycore (i.e., physics and dynamics are on different grids),
! create that attribute here (unstructured grids only, physgrid is
! not supported for structured grids).
allocate(area_d(size(grid_map, 2)))
+ allocate(areawt_d(size(grid_map, 2)))
p = 0
do lcid = begchunk, endchunk
ncols = lchunks(lcid)%ncols
@@ -1203,16 +1205,21 @@ subroutine phys_grid_init( )
cid = lchunks(lcid)%cid
do i = 1, chunks(cid)%ncols
area_d(p + i) = lchunks(lcid)%area(i)
+ areawt_d(p + i) = lchunks(lcid)%wght(i)
end do
if (pcols > ncols) then
! Need to set these to detect unused columns
area_d(p+ncols+1:p+pcols) = 0.0_r8
+ areawt_d(p+ncols+1:p+pcols) = 0.0_r8
end if
p = p + pcols
end do
call cam_grid_attribute_register('physgrid', 'area', &
'physics column areas', 'ncol', area_d, map=grid_map(3,:))
+ call cam_grid_attribute_register('physgrid', 'areawt', &
+ 'physics column area wts', 'ncol', areawt_d, map=grid_map(3,:))
nullify(area_d) ! Belongs to attribute now
+ nullify(areawt_d) ! Belongs to attribute now
end if
! Cleanup pointers (they belong to the grid now)
nullify(grid_map)
diff --git a/src/physics/cam/phys_grid_ctem.F90 b/src/physics/cam/phys_grid_ctem.F90
index e2d0cb5c71..6863799864 100644
--- a/src/physics/cam/phys_grid_ctem.F90
+++ b/src/physics/cam/phys_grid_ctem.F90
@@ -140,7 +140,7 @@ subroutine phys_grid_ctem_reg
real(r8), parameter :: latrad0 = -pi*0.5_r8
real(r8), parameter :: fourpi = pi*4._r8
- integer, parameter :: ctem_zavg_phys_decomp = 201 ! Must be unique within CAM
+ integer, parameter :: ctem_zavg_phys_decomp = 333 ! Must be unique within CAM
if (.not.do_tem_diags) return
@@ -207,11 +207,15 @@ subroutine phys_grid_ctem_init
if (.not.do_tem_diags) return
- call addfld ('VTHzaphys',(/'lev'/), 'A', 'K m s-1','Meridional Heat Flux:', gridname='ctem_zavg_phys')
- call addfld ('WTHzaphys',(/'lev'/), 'A', 'K m s-1','Vertical Heat Flux:', gridname='ctem_zavg_phys')
- call addfld ('UVzaphys', (/'lev'/), 'A', 'm2 s-2', 'Meridional Flux of Zonal Momentum', gridname='ctem_zavg_phys')
- call addfld ('UWzaphys', (/'lev'/), 'A', 'm2 s-2', 'Vertical Flux of Zonal Momentum', gridname='ctem_zavg_phys')
- call addfld ('THphys', (/'lev'/), 'A', 'K', 'Potential temp', gridname='physgrid' )
+ call addfld ('Uzm', (/'lev'/), 'A','m s-1', 'Zonal-Mean zonal wind', gridname='ctem_zavg_phys' )
+ call addfld ('Vzm', (/'lev'/), 'A','m s-1', 'Zonal-Mean meridional wind', gridname='ctem_zavg_phys' )
+ call addfld ('Wzm', (/'lev'/), 'A','m s-1', 'Zonal-Mean vertical wind', gridname='ctem_zavg_phys' )
+ call addfld ('THzm', (/'lev'/), 'A','K', 'Zonal-Mean potential temp', gridname='ctem_zavg_phys' )
+ call addfld ('VTHzm',(/'lev'/), 'A','K m s-1','Meridional Heat Flux:', gridname='ctem_zavg_phys')
+ call addfld ('WTHzm',(/'lev'/), 'A','K m s-1','Vertical Heat Flux:', gridname='ctem_zavg_phys')
+ call addfld ('UVzm', (/'lev'/), 'A','m2 s-2', 'Meridional Flux of Zonal Momentum', gridname='ctem_zavg_phys')
+ call addfld ('UWzm', (/'lev'/), 'A','m2 s-2', 'Vertical Flux of Zonal Momentum', gridname='ctem_zavg_phys')
+ call addfld ('THphys',(/'lev'/), 'A', 'K', 'Potential temp', gridname='physgrid' )
end subroutine phys_grid_ctem_init
@@ -251,6 +255,11 @@ subroutine phys_grid_ctem_diags(phys_state)
real(r8) :: vthza(nzalat,pver)
real(r8) :: wthza(nzalat,pver)
+ real(r8) :: uza(nzalat,pver)
+ real(r8) :: vza(nzalat,pver)
+ real(r8) :: wza(nzalat,pver)
+ real(r8) :: thza(nzalat,pver)
+
real(r8) :: sheight(pcols,pver) ! pressure scale height (m)
if (.not.do_calc()) return
@@ -311,12 +320,26 @@ subroutine phys_grid_ctem_diags(phys_state)
if (any(abs(vthza)>1.e20_r8)) call endrun(prefix//'bad values in vthza')
if (any(abs(wthza)>1.e20_r8)) call endrun(prefix//'bad values in wthza')
+ call ZAobj%binAvg(uzm, uza)
+ call ZAobj%binAvg(vzm, vza)
+ call ZAobj%binAvg(wzm, wza)
+ call ZAobj%binAvg(thzm, thza)
+
+ if (any(abs(uza)>1.e20_r8)) call endrun(prefix//'bad values in uza')
+ if (any(abs(vza)>1.e20_r8)) call endrun(prefix//'bad values in vza')
+ if (any(abs(wza)>1.e20_r8)) call endrun(prefix//'bad values in wza')
+ if (any(abs(thza)>1.e20_r8)) call endrun(prefix//'bad values in thza')
+
! diagnostic output
do j = 1,nzalat
- call outfld('UVzaphys',uvza(j,:),1,j)
- call outfld('UWzaphys',uwza(j,:),1,j)
- call outfld('VTHzaphys',vthza(j,:),1,j)
- call outfld('WTHzaphys',wthza(j,:),1,j)
+ call outfld('Uzm',uza(j,:),1,j)
+ call outfld('Vzm',vza(j,:),1,j)
+ call outfld('Wzm',wza(j,:),1,j)
+ call outfld('THzm',thza(j,:),1,j)
+ call outfld('UVzm',uvza(j,:),1,j)
+ call outfld('UWzm',uwza(j,:),1,j)
+ call outfld('VTHzm',vthza(j,:),1,j)
+ call outfld('WTHzm',wthza(j,:),1,j)
end do
contains
diff --git a/src/physics/cam/physics_types.F90 b/src/physics/cam/physics_types.F90
index dcda2e8906..9b0c23d2ff 100644
--- a/src/physics/cam/physics_types.F90
+++ b/src/physics/cam/physics_types.F90
@@ -6,7 +6,7 @@ module physics_types
use shr_kind_mod, only: r8 => shr_kind_r8
use ppgrid, only: pcols, pver
use constituents, only: pcnst, qmin, cnst_name, cnst_get_ind
- use geopotential, only: geopotential_dse, geopotential_t
+ use geopotential, only: geopotential_t
use physconst, only: zvir, gravit, cpair, rair
use air_composition, only: cpairv, rairv
use phys_grid, only: get_ncols_p, get_rlon_all_p, get_rlat_all_p, get_gcol_all_p
@@ -18,8 +18,6 @@ module physics_types
implicit none
private ! Make default type private to the module
- logical, parameter :: adjust_te = .FALSE.
-
! Public types:
public physics_state
@@ -210,10 +208,11 @@ subroutine physics_update(state, ptend, dt, tend)
!-----------------------------------------------------------------------
! Update the state and or tendency structure with the parameterization tendencies
!-----------------------------------------------------------------------
- use scamMod, only: scm_crm_mode, single_column
- use phys_control, only: phys_getopts
- use cam_thermo, only: cam_thermo_update ! Routine which updates physconst variables (WACCM-X)
- use qneg_module, only: qneg3
+ use scamMod, only: scm_crm_mode, single_column
+ use phys_control, only: phys_getopts
+ use cam_thermo, only: cam_thermo_dry_air_update ! Routine which updates physconst variables (WACCM-X)
+ use air_composition, only: dry_air_species_num
+ use qneg_module , only: qneg3
!------------------------------Arguments--------------------------------
type(physics_ptend), intent(inout) :: ptend ! Parameterization tendencies
@@ -377,9 +376,8 @@ subroutine physics_update(state, ptend, dt, tend)
!------------------------------------------------------------------------
! Get indices for molecular weights and call WACCM-X cam_thermo_update
!------------------------------------------------------------------------
- if ( waccmx_is('ionosphere') .or. waccmx_is('neutral') ) then
- call cam_thermo_update(state%q, state%t, state%lchnk, state%ncol, &
- to_moist_factor=state%pdeldry(:ncol,:)/state%pdel(:ncol,:) )
+ if (dry_air_species_num>0) then
+ call cam_thermo_dry_air_update(state%q, state%t, state%lchnk, state%ncol)
endif
!-----------------------------------------------------------------------
@@ -426,7 +424,7 @@ subroutine physics_update(state, ptend, dt, tend)
if (ptend%ls .or. ptend%lq(1)) then
call geopotential_t ( &
state%lnpint, state%lnpmid, state%pint , state%pmid , state%pdel , state%rpdel , &
- state%t , state%q(:,:,1), rairv_loc(:,:), gravit , zvirv , &
+ state%t , state%q(:,:,:), rairv_loc(:,:), gravit , zvirv , &
state%zi , state%zm , ncol )
! update dry static energy for use in next process
do k = ptend%top_level, ptend%bot_level
@@ -1192,7 +1190,10 @@ subroutine physics_cnst_limit(state)
end subroutine physics_cnst_limit
!===============================================================================
- subroutine physics_dme_adjust(state, tend, qini, dt)
+ subroutine physics_dme_adjust(state, tend, qini, liqini, iceini, dt)
+ use air_composition, only: dry_air_species_num,thermodynamic_active_species_num
+ use air_composition, only: thermodynamic_active_species_idx
+ use dycore, only: dycore_is
!-----------------------------------------------------------------------
!
! Purpose: Adjust the dry mass in each layer back to the value of physics input state
@@ -1224,6 +1225,8 @@ subroutine physics_dme_adjust(state, tend, qini, dt)
type(physics_state), intent(inout) :: state
type(physics_tend ), intent(inout) :: tend
real(r8), intent(in ) :: qini(pcols,pver) ! initial specific humidity
+ real(r8), intent(in ) :: liqini(pcols,pver) ! initial total liquid
+ real(r8), intent(in ) :: iceini(pcols,pver) ! initial total ice
real(r8), intent(in ) :: dt ! model physics timestep
!
!---------------------------Local workspace-----------------------------
@@ -1238,16 +1241,18 @@ subroutine physics_dme_adjust(state, tend, qini, dt)
real(r8) :: zvirv(pcols,pver) ! Local zvir array pointer
+ real(r8) :: tot_water (pcols,2) ! total water (initial, present)
+ real(r8) :: tot_water_chg(pcols) ! total water change
+
+
real(r8),allocatable :: cpairv_loc(:,:)
+ integer :: m_cnst
!
!-----------------------------------------------------------------------
if (state%psetcols .ne. pcols) then
call endrun('physics_dme_adjust: cannot pass in a state which has sub-columns')
end if
- if (adjust_te) then
- call endrun('physics_dme_adjust: must update code based on the "correct" energy before turning on "adjust_te"')
- end if
lchnk = state%lchnk
ncol = state%ncol
@@ -1255,76 +1260,57 @@ subroutine physics_dme_adjust(state, tend, qini, dt)
! adjust dry mass in each layer back to input value, while conserving
! constituents, momentum, and total energy
state%ps(:ncol) = state%pint(:ncol,1)
- do k = 1, pver
- ! adjusment factor is just change in water vapor
- fdq(:ncol) = 1._r8 + state%q(:ncol,k,1) - qini(:ncol,k)
-
- ! adjust constituents to conserve mass in each layer
- do m = 1, pcnst
+ !
+ ! original code for backwards compatability with FV and EUL
+ !
+ if (.not.(dycore_is('MPAS') .or. dycore_is('SE'))) then
+ do k = 1, pver
+
+ ! adjusment factor is just change in water vapor
+ fdq(:ncol) = 1._r8 + state%q(:ncol,k,1) - qini(:ncol,k)
+
+ ! adjust constituents to conserve mass in each layer
+ do m = 1, pcnst
state%q(:ncol,k,m) = state%q(:ncol,k,m) / fdq(:ncol)
- end do
-
- if (adjust_te) then
- ! compute specific total energy of unadjusted state (J/kg)
- te(:ncol) = state%s(:ncol,k) + 0.5_r8*(state%u(:ncol,k)**2 + state%v(:ncol,k)**2)
-
- ! recompute initial u,v from the new values and the tendencies
- utmp(:ncol) = state%u(:ncol,k) - dt * tend%dudt(:ncol,k)
- vtmp(:ncol) = state%v(:ncol,k) - dt * tend%dvdt(:ncol,k)
- ! adjust specific total energy and specific momentum (velocity) to conserve each
- te (:ncol) = te (:ncol) / fdq(:ncol)
- state%u(:ncol,k) = state%u(:ncol,k ) / fdq(:ncol)
- state%v(:ncol,k) = state%v(:ncol,k ) / fdq(:ncol)
- ! compute adjusted u,v tendencies
- tend%dudt(:ncol,k) = (state%u(:ncol,k) - utmp(:ncol)) / dt
- tend%dvdt(:ncol,k) = (state%v(:ncol,k) - vtmp(:ncol)) / dt
-
- ! compute adjusted static energy
- state%s(:ncol,k) = te(:ncol) - 0.5_r8*(state%u(:ncol,k)**2 + state%v(:ncol,k)**2)
- end if
-
-! compute new total pressure variables
- state%pdel (:ncol,k ) = state%pdel(:ncol,k ) * fdq(:ncol)
- state%ps(:ncol) = state%ps(:ncol) + state%pdel(:ncol,k)
- state%pint (:ncol,k+1) = state%pint(:ncol,k ) + state%pdel(:ncol,k)
- state%lnpint(:ncol,k+1) = log(state%pint(:ncol,k+1))
- state%rpdel (:ncol,k ) = 1._r8/ state%pdel(:ncol,k )
- end do
-
+ end do
+ ! compute new total pressure variables
+ state%pdel (:ncol,k ) = state%pdel(:ncol,k ) * fdq(:ncol)
+ state%ps(:ncol) = state%ps(:ncol) + state%pdel(:ncol,k)
+ state%pint (:ncol,k+1) = state%pint(:ncol,k ) + state%pdel(:ncol,k)
+ state%lnpint(:ncol,k+1) = log(state%pint(:ncol,k+1))
+ state%rpdel (:ncol,k ) = 1._r8/ state%pdel(:ncol,k )
+ end do
+ else
+ do k = 1, pver
+ tot_water(:ncol,1) = qini(:ncol,k) +liqini(:ncol,k)+iceini(:ncol,k) !initial total H2O
+ tot_water(:ncol,2) = 0.0_r8
+ do m_cnst=dry_air_species_num+1,thermodynamic_active_species_num
+ m = thermodynamic_active_species_idx(m_cnst)
+ tot_water(:ncol,2) = tot_water(:ncol,2)+state%q(:ncol,k,m)
+ end do
+ fdq(:ncol) = 1._r8 + tot_water(:ncol,2) - tot_water(:ncol,1)
+ ! adjust constituents to conserve mass in each layer
+ do m = 1, pcnst
+ state%q(:ncol,k,m) = state%q(:ncol,k,m) / fdq(:ncol)
+ end do
+ ! compute new total pressure variables
+ state%pdel (:ncol,k ) = state%pdel(:ncol,k ) * fdq(:ncol)
+ state%ps(:ncol) = state%ps(:ncol) + state%pdel(:ncol,k)
+ state%pint (:ncol,k+1) = state%pint(:ncol,k ) + state%pdel(:ncol,k)
+ state%lnpint(:ncol,k+1) = log(state%pint(:ncol,k+1))
+ state%rpdel (:ncol,k ) = 1._r8/ state%pdel(:ncol,k )
+ !note that mid-level variables (e.g. pmid) are not recomputed
+ end do
+ endif
if ( waccmx_is('ionosphere') .or. waccmx_is('neutral') ) then
zvirv(:,:) = shr_const_rwv / rairv(:,:,state%lchnk) - 1._r8
else
zvirv(:,:) = zvir
endif
-! compute new T,z from new s,q,dp
- if (adjust_te) then
-
-! cpairv_loc needs to be allocated to a size which matches state and ptend
-! If psetcols == pcols, cpairv is the correct size and just copy into cpairv_loc
-! If psetcols > pcols and all cpairv match cpair, then assign the constant cpair
-
- allocate(cpairv_loc(state%psetcols,pver))
- if (state%psetcols == pcols) then
- cpairv_loc(:,:) = cpairv(:,:,state%lchnk)
- else if (state%psetcols > pcols .and. all(cpairv(:,:,:) == cpair)) then
- cpairv_loc(:,:) = cpair
- else
- call endrun('physics_dme_adjust: cpairv is not allowed to vary when subcolumns are turned on')
- end if
-
- call geopotential_dse(state%lnpint, state%lnpmid, state%pint, &
- state%pmid , state%pdel , state%rpdel, &
- state%s , state%q(:,:,1), state%phis , rairv(:,:,state%lchnk), &
- gravit, cpairv_loc(:,:), zvirv, &
- state%t , state%zi , state%zm , ncol)
-
- deallocate(cpairv_loc)
-
- end if
-
end subroutine physics_dme_adjust
+
!-----------------------------------------------------------------------
!===============================================================================
@@ -1537,7 +1523,7 @@ end subroutine set_dry_to_wet
subroutine physics_state_alloc(state,lchnk,psetcols)
- use infnan, only : inf, assignment(=)
+ use infnan, only: inf, assignment(=)
! allocate the individual state components
diff --git a/src/physics/cam/physpkg.F90 b/src/physics/cam/physpkg.F90
index c726eb490e..c33546b194 100644
--- a/src/physics/cam/physpkg.F90
+++ b/src/physics/cam/physpkg.F90
@@ -13,7 +13,7 @@ module physpkg
use shr_kind_mod, only: r8 => shr_kind_r8
use spmd_utils, only: masterproc
- use physconst, only: latvap, latice, rh2o
+ use physconst, only: latvap, latice
use physics_types, only: physics_state, physics_tend, physics_state_set_grid, &
physics_ptend, physics_tend_init, physics_update, &
physics_type_alloc, physics_ptend_dealloc,&
@@ -21,7 +21,7 @@ module physpkg
use phys_grid, only: get_ncols_p
use phys_gmean, only: gmean_mass
use ppgrid, only: begchunk, endchunk, pcols, pver, pverp, psubcols
- use constituents, only: pcnst, cnst_name, cnst_get_ind
+ use constituents, only: pcnst, cnst_get_ind
use camsrfexch, only: cam_out_t, cam_in_t
use cam_control_mod, only: ideal_phys, adiabatic
@@ -74,6 +74,8 @@ module physpkg
integer :: qini_idx = 0
integer :: cldliqini_idx = 0
integer :: cldiceini_idx = 0
+ integer :: totliqini_idx = 0
+ integer :: toticeini_idx = 0
integer :: prec_str_idx = 0
integer :: snow_str_idx = 0
@@ -109,11 +111,11 @@ subroutine phys_register
use physics_buffer, only: pbuf_init_time, pbuf_cam_snapshot_register
use physics_buffer, only: pbuf_add_field, dtype_r8, pbuf_register_subcol
use shr_kind_mod, only: r8 => shr_kind_r8
- use spmd_utils, only: masterproc
- use constituents, only: pcnst, cnst_add, cnst_chk_dim, cnst_name
+ use constituents, only: pcnst, cnst_add, cnst_chk_dim
use cam_control_mod, only: moist_physics
use chemistry, only: chem_register
+ use mo_lightning, only: lightning_register
use cloud_fraction, only: cldfrc_register
use rk_stratiform, only: rk_stratiform_register
use microp_driver, only: microp_driver_register
@@ -121,7 +123,7 @@ subroutine phys_register
use macrop_driver, only: macrop_driver_register
use clubb_intr, only: clubb_register_cam
use conv_water, only: conv_water_register
- use physconst, only: mwdry, cpair, mwh2o, cpwv
+ use physconst, only: mwh2o, cpwv
use tracers, only: tracers_register
use check_energy, only: check_energy_register
use carma_intr, only: carma_register
@@ -136,7 +138,6 @@ subroutine phys_register
use flux_avg, only: flux_avg_register
use iondrag, only: iondrag_register
use waccmx_phys_intr, only: waccmx_phys_ion_elec_temp_reg
- use string_utils, only: to_lower
use prescribed_ozone, only: prescribed_ozone_register
use prescribed_volcaero,only: prescribed_volcaero_register
use prescribed_strataero,only: prescribed_strataero_register
@@ -207,6 +208,8 @@ subroutine phys_register
call pbuf_add_field('QINI', 'physpkg', dtype_r8, (/pcols,pver/), qini_idx)
call pbuf_add_field('CLDLIQINI', 'physpkg', dtype_r8, (/pcols,pver/), cldliqini_idx)
call pbuf_add_field('CLDICEINI', 'physpkg', dtype_r8, (/pcols,pver/), cldiceini_idx)
+ call pbuf_add_field('TOTLIQINI', 'physpkg', dtype_r8, (/pcols,pver/), totliqini_idx)
+ call pbuf_add_field('TOTICEINI', 'physpkg', dtype_r8, (/pcols,pver/), toticeini_idx)
! check energy package
call check_energy_register
@@ -267,6 +270,9 @@ subroutine phys_register
! register chemical constituents including aerosols ...
call chem_register()
+ ! add prognostic lightning flash freq pbuf fld
+ call lightning_register()
+
! co2 constituents
call co2_register()
@@ -359,7 +365,7 @@ end subroutine phys_register
subroutine phys_inidat( cam_out, pbuf2d )
use cam_abortutils, only: endrun
- use physics_buffer, only: pbuf_get_index, pbuf_get_field, physics_buffer_desc, pbuf_set_field, dyn_time_lvls
+ use physics_buffer, only: pbuf_get_index, physics_buffer_desc, pbuf_set_field, dyn_time_lvls
use cam_initfiles, only: initial_file_get_id, topo_file_get_id
@@ -375,11 +381,10 @@ subroutine phys_inidat( cam_out, pbuf2d )
type(cam_out_t), intent(inout) :: cam_out(begchunk:endchunk)
type(physics_buffer_desc), pointer :: pbuf2d(:,:)
- integer :: lchnk, m, n, i, k, ncol
+ integer :: lchnk, m, n, ncol
type(file_desc_t), pointer :: fh_ini, fh_topo
character(len=8) :: fieldname
real(r8), pointer :: tptr(:,:), tptr_2(:,:), tptr3d(:,:,:), tptr3d_2(:,:,:)
- real(r8), pointer :: qpert(:,:)
character(len=11) :: subname='phys_inidat' ! subroutine name
integer :: tpert_idx, qpert_idx, pblh_idx
@@ -706,9 +711,7 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out )
!-----------------------------------------------------------------------
use physics_buffer, only: physics_buffer_desc, pbuf_initialize, pbuf_get_index
- use physconst, only: rair, cpair, gravit, stebol, tmelt, &
- latvap, latice, rh2o, rhoh2o, pstd, zvir, &
- karman, rhodair
+ use physconst, only: rair, cpair, gravit, zvir, karman
use cam_thermo, only: cam_thermo_init
use ref_pres, only: pref_edge, pref_mid
@@ -716,6 +719,7 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out )
use cam_control_mod, only: initial_run
use check_energy, only: check_energy_init
use chemistry, only: chem_init
+ use mo_lightning, only: lightning_init
use prescribed_ozone, only: prescribed_ozone_init
use prescribed_ghg, only: prescribed_ghg_init
use prescribed_aero, only: prescribed_aero_init
@@ -748,14 +752,13 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out )
use pbl_utils, only: pbl_utils_init
use vertical_diffusion, only: vertical_diffusion_init
use phys_debug_util, only: phys_debug_init
- use phys_debug, only: phys_debug_state_init
use rad_constituents, only: rad_cnst_init
use aer_rad_props, only: aer_rad_props_init
use subcol, only: subcol_init
use qbo, only: qbo_init
use qneg_module, only: qneg_init
use lunar_tides, only: lunar_tides_init
- use iondrag, only: iondrag_init, do_waccm_ions
+ use iondrag, only: iondrag_init
#if ( defined OFFLINE_DYN )
use metdata, only: metdata_phys_init
#endif
@@ -773,6 +776,7 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out )
use cam_history, only: addfld, register_vector_field, add_default
use phys_control, only: phys_getopts
use phys_grid_ctem, only: phys_grid_ctem_init
+ use cam_budget, only: cam_budget_init
! Input/output arguments
type(physics_state), pointer :: phys_state(:)
@@ -790,7 +794,6 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out )
! temperature, water vapor, cloud
! ice, cloud liquid, U, V
integer :: history_budget_histfile_num ! output history file number for budget fields
-
!-----------------------------------------------------------------------
call physics_type_alloc(phys_state, phys_tend, begchunk, endchunk, pcols)
@@ -858,6 +861,9 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out )
! Prognostic chemistry.
call chem_init(phys_state,pbuf2d)
+ ! Lightning flash frq and NOx prod
+ call lightning_init( pbuf2d )
+
! Prescribed tracers
call prescribed_ozone_init()
call prescribed_ghg_init()
@@ -973,6 +979,9 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out )
! Initialize the snapshot capability
call cam_snapshot_init(cam_in, cam_out, pbuf2d, begchunk)
+ ! Initialize the budget capability
+ call cam_budget_init()
+
! addfld calls for U, V tendency budget variables that are output in
! tphysac, tphysbc
call addfld ( 'UTEND_DCONV', (/ 'lev' /), 'A', 'm/s2', 'Zonal wind tendency by deep convection')
@@ -1088,7 +1097,6 @@ subroutine phys_run1(phys_state, ztodt, phys_tend, pbuf2d, cam_in, cam_out)
!---------------------------Local workspace-----------------------------
!
integer :: c ! indices
- integer :: ncol ! number of columns
integer :: nstep ! current timestep number
logical :: use_spcam
type(physics_buffer_desc), pointer :: phys_buffer_chunk(:)
@@ -1113,10 +1121,6 @@ subroutine phys_run1(phys_state, ztodt, phys_tend, pbuf2d, cam_in, cam_out)
call check_energy_gmean(phys_state, pbuf2d, ztodt, nstep)
call t_stopf ('chk_en_gmean')
- call t_stopf ('physpkg_st1')
-
- call t_startf ('physpkg_st1')
-
call pbuf_allocate(pbuf2d, 'physpkg')
call diag_allocate()
@@ -1200,7 +1204,6 @@ subroutine phys_run2(phys_state, ztodt, phys_tend, pbuf2d, cam_out, &
use physics_buffer, only: physics_buffer_desc, pbuf_get_chunk, pbuf_deallocate, pbuf_update_tim_idx
use mo_lightning, only: lightning_no_prod
use cam_diagnostics, only: diag_deallocate, diag_surf
- use physconst, only: stebol, latvap
use carma_intr, only: carma_accumulate_stats
use spmd_utils, only: mpicom
use iop_forcing, only: scam_use_iop_srf
@@ -1251,9 +1254,9 @@ subroutine phys_run2(phys_state, ztodt, phys_tend, pbuf2d, cam_out, &
!
call get_met_srf2( cam_in )
#endif
- ! Set lightning production of NO
+ ! lightning flash freq and prod rate of NOx
call t_startf ('lightning_no_prod')
- call lightning_no_prod( phys_state, pbuf2d, cam_in )
+ call lightning_no_prod( phys_state, pbuf2d, cam_in )
call t_stopf ('lightning_no_prod')
call t_barrierf('sync_ac_physics', mpicom)
@@ -1375,7 +1378,7 @@ subroutine tphysac (ztodt, cam_in, &
use aero_model, only: aero_model_drydep
use carma_intr, only: carma_emission_tend, carma_timestep_tend
use carma_flags_mod, only: carma_do_aerosol, carma_do_emission
- use check_energy, only: check_energy_chng, calc_te_and_aam_budgets
+ use check_energy, only: check_energy_chng, tot_energy_phys
use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng
use time_manager, only: get_nstep
use cam_abortutils, only: endrun
@@ -1389,14 +1392,17 @@ subroutine tphysac (ztodt, cam_in, &
use perf_mod
use flux_avg, only: flux_avg_run
use unicon_cam, only: unicon_cam_org_diags
- use cam_history, only: hist_fld_active, outfld
+ use cam_history, only: outfld
use qneg_module, only: qneg4
use co2_cycle, only: co2_cycle_set_ptend
use nudging, only: Nudge_Model,Nudge_ON,nudging_timestep_tend
use cam_snapshot, only: cam_snapshot_all_outfld_tphysac
use cam_snapshot_common,only: cam_snapshot_ptend_outfld
use lunar_tides, only: lunar_tides_tend
-
+ use cam_thermo, only: cam_thermo_water_update
+ use cam_budget, only: thermo_budget_history
+ use dyn_tests_utils, only: vc_dycore, vc_height, vc_dry_pressure
+ use air_composition, only: cpairv, cp_or_cv_dycore
!
! Arguments
!
@@ -1416,30 +1422,24 @@ subroutine tphysac (ztodt, cam_in, &
!
type(physics_ptend) :: ptend ! indivdual parameterization tendencies
- integer :: nstep ! current timestep number
- real(r8) :: zero(pcols) ! array of zeros
+ integer :: nstep ! current timestep number
+ real(r8) :: zero(pcols) ! array of zeros
- integer :: lchnk ! chunk identifier
- integer :: ncol ! number of atmospheric columns
- integer i,k,m ! Longitude, level indices
- integer :: yr, mon, day, tod ! components of a date
- integer :: ixcldice, ixcldliq ! constituent indices for cloud liquid and ice water.
+ integer :: lchnk ! chunk identifier
+ integer :: ncol ! number of atmospheric columns
+ integer :: i,k ! Longitude, level indices
integer :: ixq
- logical :: labort ! abort flag
+ logical :: labort ! abort flag
- real(r8) tvm(pcols,pver) ! virtual temperature
- real(r8) prect(pcols) ! total precipitation
real(r8) surfric(pcols) ! surface friction velocity
real(r8) obklen(pcols) ! Obukhov length
real(r8) :: fh2o(pcols) ! h2o flux to balance source from methane chemistry
real(r8) :: flx_heat(pcols) ! Heat flux for check_energy_chng.
- real(r8) :: tmp_q (pcols,pver) ! tmp space
- real(r8) :: tmp_cldliq(pcols,pver) ! tmp space
- real(r8) :: tmp_cldice(pcols,pver) ! tmp space
real(r8) :: tmp_trac (pcols,pver,pcnst) ! tmp space
real(r8) :: tmp_pdel (pcols,pver) ! tmp space
real(r8) :: tmp_ps (pcols) ! tmp space
+ real(r8) :: scaling(pcols,pver)
logical :: moist_mixing_ratio_dycore
! physics buffer fields for total energy and mass adjustment
@@ -1449,6 +1449,8 @@ subroutine tphysac (ztodt, cam_in, &
real(r8), pointer, dimension(:,:) :: qini
real(r8), pointer, dimension(:,:) :: cldliqini
real(r8), pointer, dimension(:,:) :: cldiceini
+ real(r8), pointer, dimension(:,:) :: totliqini
+ real(r8), pointer, dimension(:,:) :: toticeini
real(r8), pointer, dimension(:,:) :: dtcore
real(r8), pointer, dimension(:,:) :: dqcore
real(r8), pointer, dimension(:,:) :: ducore
@@ -1483,6 +1485,8 @@ subroutine tphysac (ztodt, cam_in, &
call pbuf_get_field(pbuf, qini_idx, qini)
call pbuf_get_field(pbuf, cldliqini_idx, cldliqini)
call pbuf_get_field(pbuf, cldiceini_idx, cldiceini)
+ call pbuf_get_field(pbuf, totliqini_idx, totliqini)
+ call pbuf_get_field(pbuf, toticeini_idx, toticeini)
ifld = pbuf_get_index('CLD')
call pbuf_get_field(pbuf, ifld, cld, start=(/1,1,itim_old/),kount=(/pcols,pver,1/))
@@ -1823,8 +1827,8 @@ subroutine tphysac (ztodt, cam_in, &
fh2o, surfric, obklen, flx_heat)
end if
- call calc_te_and_aam_budgets(state, 'phAP')
- call calc_te_and_aam_budgets(state, 'dyAP',vc=vc_dycore)
+ call tot_energy_phys(state, 'phAP')
+ call tot_energy_phys(state, 'dyAP',vc=vc_dycore)
!---------------------------------------------------------------------------------
! Enforce charge neutrality after O+ change from ionos_tend
@@ -1855,7 +1859,9 @@ subroutine tphysac (ztodt, cam_in, &
!-------------- Energy budget checks vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
! Save total energy for global fixer in next timestep
-
+ !
+ ! This call must be after the last parameterization and call to physics_update
+ !
call pbuf_set_field(pbuf, teout_idx, state%te_cur(:,dyn_te_idx), (/1,itim_old/),(/pcols,1/))
if (shallow_scheme .eq. 'UNICON') then
@@ -1874,62 +1880,73 @@ subroutine tphysac (ztodt, cam_in, &
call unicon_cam_org_diags(state, pbuf)
end if
- moist_mixing_ratio_dycore = dycore_is('LR').or. dycore_is('FV3')
!
! FV: convert dry-type mixing ratios to moist here because physics_dme_adjust
! assumes moist. This is done in p_d_coupling for other dynamics. Bundy, Feb 2004.
- if (moist_mixing_ratio_dycore) call set_dry_to_wet(state) ! Physics had dry, dynamics wants moist
-
- ! Scale dry mass and energy (does nothing if dycore is EUL or SLD)
- call cnst_get_ind('CLDLIQ', ixcldliq)
- call cnst_get_ind('CLDICE', ixcldice)
-
- tmp_q (:ncol,:pver) = state%q(:ncol,:pver,1)
- tmp_cldliq(:ncol,:pver) = state%q(:ncol,:pver,ixcldliq)
- tmp_cldice(:ncol,:pver) = state%q(:ncol,:pver,ixcldice)
+ moist_mixing_ratio_dycore = dycore_is('LR').or. dycore_is('FV3')
+ !
+ ! update cp/cv for energy computation based in updated water variables
+ !
+ call cam_thermo_water_update(state%q(:ncol,:,:), lchnk, ncol, vc_dycore,&
+ to_dry_factor=state%pdel(:ncol,:)/state%pdeldry(:ncol,:))
! for dry mixing ratio dycore, physics_dme_adjust is called for energy diagnostic purposes only.
! So, save off tracers
- if (.not.moist_mixing_ratio_dycore.and.&
- (hist_fld_active('SE_phAM').or.hist_fld_active('KE_phAM').or.hist_fld_active('WV_phAM').or.&
- hist_fld_active('WL_phAM').or.hist_fld_active('WI_phAM').or.hist_fld_active('MR_phAM').or.&
- hist_fld_active('MO_phAM'))) then
- tmp_trac(:ncol,:pver,:pcnst) = state%q(:ncol,:pver,:pcnst)
- tmp_pdel(:ncol,:pver) = state%pdel(:ncol,:pver)
- tmp_ps(:ncol) = state%ps(:ncol)
-
+ if (.not.moist_mixing_ratio_dycore) then
+ !
+ ! for dry-mixing ratio based dycores dme_adjust takes place in the dynamical core
+ !
+ ! only compute dme_adjust for diagnostics purposes
+ !
+ if (thermo_budget_history) then
+ tmp_trac(:ncol,:pver,:pcnst) = state%q(:ncol,:pver,:pcnst)
+ tmp_pdel(:ncol,:pver) = state%pdel(:ncol,:pver)
+ tmp_ps(:ncol) = state%ps(:ncol)
+ call physics_dme_adjust(state, tend, qini, totliqini, toticeini, ztodt)
+ call tot_energy_phys(state, 'phAM')
+ call tot_energy_phys(state, 'dyAM', vc=vc_dycore)
+ ! Restore pre-"physics_dme_adjust" tracers
+ state%q(:ncol,:pver,:pcnst) = tmp_trac(:ncol,:pver,:pcnst)
+ state%pdel(:ncol,:pver) = tmp_pdel(:ncol,:pver)
+ state%ps(:ncol) = tmp_ps(:ncol)
+ end if
+ else
+ !
+ ! for moist-mixing ratio based dycores
+ !
+ ! Note: this operation will NOT be reverted with set_wet_to_dry after set_dry_to_wet call
+ !
call set_dry_to_wet(state)
- call physics_dme_adjust(state, tend, qini, ztodt)
-
- call calc_te_and_aam_budgets(state, 'phAM')
- call calc_te_and_aam_budgets(state, 'dyAM',vc=vc_dycore)
- ! Restore pre-"physics_dme_adjust" tracers
- state%q(:ncol,:pver,:pcnst) = tmp_trac(:ncol,:pver,:pcnst)
- state%pdel(:ncol,:pver) = tmp_pdel(:ncol,:pver)
- state%ps(:ncol) = tmp_ps(:ncol)
- end if
-
- if (moist_mixing_ratio_dycore) then
-
if (trim(cam_take_snapshot_before) == "physics_dme_adjust") then
- call cam_snapshot_all_outfld_tphysac(cam_snapshot_before_num, state, tend, cam_in, cam_out, pbuf,&
+ call cam_snapshot_all_outfld_tphysac(cam_snapshot_after_num, state, tend, cam_in, cam_out, pbuf,&
fh2o, surfric, obklen, flx_heat)
end if
-
- call physics_dme_adjust(state, tend, qini, ztodt)
-
+ call physics_dme_adjust(state, tend, qini, totliqini, toticeini, ztodt)
if (trim(cam_take_snapshot_after) == "physics_dme_adjust") then
- call cam_snapshot_all_outfld_tphysac(cam_snapshot_after_num, state, tend, cam_in, cam_out, pbuf,&
- fh2o, surfric, obklen, flx_heat)
+ call cam_snapshot_all_outfld_tphysac(cam_snapshot_after_num, state, tend, cam_in, cam_out, pbuf,&
+ fh2o, surfric, obklen, flx_heat)
end if
- call calc_te_and_aam_budgets(state, 'phAM')
- call calc_te_and_aam_budgets(state, 'dyAM',vc=vc_dycore)
+ call tot_energy_phys(state, 'phAM')
+ call tot_energy_phys(state, 'dyAM', vc=vc_dycore)
endif
-!!! REMOVE THIS CALL, SINCE ONLY Q IS BEING ADJUSTED. WON'T BALANCE ENERGY. TE IS SAVED BEFORE THIS
-!!! call check_energy_chng(state, tend, "drymass", nstep, ztodt, zero, zero, zero, zero)
+ if (vc_dycore == vc_height.or.vc_dycore == vc_dry_pressure) then
+ !
+ ! MPAS and SE specific scaling of temperature for enforcing energy consistency
+ ! (and to make sure that temperature dependent diagnostic tendencies
+ ! are computed correctly; e.g. dtcore)
+ !
+ scaling(1:ncol,:) = cpairv(:ncol,:,lchnk)/cp_or_cv_dycore(:ncol,:,lchnk)
+ state%T(1:ncol,:) = state%temp_ini(1:ncol,:)+&
+ scaling(1:ncol,:)*(state%T(1:ncol,:)-state%temp_ini(1:ncol,:))
+ tend%dtdt(:ncol,:) = scaling(:ncol,:)*tend%dtdt(:ncol,:)
+ !
+ ! else: do nothing for dycores with energy consistent with CAM physics
+ !
+ end if
+
! store T, U, and V in buffer for use in computing dynamics T-tendency in next timestep
do k = 1,pver
@@ -1954,8 +1971,7 @@ subroutine tphysac (ztodt, cam_in, &
endif
endif
- call diag_phys_tend_writeout (state, pbuf, tend, ztodt, tmp_q, tmp_cldliq, tmp_cldice, &
- qini, cldliqini, cldiceini)
+ call diag_phys_tend_writeout (state, pbuf, tend, ztodt, qini, cldliqini, cldiceini)
call clybry_fam_set( ncol, lchnk, map2chm, state%q, pbuf )
@@ -2004,18 +2020,20 @@ subroutine tphysbc (ztodt, state, &
use physics_types, only: physics_state, physics_tend, physics_ptend, &
physics_update, physics_ptend_init, physics_ptend_sum, &
physics_state_check, physics_ptend_scale, &
- phys_te_idx, dyn_te_idx
+ dyn_te_idx
use cam_diagnostics, only: diag_conv_tend_ini, diag_phys_writeout, diag_conv, diag_export, diag_state_b4_phys_write
use cam_diagnostics, only: diag_clip_tend_writeout
use cam_history, only: outfld
- use physconst, only: cpair, latvap
+ use physconst, only: latvap
use constituents, only: pcnst, qmin, cnst_get_ind
+ use air_composition, only: thermodynamic_active_species_liq_num,thermodynamic_active_species_liq_idx
+ use air_composition, only: thermodynamic_active_species_ice_num,thermodynamic_active_species_ice_idx
use convect_deep, only: convect_deep_tend, convect_deep_tend_2, deep_scheme_does_scav_trans
use time_manager, only: is_first_step, get_nstep
use convect_shallow, only: convect_shallow_tend
use check_energy, only: check_energy_chng, check_energy_fix, check_energy_timestep_init
use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng
- use check_energy, only: calc_te_and_aam_budgets
+ use check_energy, only: tot_energy_phys
use dycore, only: dycore_is
use aero_model, only: aero_model_wetdep
use carma_intr, only: carma_wetdep_tend, carma_timestep_tend
@@ -2084,6 +2102,7 @@ subroutine tphysbc (ztodt, state, &
integer :: i ! column indicex
integer :: ixcldice, ixcldliq, ixq ! constituent indices for cloud liquid and ice water.
+ integer :: m, m_cnst
! for macro/micro co-substepping
integer :: macmic_it ! iteration variables
real(r8) :: cld_macmic_ztodt ! modified timestep
@@ -2097,6 +2116,8 @@ subroutine tphysbc (ztodt, state, &
real(r8), pointer, dimension(:,:) :: qini
real(r8), pointer, dimension(:,:) :: cldliqini
real(r8), pointer, dimension(:,:) :: cldiceini
+ real(r8), pointer, dimension(:,:) :: totliqini
+ real(r8), pointer, dimension(:,:) :: toticeini
real(r8), pointer, dimension(:,:) :: dtcore
real(r8), pointer, dimension(:,:) :: dqcore
real(r8), pointer, dimension(:,:) :: ducore
@@ -2145,8 +2166,6 @@ subroutine tphysbc (ztodt, state, &
type(check_tracers_data):: tracerint ! energy integrals and cummulative boundary fluxes
real(r8) :: zero_tracers(pcols,pcnst)
- logical :: lq(pcnst)
-
!-----------------------------------------------------------------------
call t_startf('bc_init')
@@ -2172,6 +2191,8 @@ subroutine tphysbc (ztodt, state, &
call pbuf_get_field(pbuf, qini_idx, qini)
call pbuf_get_field(pbuf, cldliqini_idx, cldliqini)
call pbuf_get_field(pbuf, cldiceini_idx, cldiceini)
+ call pbuf_get_field(pbuf, totliqini_idx, totliqini)
+ call pbuf_get_field(pbuf, toticeini_idx, toticeini)
call pbuf_get_field(pbuf, dtcore_idx, dtcore, start=(/1,1,itim_old/), kount=(/pcols,pver,1/) )
call pbuf_get_field(pbuf, dqcore_idx, dqcore, start=(/1,1,itim_old/), kount=(/pcols,pver,1/) )
@@ -2217,16 +2238,16 @@ subroutine tphysbc (ztodt, state, &
!===================================================
call t_startf('energy_fixer')
- call calc_te_and_aam_budgets(state, 'phBF')
- call calc_te_and_aam_budgets(state, 'dyBF',vc=vc_dycore)
+ call tot_energy_phys(state, 'phBF')
+ call tot_energy_phys(state, 'dyBF',vc=vc_dycore)
if (.not.dycore_is('EUL')) then
call check_energy_fix(state, ptend, nstep, flx_heat)
call physics_update(state, ptend, ztodt, tend)
call check_energy_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat)
call outfld( 'EFIX', flx_heat , pcols, lchnk )
end if
- call calc_te_and_aam_budgets(state, 'phBP')
- call calc_te_and_aam_budgets(state, 'dyBP',vc=vc_dycore)
+ call tot_energy_phys(state, 'phBP')
+ call tot_energy_phys(state, 'dyBP',vc=vc_dycore)
! Save state for convective tendency calculations.
call diag_conv_tend_ini(state, pbuf)
@@ -2237,6 +2258,18 @@ subroutine tphysbc (ztodt, state, &
cldliqini(:ncol,:pver) = state%q(:ncol,:pver,ixcldliq)
cldiceini(:ncol,:pver) = state%q(:ncol,:pver,ixcldice)
+ totliqini(:ncol,:pver) = 0.0_r8
+ do m_cnst=1,thermodynamic_active_species_liq_num
+ m = thermodynamic_active_species_liq_idx(m_cnst)
+ totliqini(:ncol,:pver) = totliqini(:ncol,:pver)+state%q(:ncol,:pver,m)
+ end do
+ toticeini(:ncol,:pver) = 0.0_r8
+ do m_cnst=1,thermodynamic_active_species_ice_num
+ m = thermodynamic_active_species_ice_idx(m_cnst)
+ toticeini(:ncol,:pver) = toticeini(:ncol,:pver)+state%q(:ncol,:pver,m)
+ end do
+
+
call outfld('TEOUT', teout , pcols, lchnk )
call outfld('TEINP', state%te_ini(:,dyn_te_idx), pcols, lchnk )
call outfld('TEFIX', state%te_cur(:,dyn_te_idx), pcols, lchnk )
@@ -2859,7 +2892,6 @@ subroutine phys_timestep_init(phys_state, cam_in, cam_out, pbuf2d)
! datasets.
!
!-----------------------------------------------------------------------------------
- use shr_kind_mod, only: r8 => shr_kind_r8
use chemistry, only: chem_timestep_init
use chem_surfvals, only: chem_surfvals_set
use physics_types, only: physics_state
diff --git a/src/physics/cam_dev/physpkg.F90 b/src/physics/cam_dev/physpkg.F90
index d2fe6f7ca0..7452f9e115 100644
--- a/src/physics/cam_dev/physpkg.F90
+++ b/src/physics/cam_dev/physpkg.F90
@@ -71,6 +71,8 @@ module physpkg
integer :: qini_idx = 0
integer :: cldliqini_idx = 0
integer :: cldiceini_idx = 0
+ integer :: totliqini_idx = 0
+ integer :: toticeini_idx = 0
integer :: prec_str_idx = 0
integer :: snow_str_idx = 0
@@ -110,6 +112,7 @@ subroutine phys_register
use cam_control_mod, only: moist_physics
use chemistry, only: chem_register
+ use mo_lightning, only: lightning_register
use cloud_fraction, only: cldfrc_register
use microp_driver, only: microp_driver_register
use microp_aero, only: microp_aero_register
@@ -194,6 +197,8 @@ subroutine phys_register
call pbuf_add_field('QINI', 'physpkg', dtype_r8, (/pcols,pver/), qini_idx)
call pbuf_add_field('CLDLIQINI', 'physpkg', dtype_r8, (/pcols,pver/), cldliqini_idx)
call pbuf_add_field('CLDICEINI', 'physpkg', dtype_r8, (/pcols,pver/), cldiceini_idx)
+ call pbuf_add_field('TOTLIQINI', 'physpkg', dtype_r8, (/pcols,pver/), totliqini_idx)
+ call pbuf_add_field('TOTICEINI', 'physpkg', dtype_r8, (/pcols,pver/), toticeini_idx)
! check energy package
call check_energy_register
@@ -253,6 +258,9 @@ subroutine phys_register
! register chemical constituents including aerosols ...
call chem_register()
+ ! add prognostic lightning flash freq pbuf fld
+ call lightning_register()
+
! co2 constituents
call co2_register()
@@ -699,6 +707,7 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out )
use cam_control_mod, only: initial_run
use check_energy, only: check_energy_init
use chemistry, only: chem_init
+ use mo_lightning, only: lightning_init
use prescribed_ozone, only: prescribed_ozone_init
use prescribed_ghg, only: prescribed_ghg_init
use prescribed_aero, only: prescribed_aero_init
@@ -749,6 +758,8 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out )
use nudging, only: Nudge_Model, nudging_init
use cam_snapshot, only: cam_snapshot_init
use cam_history, only: addfld, register_vector_field, add_default
+ use cam_budget, only: cam_budget_init
+ use phys_grid_ctem, only: phys_grid_ctem_init
! Input/output arguments
type(physics_state), pointer :: phys_state(:)
@@ -831,6 +842,9 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out )
! Prognostic chemistry.
call chem_init(phys_state,pbuf2d)
+ ! Lightning flash frq and NOx prod
+ call lightning_init( pbuf2d )
+
! Prescribed tracers
call prescribed_ozone_init()
call prescribed_ghg_init()
@@ -928,9 +942,15 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out )
! Initialize qneg3 and qneg4
call qneg_init()
+ ! Initialize phys TEM diagnostics
+ call phys_grid_ctem_init()
+
! Initialize the snapshot capability
call cam_snapshot_init(cam_in, cam_out, pbuf2d, begchunk)
+ ! Initialize the budget capability
+ call cam_budget_init()
+
! addfld calls for U, V tendency budget variables that are output in
! tphysac, tphysbc
call addfld ( 'UTEND_DCONV', (/ 'lev' /), 'A', 'm/s2', 'Zonal wind tendency by deep convection')
@@ -1192,9 +1212,9 @@ subroutine phys_run2(phys_state, ztodt, phys_tend, pbuf2d, cam_out, &
!
call get_met_srf2( cam_in )
#endif
- ! Set lightning production of NO
+ ! lightning flash freq and prod rate of NOx
call t_startf ('lightning_no_prod')
- call lightning_no_prod( phys_state, pbuf2d, cam_in )
+ call lightning_no_prod( phys_state, pbuf2d, cam_in )
call t_stopf ('lightning_no_prod')
call t_barrierf('sync_ac_physics', mpicom)
@@ -1248,6 +1268,8 @@ subroutine phys_final( phys_state, phys_tend, pbuf2d )
use carma_intr, only: carma_final
use wv_saturation, only: wv_sat_final
use microp_aero, only: microp_aero_final
+ use phys_grid_ctem, only: phys_grid_ctem_final
+ use nudging, only: Nudge_Model, nudging_final
!-----------------------------------------------------------------------
!
@@ -1270,6 +1292,8 @@ subroutine phys_final( phys_state, phys_tend, pbuf2d )
call carma_final
call wv_sat_final
call microp_aero_final()
+ call phys_grid_ctem_final()
+ if(Nudge_Model) call nudging_final()
end subroutine phys_final
@@ -1309,7 +1333,7 @@ subroutine tphysac (ztodt, cam_in, &
use aoa_tracers, only: aoa_tracers_timestep_tend
use physconst, only: rhoh2o
use aero_model, only: aero_model_drydep
- use check_energy, only: check_energy_chng, calc_te_and_aam_budgets
+ use check_energy, only: check_energy_chng, tot_energy_phys
use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng
use time_manager, only: get_nstep
use cam_abortutils, only: endrun
@@ -1352,6 +1376,10 @@ subroutine tphysac (ztodt, cam_in, &
use carma_flags_mod, only: carma_do_aerosol, carma_do_emission, carma_do_detrain
use carma_flags_mod, only: carma_do_cldice, carma_do_cldliq, carma_do_wetdep
use dyn_tests_utils, only: vc_dycore
+ use cam_thermo, only: cam_thermo_water_update
+ use cam_budget, only: thermo_budget_history
+ use dyn_tests_utils, only: vc_dycore, vc_height, vc_dry_pressure
+ use air_composition, only: cpairv, cp_or_cv_dycore
!
! Arguments
!
@@ -1437,12 +1465,10 @@ subroutine tphysac (ztodt, cam_in, &
real(r8) obklen(pcols) ! Obukhov length
real(r8) :: fh2o(pcols) ! h2o flux to balance source from methane chemistry
real(r8) :: flx_heat(pcols) ! Heat flux for check_energy_chng.
- real(r8) :: tmp_q (pcols,pver) ! tmp space
- real(r8) :: tmp_cldliq(pcols,pver) ! tmp space
- real(r8) :: tmp_cldice(pcols,pver) ! tmp space
real(r8) :: tmp_trac (pcols,pver,pcnst) ! tmp space
real(r8) :: tmp_pdel (pcols,pver) ! tmp space
real(r8) :: tmp_ps (pcols) ! tmp space
+ real(r8) :: scaling(pcols,pver)
logical :: moist_mixing_ratio_dycore
! physics buffer fields for total energy and mass adjustment
@@ -1452,6 +1478,8 @@ subroutine tphysac (ztodt, cam_in, &
real(r8), pointer, dimension(:,:) :: qini
real(r8), pointer, dimension(:,:) :: cldliqini
real(r8), pointer, dimension(:,:) :: cldiceini
+ real(r8), pointer, dimension(:,:) :: totliqini
+ real(r8), pointer, dimension(:,:) :: toticeini
real(r8), pointer, dimension(:,:) :: dtcore
real(r8), pointer, dimension(:,:) :: dqcore
real(r8), pointer, dimension(:,:) :: ducore
@@ -1487,6 +1515,8 @@ subroutine tphysac (ztodt, cam_in, &
call pbuf_get_field(pbuf, qini_idx, qini)
call pbuf_get_field(pbuf, cldliqini_idx, cldliqini)
call pbuf_get_field(pbuf, cldiceini_idx, cldiceini)
+ call pbuf_get_field(pbuf, totliqini_idx, totliqini)
+ call pbuf_get_field(pbuf, toticeini_idx, toticeini)
ifld = pbuf_get_index('CLD')
call pbuf_get_field(pbuf, ifld, cld, start=(/1,1,itim_old/),kount=(/pcols,pver,1/))
@@ -2264,8 +2294,8 @@ subroutine tphysac (ztodt, cam_in, &
call cam_snapshot_all_outfld_tphysac(cam_snapshot_after_num, state, tend, cam_in, cam_out, pbuf,&
fh2o, surfric, obklen, flx_heat, cmfmc, dlf, det_s, det_ice, net_flx)
end if
- call calc_te_and_aam_budgets(state, 'phAP')
- call calc_te_and_aam_budgets(state, 'dyAP',vc=vc_dycore)
+ call tot_energy_phys(state, 'phAP')
+ call tot_energy_phys(state, 'dyAP',vc=vc_dycore)
!---------------------------------------------------------------------------------
! Enforce charge neutrality after O+ change from ionos_tend
@@ -2295,61 +2325,77 @@ subroutine tphysac (ztodt, cam_in, &
!-------------- Energy budget checks vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
! Save total energy for global fixer in next timestep
+ !
+ ! This call must be after the last parameterization and call to physics_update
+ !
call pbuf_set_field(pbuf, teout_idx, state%te_cur(:,dyn_te_idx), (/1,itim_old/),(/pcols,1/))
!
! FV: convert dry-type mixing ratios to moist here because physics_dme_adjust
! assumes moist. This is done in p_d_coupling for other dynamics. Bundy, Feb 2004.
moist_mixing_ratio_dycore = dycore_is('LR').or. dycore_is('FV3')
- if (moist_mixing_ratio_dycore) call set_dry_to_wet(state) ! Physics had dry, dynamics wants moist
-
- ! Scale dry mass and energy (does nothing if dycore is EUL or SLD)
- tmp_q (:ncol,:pver) = state%q(:ncol,:pver,ixq)
- tmp_cldliq(:ncol,:pver) = state%q(:ncol,:pver,ixcldliq)
- tmp_cldice(:ncol,:pver) = state%q(:ncol,:pver,ixcldice)
+ !
+ ! update cp/cv for energy computation based in updated water variables
+ !
+ call cam_thermo_water_update(state%q(:ncol,:,:), lchnk, ncol, vc_dycore,&
+ to_dry_factor=state%pdel(:ncol,:)/state%pdeldry(:ncol,:))
! for dry mixing ratio dycore, physics_dme_adjust is called for energy diagnostic purposes only.
! So, save off tracers
- if (.not.moist_mixing_ratio_dycore.and.&
- (hist_fld_active('SE_phAM').or.hist_fld_active('KE_phAM').or.hist_fld_active('WV_phAM').or.&
- hist_fld_active('WL_phAM').or.hist_fld_active('WI_phAM').or.hist_fld_active('MR_phAM').or.&
- hist_fld_active('MO_phAM'))) then
- tmp_trac(:ncol,:pver,:pcnst) = state%q(:ncol,:pver,:pcnst)
- tmp_pdel(:ncol,:pver) = state%pdel(:ncol,:pver)
- tmp_ps(:ncol) = state%ps(:ncol)
-
+ if (.not.moist_mixing_ratio_dycore) then
+ !
+ ! for dry-mixing ratio based dycores dme_adjust takes place in the dynamical core
+ !
+ ! only compute dme_adjust for diagnostics purposes
+ !
+ if (thermo_budget_history) then
+ tmp_trac(:ncol,:pver,:pcnst) = state%q(:ncol,:pver,:pcnst)
+ tmp_pdel(:ncol,:pver) = state%pdel(:ncol,:pver)
+ tmp_ps(:ncol) = state%ps(:ncol)
+ call physics_dme_adjust(state, tend, qini, totliqini, toticeini, ztodt)
+ call tot_energy_phys(state, 'phAM')
+ call tot_energy_phys(state, 'dyAM', vc=vc_dycore)
+ ! Restore pre-"physics_dme_adjust" tracers
+ state%q(:ncol,:pver,:pcnst) = tmp_trac(:ncol,:pver,:pcnst)
+ state%pdel(:ncol,:pver) = tmp_pdel(:ncol,:pver)
+ state%ps(:ncol) = tmp_ps(:ncol)
+ end if
+ else
+ !
+ ! for moist-mixing ratio based dycores
+ !
+ ! Note: this operation will NOT be reverted with set_wet_to_dry after set_dry_to_wet call
+ !
call set_dry_to_wet(state)
-
- call physics_dme_adjust(state, tend, qini, ztodt)
-
- call calc_te_and_aam_budgets(state, 'phAM')
- call calc_te_and_aam_budgets(state, 'dyAM',vc=vc_dycore)
- ! Restore pre-"physics_dme_adjust" tracers
- state%q(:ncol,:pver,:pcnst) = tmp_trac(:ncol,:pver,:pcnst)
- state%pdel(:ncol,:pver) = tmp_pdel(:ncol,:pver)
- state%ps(:ncol) = tmp_ps(:ncol)
- end if
-
- if (moist_mixing_ratio_dycore) then
-
if (trim(cam_take_snapshot_before) == "physics_dme_adjust") then
call cam_snapshot_all_outfld_tphysac(cam_snapshot_before_num, state, tend, cam_in, cam_out, pbuf,&
fh2o, surfric, obklen, flx_heat, cmfmc, dlf, det_s, det_ice, net_flx)
end if
-
- call physics_dme_adjust(state, tend, qini, ztodt)
-
+ call physics_dme_adjust(state, tend, qini, totliqini, toticeini, ztodt)
if (trim(cam_take_snapshot_after) == "physics_dme_adjust") then
- call cam_snapshot_all_outfld_tphysac(cam_snapshot_after_num, state, tend, cam_in, cam_out, pbuf,&
- fh2o, surfric, obklen, flx_heat, cmfmc, dlf, det_s, det_ice, net_flx)
+ call cam_snapshot_all_outfld_tphysac(cam_snapshot_after_num, state, tend, cam_in, cam_out, pbuf,&
+ fh2o, surfric, obklen, flx_heat, cmfmc, dlf, det_s, det_ice, net_flx)
end if
- call calc_te_and_aam_budgets(state, 'phAM')
- call calc_te_and_aam_budgets(state, 'dyAM',vc=vc_dycore)
+ call tot_energy_phys(state, 'phAM')
+ call tot_energy_phys(state, 'dyAM', vc=vc_dycore)
endif
-!!! REMOVE THIS CALL, SINCE ONLY Q IS BEING ADJUSTED. WON'T BALANCE ENERGY. TE IS SAVED BEFORE THIS
-!!! call check_energy_chng(state, tend, "drymass", nstep, ztodt, zero, zero, zero, zero)
+ if (vc_dycore == vc_height.or.vc_dycore == vc_dry_pressure) then
+ !
+ ! MPAS and SE specific scaling of temperature for enforcing energy consistency
+ ! (and to make sure that temperature dependent diagnostic tendencies
+ ! are computed correctly; e.g. dtcore)
+ !
+ scaling(1:ncol,:) = cpairv(:ncol,:,lchnk)/cp_or_cv_dycore(:ncol,:,lchnk)
+ state%T(1:ncol,:) = state%temp_ini(1:ncol,:)+&
+ scaling(1:ncol,:)*(state%T(1:ncol,:)-state%temp_ini(1:ncol,:))
+ tend%dtdt(:ncol,:) = scaling(:ncol,:)*tend%dtdt(:ncol,:)
+ !
+ ! else: do nothing for dycores with energy consistent with CAM physics
+ !
+ end if
+
! store T, U, and V in buffer for use in computing dynamics T-tendency in next timestep
do k = 1,pver
@@ -2374,8 +2420,7 @@ subroutine tphysac (ztodt, cam_in, &
endif
endif
- call diag_phys_tend_writeout (state, pbuf, tend, ztodt, tmp_q, tmp_cldliq, tmp_cldice, &
- qini, cldliqini, cldiceini)
+ call diag_phys_tend_writeout (state, pbuf, tend, ztodt, qini, cldliqini, cldiceini)
call clybry_fam_set( ncol, lchnk, map2chm, state%q, pbuf )
@@ -2419,12 +2464,14 @@ subroutine tphysbc (ztodt, state, &
use cam_diagnostics, only: diag_conv_tend_ini, diag_conv, diag_export, diag_state_b4_phys_write
use cam_history, only: outfld
use constituents, only: qmin
+ use air_composition, only: thermodynamic_active_species_liq_num,thermodynamic_active_species_liq_idx
+ use air_composition, only: thermodynamic_active_species_ice_num,thermodynamic_active_species_ice_idx
use convect_deep, only: convect_deep_tend
use time_manager, only: is_first_step, get_nstep
use convect_diagnostics,only: convect_diagnostics_calc
use check_energy, only: check_energy_chng, check_energy_fix
use check_energy, only: check_tracers_data, check_tracers_init
- use check_energy, only: calc_te_and_aam_budgets
+ use check_energy, only: tot_energy_phys
use dycore, only: dycore_is
use radiation, only: radiation_tend
use perf_mod
@@ -2474,6 +2521,7 @@ subroutine tphysbc (ztodt, state, &
integer :: i ! column indicex
integer :: ixcldice, ixcldliq, ixq ! constituent indices for cloud liquid and ice water.
+ integer :: m, m_cnst
! physics buffer fields to compute tendencies for stratiform package
integer itim_old, ifld
@@ -2484,6 +2532,8 @@ subroutine tphysbc (ztodt, state, &
real(r8), pointer, dimension(:,:) :: qini
real(r8), pointer, dimension(:,:) :: cldliqini
real(r8), pointer, dimension(:,:) :: cldiceini
+ real(r8), pointer, dimension(:,:) :: totliqini
+ real(r8), pointer, dimension(:,:) :: toticeini
real(r8), pointer, dimension(:,:) :: dtcore
real(r8), pointer, dimension(:,:) :: dqcore
real(r8), pointer, dimension(:,:) :: ducore
@@ -2548,6 +2598,8 @@ subroutine tphysbc (ztodt, state, &
call pbuf_get_field(pbuf, qini_idx, qini)
call pbuf_get_field(pbuf, cldliqini_idx, cldliqini)
call pbuf_get_field(pbuf, cldiceini_idx, cldiceini)
+ call pbuf_get_field(pbuf, totliqini_idx, totliqini)
+ call pbuf_get_field(pbuf, toticeini_idx, toticeini)
call pbuf_get_field(pbuf, dtcore_idx, dtcore, start=(/1,1,itim_old/), kount=(/pcols,pver,1/) )
call pbuf_get_field(pbuf, dqcore_idx, dqcore, start=(/1,1,itim_old/), kount=(/pcols,pver,1/) )
@@ -2594,8 +2646,8 @@ subroutine tphysbc (ztodt, state, &
!===================================================
call t_startf('energy_fixer')
- call calc_te_and_aam_budgets(state, 'phBF')
- call calc_te_and_aam_budgets(state, 'dyBF',vc=vc_dycore)
+ call tot_energy_phys(state, 'phBF')
+ call tot_energy_phys(state, 'dyBF',vc=vc_dycore)
if (.not.dycore_is('EUL')) then
call check_energy_fix(state, ptend, nstep, flx_heat)
@@ -2604,8 +2656,8 @@ subroutine tphysbc (ztodt, state, &
call outfld( 'EFIX', flx_heat , pcols, lchnk )
end if
- call calc_te_and_aam_budgets(state, 'phBP')
- call calc_te_and_aam_budgets(state, 'dyBP',vc=vc_dycore)
+ call tot_energy_phys(state, 'phBP')
+ call tot_energy_phys(state, 'dyBP',vc=vc_dycore)
! Save state for convective tendency calculations.
call diag_conv_tend_ini(state, pbuf)
@@ -2616,6 +2668,18 @@ subroutine tphysbc (ztodt, state, &
cldliqini(:ncol,:pver) = state%q(:ncol,:pver,ixcldliq)
cldiceini(:ncol,:pver) = state%q(:ncol,:pver,ixcldice)
+ totliqini(:ncol,:pver) = 0.0_r8
+ do m_cnst=1,thermodynamic_active_species_liq_num
+ m = thermodynamic_active_species_liq_idx(m_cnst)
+ totliqini(:ncol,:pver) = totliqini(:ncol,:pver)+state%q(:ncol,:pver,m)
+ end do
+ toticeini(:ncol,:pver) = 0.0_r8
+ do m_cnst=1,thermodynamic_active_species_ice_num
+ m = thermodynamic_active_species_ice_idx(m_cnst)
+ toticeini(:ncol,:pver) = toticeini(:ncol,:pver)+state%q(:ncol,:pver,m)
+ end do
+
+
call outfld('TEOUT', teout , pcols, lchnk )
call outfld('TEINP', state%te_ini(:,dyn_te_idx), pcols, lchnk )
call outfld('TEFIX', state%te_cur(:,dyn_te_idx), pcols, lchnk )
@@ -2828,6 +2892,7 @@ subroutine phys_timestep_init(phys_state, cam_in, cam_out, pbuf2d)
use iop_forcing, only: scam_use_iop_srf
use nudging, only: Nudge_Model, nudging_timestep_init
use waccmx_phys_intr, only: waccmx_phys_ion_elec_temp_timestep_init
+ use phys_grid_ctem, only: phys_grid_ctem_diags
implicit none
@@ -2895,6 +2960,9 @@ subroutine phys_timestep_init(phys_state, cam_in, cam_out, pbuf2d)
!----------------------------------
if(Nudge_Model) call nudging_timestep_init(phys_state)
+ ! Update TEM diagnostics
+ call phys_grid_ctem_diags(phys_state)
+
end subroutine phys_timestep_init
end module physpkg
diff --git a/src/physics/simple/physpkg.F90 b/src/physics/simple/physpkg.F90
index 353c245318..9c1e4c61bf 100644
--- a/src/physics/simple/physpkg.F90
+++ b/src/physics/simple/physpkg.F90
@@ -47,6 +47,8 @@ module physpkg
integer :: qini_idx = 0
integer :: cldliqini_idx = 0
integer :: cldiceini_idx = 0
+ integer :: totliqini_idx = 0
+ integer :: toticeini_idx = 0
logical :: state_debug_checks ! Debug physics_state.
@@ -117,6 +119,8 @@ subroutine phys_register
if (moist_physics) then
call pbuf_add_field('CLDLIQINI', 'physpkg', dtype_r8, (/pcols,pver/), cldliqini_idx)
call pbuf_add_field('CLDICEINI', 'physpkg', dtype_r8, (/pcols,pver/), cldiceini_idx)
+ call pbuf_add_field('TOTLIQINI', 'physpkg', dtype_r8, (/pcols,pver/), totliqini_idx)
+ call pbuf_add_field('TOTICEINI', 'physpkg', dtype_r8, (/pcols,pver/), toticeini_idx)
end if
! check energy package
@@ -198,6 +202,7 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out )
use phys_debug_util, only: phys_debug_init
use qneg_module, only: qneg_init
use cam_snapshot, only: cam_snapshot_init
+ use cam_budget, only: cam_budget_init
! Input/output arguments
type(physics_state), pointer :: phys_state(:)
@@ -267,6 +272,9 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out )
! Initialize the snapshot capability
call cam_snapshot_init(cam_in, cam_out, pbuf2d, begchunk)
+ ! Initialize energy budgets
+ call cam_budget_init()
+
end subroutine phys_init
!======================================================================================
@@ -469,9 +477,12 @@ subroutine tphysac (ztodt, cam_in, cam_out, state, tend, pbuf)
use cam_diagnostics, only: diag_phys_tend_writeout, diag_surf
use tj2016_cam, only: thatcher_jablonowski_sfc_pbl_hs_tend
use dycore, only: dycore_is
- use check_energy, only: calc_te_and_aam_budgets
+ use check_energy, only: tot_energy_phys
use cam_history, only: hist_fld_active
-
+ use cam_thermo, only: cam_thermo_water_update
+ use cam_budget, only: thermo_budget_history
+ use dyn_tests_utils, only: vc_dycore, vc_height, vc_dry_pressure
+ use air_composition, only: cpairv, cp_or_cv_dycore
! Arguments
!
real(r8), intent(in) :: ztodt ! Two times model timestep (2 delta-t)
@@ -492,20 +503,24 @@ subroutine tphysac (ztodt, cam_in, cam_out, state, tend, pbuf)
real(r8), pointer :: qini(:,:)
real(r8), pointer :: cldliqini(:,:)
real(r8), pointer :: cldiceini(:,:)
+ real(r8), pointer :: totliqini(:,:)
+ real(r8), pointer :: toticeini(:,:)
integer :: ixcldliq
integer :: ixcldice
integer :: k
- integer :: ncol
+ integer :: ncol, lchnk
integer :: itim_old
logical :: moist_mixing_ratio_dycore
real(r8) :: tmp_trac (pcols,pver,pcnst) ! tmp space
real(r8) :: tmp_pdel (pcols,pver) ! tmp space
real(r8) :: tmp_ps (pcols) ! tmp space
+ real(r8) :: scaling(pcols,pver)
!--------------------------------------------------------------------------
! number of active atmospheric columns
ncol = state%ncol
+ lchnk = state%lchnk
! Associate pointers with physics buffer fields
itim_old = pbuf_old_tim_idx()
@@ -518,11 +533,17 @@ subroutine tphysac (ztodt, cam_in, cam_out, state, tend, pbuf)
if (moist_physics) then
call pbuf_get_field(pbuf, cldliqini_idx, cldliqini)
call pbuf_get_field(pbuf, cldiceini_idx, cldiceini)
+ call pbuf_get_field(pbuf, totliqini_idx, totliqini)
+ call pbuf_get_field(pbuf, toticeini_idx, toticeini)
else
allocate(cldliqini(pcols, pver))
cldliqini = 0.0_r8
allocate(cldiceini(pcols, pver))
cldiceini = 0.0_r8
+ allocate(totliqini(pcols, pver))
+ totliqini = 0.0_r8
+ allocate(toticeini(pcols, pver))
+ toticeini = 0.0_r8
end if
!=========================
@@ -534,17 +555,19 @@ subroutine tphysac (ztodt, cam_in, cam_out, state, tend, pbuf)
call physics_update(state, ptend, ztodt, tend)
end if
- call calc_te_and_aam_budgets(state, 'phAP')
- call calc_te_and_aam_budgets(state, 'dyAP',vc=vc_dycore)
+ call tot_energy_phys(state, 'phAP')
+ call tot_energy_phys(state, 'dyAP',vc=vc_dycore)
! FV: convert dry-type mixing ratios to moist here because
! physics_dme_adjust assumes moist. This is done in p_d_coupling for
! other dynamics. Bundy, Feb 2004.
!
moist_mixing_ratio_dycore = dycore_is('LR').or. dycore_is('FV3')
- if (moist_physics .and. moist_mixing_ratio_dycore) then
- call set_dry_to_wet(state) ! Physics had dry, dynamics wants moist
- end if
+ !
+ ! update cp/cv for energy computation based in updated water variables
+ !
+ call cam_thermo_water_update(state%q(:ncol,:,:), lchnk, ncol, vc_dycore,&
+ to_dry_factor=state%pdel(:ncol,:)/state%pdeldry(:ncol,:))
if (moist_physics) then
! Scale dry mass and energy (does nothing if dycore is EUL or SLD)
@@ -561,44 +584,59 @@ subroutine tphysac (ztodt, cam_in, cam_out, state, tend, pbuf)
else
tmp_cldice(:ncol,:pver) = 0.0_r8
end if
-
- ! for dry mixing ratio dycore, physics_dme_adjust is called for energy diagnostic purposes only.
+ !
+ ! for dry mixing ratio dycore, physics_dme_adjust is called for energy diagnostic purposes only.
! So, save off tracers
- if (.not.moist_mixing_ratio_dycore.and.&
- (hist_fld_active('SE_phAM').or.hist_fld_active('KE_phAM').or.hist_fld_active('WV_phAM').or.&
- hist_fld_active('WL_phAM').or.hist_fld_active('WI_phAM').or.hist_fld_active('MR_phAM').or.&
- hist_fld_active('MO_phAM'))) then
- tmp_trac(:ncol,:pver,:pcnst) = state%q(:ncol,:pver,:pcnst)
- tmp_pdel(:ncol,:pver) = state%pdel(:ncol,:pver)
- tmp_ps(:ncol) = state%ps(:ncol)
+ if (.not.moist_mixing_ratio_dycore) then
+ !
+ ! for dry-mixing ratio based dycores dme_adjust takes place in the dynamical core
+ !
+ ! only compute dme_adjust for diagnostics purposes
+ !
+ if (thermo_budget_history) then
+ tmp_trac(:ncol,:pver,:pcnst) = state%q(:ncol,:pver,:pcnst)
+ tmp_pdel(:ncol,:pver) = state%pdel(:ncol,:pver)
+ tmp_ps(:ncol) = state%ps(:ncol)
+ call physics_dme_adjust(state, tend, qini, totliqini, toticeini, ztodt)
+ call tot_energy_phys(state, 'phAM')
+ call tot_energy_phys(state, 'dyAM', vc=vc_dycore)
+ ! Restore pre-"physics_dme_adjust" tracers
+ state%q(:ncol,:pver,:pcnst) = tmp_trac(:ncol,:pver,:pcnst)
+ state%pdel(:ncol,:pver) = tmp_pdel(:ncol,:pver)
+ state%ps(:ncol) = tmp_ps(:ncol)
+ end if
+ else
!
- ! pint, lnpint,rpdel are altered by dme_adjust but not used for tendencies in dynamics of SE
- ! we do not reset them to pre-dme_adjust values
+ ! for moist-mixing ratio based dycores
+ !
+ ! Note: this operation will NOT be reverted with set_wet_to_dry after set_dry_to_wet call
!
call set_dry_to_wet(state)
-
- call physics_dme_adjust(state, tend, qini, ztodt)
-
- call calc_te_and_aam_budgets(state, 'phAM')
- call calc_te_and_aam_budgets(state, 'dyAM',vc=vc_dycore)
- ! Restore pre-"physics_dme_adjust" tracers
- state%q(:ncol,:pver,:pcnst) = tmp_trac(:ncol,:pver,:pcnst)
- state%pdel(:ncol,:pver) = tmp_pdel(:ncol,:pver)
- state%ps(:ncol) = tmp_ps(:ncol)
- end if
-
- if (moist_mixing_ratio_dycore) then
- call physics_dme_adjust(state, tend, qini, ztodt)
- call calc_te_and_aam_budgets(state, 'phAM')
- call calc_te_and_aam_budgets(state, 'dyAM',vc=vc_dycore)
+ call physics_dme_adjust(state, tend, qini, totliqini, toticeini, ztodt)
+ call tot_energy_phys(state, 'phAM')
+ call tot_energy_phys(state, 'dyAM', vc=vc_dycore)
+ endif
+ if (vc_dycore == vc_height.or.vc_dycore == vc_dry_pressure) then
+ !
+ ! MPAS and SE specific scaling of temperature for enforcing energy consistency
+ ! (and to make sure that temperature dependent diagnostic tendencies
+ ! are computed correctly; e.g. dtcore)
+ !
+ scaling(1:ncol,:) = cpairv(:ncol,:,lchnk)/cp_or_cv_dycore(:ncol,:,lchnk)
+ state%T(1:ncol,:) = state%temp_ini(1:ncol,:)+&
+ scaling(1:ncol,:)*(state%T(1:ncol,:)-state%temp_ini(1:ncol,:))
+ tend%dtdt(:ncol,:) = scaling(:ncol,:)*tend%dtdt(:ncol,:)
+ !
+ ! else: do nothing for dycores with energy consistent with CAM physics
+ !
end if
-
+
else
tmp_q (:ncol,:pver) = 0.0_r8
tmp_cldliq(:ncol,:pver) = 0.0_r8
tmp_cldice(:ncol,:pver) = 0.0_r8
- call calc_te_and_aam_budgets(state, 'phAM')
- call calc_te_and_aam_budgets(state, 'dyAM',vc=vc_dycore)
+ call tot_energy_phys(state, 'phAM')
+ call tot_energy_phys(state, 'dyAM',vc=vc_dycore)
end if
! store T in buffer for use in computing dynamics T-tendency in next timestep
@@ -609,13 +647,15 @@ subroutine tphysac (ztodt, cam_in, cam_out, state, tend, pbuf)
end do
call diag_phys_tend_writeout (state, pbuf, tend, ztodt, &
- tmp_q, tmp_cldliq, tmp_cldice, qini, cldliqini, cldiceini)
+ qini, cldliqini, cldiceini)
call diag_surf(cam_in, cam_out, state, pbuf)
if (.not. moist_physics) then
deallocate(cldliqini)
deallocate(cldiceini)
+ deallocate(totliqini)
+ deallocate(toticeini)
end if
end subroutine tphysac
@@ -647,7 +687,7 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in )
use time_manager, only: get_nstep
use check_energy, only: check_energy_chng, check_energy_fix, check_energy_timestep_init
use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng
- use check_energy, only: calc_te_and_aam_budgets
+ use check_energy, only: tot_energy_phys
use chemistry, only: chem_is_active, chem_timestep_tend
use held_suarez_cam, only: held_suarez_tend
use kessler_cam, only: kessler_tend
@@ -656,6 +696,8 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in )
use cam_snapshot_common,only: cam_snapshot_all_outfld
use cam_snapshot_common,only: cam_snapshot_ptend_outfld
use physics_types, only: dyn_te_idx
+ use air_composition, only: thermodynamic_active_species_liq_num,thermodynamic_active_species_liq_idx
+ use air_composition, only: thermodynamic_active_species_ice_num,thermodynamic_active_species_ice_idx
! Arguments
real(r8), intent(in) :: ztodt ! model time increment
@@ -676,12 +718,15 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in )
integer :: itim_old
integer :: ixcldliq
integer :: ixcldice
+ integer :: m, m_cnst
! physics buffer fields for total energy and mass adjustment
real(r8), pointer :: teout(:)
real(r8), pointer :: qini(:,:)
real(r8), pointer :: cldliqini(:,:)
real(r8), pointer :: cldiceini(:,:)
+ real(r8), pointer :: totliqini(:,:)
+ real(r8), pointer :: toticeini(:,:)
real(r8), pointer :: dtcore(:,:)
real(r8) :: zero(pcols) ! array of zeros
@@ -709,6 +754,8 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in )
if (moist_physics) then
call pbuf_get_field(pbuf, cldliqini_idx, cldliqini)
call pbuf_get_field(pbuf, cldiceini_idx, cldiceini)
+ call pbuf_get_field(pbuf, totliqini_idx, totliqini)
+ call pbuf_get_field(pbuf, toticeini_idx, toticeini)
end if
! Set accumulated physics tendencies to 0
@@ -733,8 +780,8 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in )
!===================================================
! Global mean total energy fixer and AAM diagnostics
!===================================================
- call calc_te_and_aam_budgets(state, 'phBF')
- call calc_te_and_aam_budgets(state, 'dyBF',vc=vc_dycore)
+ call tot_energy_phys(state, 'phBF')
+ call tot_energy_phys(state, 'dyBF',vc=vc_dycore)
call t_startf('energy_fixer')
@@ -747,8 +794,8 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in )
call t_stopf('energy_fixer')
- call calc_te_and_aam_budgets(state, 'phBP')
- call calc_te_and_aam_budgets(state, 'dyBP',vc=vc_dycore)
+ call tot_energy_phys(state, 'phBP')
+ call tot_energy_phys(state, 'dyBP',vc=vc_dycore)
! Save state for convective tendency calculations.
call diag_conv_tend_ini(state, pbuf)
@@ -764,8 +811,17 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in )
if (ixcldice > 0) then
cldiceini(:ncol,:pver) = state%q(:ncol,:pver,ixcldice)
end if
+ totliqini(:ncol,:pver) = 0.0_r8
+ do m_cnst=1,thermodynamic_active_species_liq_num
+ m = thermodynamic_active_species_liq_idx(m_cnst)
+ totliqini(:ncol,:pver) = totliqini(:ncol,:pver)+state%q(:ncol,:pver,m)
+ end do
+ toticeini(:ncol,:pver) = 0.0_r8
+ do m_cnst=1,thermodynamic_active_species_ice_num
+ m = thermodynamic_active_species_ice_idx(m_cnst)
+ toticeini(:ncol,:pver) = toticeini(:ncol,:pver)+state%q(:ncol,:pver,m)
+ end do
end if
-
call outfld('TEOUT', teout , pcols, lchnk )
call outfld('TEINP', state%te_ini(:,dyn_te_idx), pcols, lchnk )
call outfld('TEFIX', state%te_cur(:,dyn_te_idx), pcols, lchnk )
diff --git a/src/utils/air_composition.F90 b/src/utils/air_composition.F90
index 367f52811a..6046ffebf1 100644
--- a/src/utils/air_composition.F90
+++ b/src/utils/air_composition.F90
@@ -1,4 +1,5 @@
-! air_composition module defines major species of the atmosphere and manages the physical properties that are dependent on the composition of air
+! air_composition module defines major species of the atmosphere and manages
+! the physical properties that are dependent on the composition of air
module air_composition
use shr_kind_mod, only: r8 => shr_kind_r8
@@ -10,7 +11,9 @@ module air_composition
public :: air_composition_readnl
public :: air_composition_init
- public :: air_composition_update
+ public :: dry_air_composition_update
+ public :: water_composition_update
+
! get_cp_dry: (generalized) heat capacity for dry air
public :: get_cp_dry
! get_cp: (generalized) heat capacity
@@ -102,7 +105,9 @@ module air_composition
real(r8), public, protected, allocatable :: cappav(:,:,:)
! mbarv: composition dependent atmosphere mean mass
real(r8), public, protected, allocatable :: mbarv(:,:,:)
-
+ ! cp_or_cv_dycore: enthalpy or internal energy scaling factor for
+ ! energy consistency
+ real(r8), public, protected, allocatable :: cp_or_cv_dycore(:,:,:)
!
! Interfaces for public routines
interface get_cp_dry
@@ -230,7 +235,6 @@ subroutine air_composition_init()
use physconst, only: r_universal, cpair, rair, cpwv, rh2o, cpliq, cpice, mwdry
use constituents, only: cnst_get_ind, cnst_mw
use ppgrid, only: pcols, pver, begchunk, endchunk
-
integer :: icnst, ix, isize, ierr, idx
integer :: liq_num, ice_num
integer :: liq_idx(water_species_in_air_num)
@@ -330,6 +334,10 @@ subroutine air_composition_init()
if (ierr /= 0) then
call endrun(errstr//"mbarv")
end if
+ allocate(cp_or_cv_dycore(pcols,pver,begchunk:endchunk), stat=ierr)
+ if (ierr /= 0) then
+ call endrun(errstr//"cp_or_cv_dycore")
+ end if
thermodynamic_active_species_idx = -HUGE(1)
thermodynamic_active_species_idx_dycore = -HUGE(1)
@@ -620,27 +628,63 @@ end subroutine air_composition_init
!===========================================================================
!-----------------------------------------------------------------------
- ! air_composition_update: Update the physics "constants" that vary
+ ! dry_air_composition_update: Update the physics "constants" that vary
!-------------------------------------------------------------------------
!===========================================================================
- subroutine air_composition_update(mmr, lchnk, ncol, to_moist_factor)
-
- real(r8), intent(in) :: mmr(:,:,:) ! constituents array
+ subroutine dry_air_composition_update(mmr, lchnk, ncol, to_dry_factor)
+ use cam_abortutils, only: endrun
+ !(mmr = dry mixing ratio, if not, use to_dry_factor to convert!)
+ real(r8), intent(in) :: mmr(:,:,:) ! mixing ratios for species dependent dry air
integer, intent(in) :: lchnk ! Chunk number
integer, intent(in) :: ncol ! number of columns
- real(r8), optional, intent(in) :: to_moist_factor(:,:)
+ real(r8), optional, intent(in) :: to_dry_factor(:,:)
call get_R_dry(mmr(:ncol, :, :), thermodynamic_active_species_idx, &
- rairv(:ncol, :, lchnk), fact=to_moist_factor)
- call get_cp_dry(mmr(:ncol,:,:), thermodynamic_active_species_idx, &
- cpairv(:ncol,:,lchnk), fact=to_moist_factor)
- call get_mbarv(mmr(:ncol,:,:), thermodynamic_active_species_idx, &
- mbarv(:ncol,:,lchnk), fact=to_moist_factor)
-
+ rairv(:ncol, :, lchnk), fact=to_dry_factor)
+ call get_cp_dry(mmr(:ncol,:,:), thermodynamic_active_species_idx, &
+ cpairv(:ncol,:,lchnk), fact=to_dry_factor)
+ call get_mbarv(mmr(:ncol,:,:), thermodynamic_active_species_idx, &
+ mbarv(:ncol,:,lchnk), fact=to_dry_factor)
cappav(:ncol,:,lchnk) = rairv(:ncol,:,lchnk) / cpairv(:ncol,:,lchnk)
+ end subroutine dry_air_composition_update
- end subroutine air_composition_update
+ !===========================================================================
+ !---------------------------------------------------------------------------
+ ! water_composition_update: Update generalized cp or cv depending on dycore
+ !---------------------------------------------------------------------------
+ !===========================================================================
+
+ subroutine water_composition_update(mmr, lchnk, ncol, vcoord, to_dry_factor)
+ use cam_abortutils, only: endrun
+ use string_utils, only: int2str
+ use dyn_tests_utils, only: vc_height, vc_moist_pressure, vc_dry_pressure
+ real(r8), intent(in) :: mmr(:,:,:) ! constituents array
+ integer, intent(in) :: lchnk ! Chunk number
+ integer, intent(in) :: ncol ! number of columns
+ integer, intent(in) :: vcoord
+ real(r8), optional, intent(in) :: to_dry_factor(:,:)
+
+ character(len=*), parameter :: subname = 'water_composition_update'
+
+ if (vcoord==vc_dry_pressure) then
+ call get_cp(mmr(:ncol,:,:),.false.,cp_or_cv_dycore(:ncol,:,lchnk), factor=to_dry_factor, &
+ active_species_idx_dycore=thermodynamic_active_species_idx,cpdry=cpairv(:ncol,:,lchnk))
+ else if (vcoord==vc_height) then
+ call get_R(mmr(:ncol,:,:), thermodynamic_active_species_idx, &
+ cp_or_cv_dycore(:ncol,:,lchnk), fact=to_dry_factor, Rdry=rairv(:ncol,:,lchnk))
+ !
+ ! internal energy coefficient for MPAS
+ ! (equation 92 in Eldred et al. 2023; https://rmets.onlinelibrary.wiley.com/doi/epdf/10.1002/qj.4353)
+ !
+ cp_or_cv_dycore(:ncol,:,lchnk)=cp_or_cv_dycore(:ncol,:,lchnk)*&
+ (cpairv(:ncol,:,lchnk)-rairv(:ncol,:,lchnk)) /rairv(:ncol,:,lchnk)
+ else if (vcoord==vc_moist_pressure) then
+ ! no update needed for moist pressure vcoord
+ else
+ call endrun(subname//" vertical coordinate not supported; vcoord="// int2str(vcoord))
+ end if
+ end subroutine water_composition_update
!===========================================================================
!***************************************************************************
@@ -750,29 +794,35 @@ end subroutine get_cp_dry_2hd
!
!***************************************************************************
!
- subroutine get_cp_1hd(tracer, inv_cp, cp, dp_dry, active_species_idx_dycore)
+ subroutine get_cp_1hd(tracer, inv_cp, cp, factor, active_species_idx_dycore, cpdry)
use cam_abortutils, only: endrun
use string_utils, only: int2str
! Dummy arguments
- ! tracedr: Tracer array
+ ! tracer: Tracer array
+ !
+ ! factor not present then tracer must be dry mixing ratio
+ ! if factor present tracer*factor must be dry mixing ratio
+ !
real(r8), intent(in) :: tracer(:,:,:)
- real(r8), optional, intent(in) :: dp_dry(:,:)
! inv_cp: output inverse cp instead of cp
logical, intent(in) :: inv_cp
real(r8), intent(out) :: cp(:,:)
+ ! dp: if provided then tracer is mass not mixing ratio
+ real(r8), optional, intent(in) :: factor(:,:)
! active_species_idx_dycore: array of indices for index of
! thermodynamic active species in dycore tracer array
! (if different from physics index)
integer, optional, intent(in) :: active_species_idx_dycore(:)
+ real(r8),optional, intent(in) :: cpdry(:,:)
- ! Local variables
+ ! LOCAL VARIABLES
integer :: qdx, itrac
real(r8) :: sum_species(SIZE(cp, 1), SIZE(cp, 2))
real(r8) :: sum_cp(SIZE(cp, 1), SIZE(cp, 2))
- real(r8) :: factor(SIZE(cp, 1), SIZE(cp, 2))
+ real(r8) :: factor_local(SIZE(cp, 1), SIZE(cp, 2))
integer :: idx_local(thermodynamic_active_species_num)
- character(len=*), parameter :: subname = 'get_cp_1hd: '
+ character(LEN=*), parameter :: subname = 'get_cp_1hd: '
if (present(active_species_idx_dycore)) then
if (SIZE(active_species_idx_dycore) /= &
@@ -786,51 +836,57 @@ subroutine get_cp_1hd(tracer, inv_cp, cp, dp_dry, active_species_idx_dycore)
idx_local = thermodynamic_active_species_idx
end if
- if (present(dp_dry)) then
- factor = 1.0_r8 / dp_dry
+ if (present(factor)) then
+ factor_local = factor
else
- factor = 1.0_r8
+ factor_local = 1.0_r8
end if
+
sum_species = 1.0_r8 ! all dry air species sum to 1
do qdx = dry_air_species_num + 1, thermodynamic_active_species_num
- itrac = idx_local(qdx)
- sum_species(:,:) = sum_species(:,:) + &
- (tracer(:,:,itrac) * factor(:,:))
+ itrac = idx_local(qdx)
+ sum_species(:,:) = sum_species(:,:) + (tracer(:,:,itrac) * factor_local(:,:))
end do
if (dry_air_species_num == 0) then
sum_cp = thermodynamic_active_species_cp(0)
+ else if (present(cpdry)) then
+ !
+ ! if cpdry is known don't recompute
+ !
+ sum_cp = cpdry
else
- call get_cp_dry(tracer, idx_local, sum_cp, fact=factor)
+ call get_cp_dry(tracer, idx_local, sum_cp, fact=factor_local)
end if
do qdx = dry_air_species_num + 1, thermodynamic_active_species_num
- itrac = idx_local(qdx)
- sum_cp(:,:) = sum_cp(:,:) + &
- (thermodynamic_active_species_cp(qdx) * tracer(:,:,itrac) * &
- factor(:,:))
+ itrac = idx_local(qdx)
+ sum_cp(:,:) = sum_cp(:,:)+ &
+ thermodynamic_active_species_cp(qdx) * tracer(:,:,itrac)* factor_local(:,:)
end do
if (inv_cp) then
- cp = sum_species / sum_cp
+ cp = sum_species / sum_cp
else
- cp = sum_cp / sum_species
+ cp = sum_cp / sum_species
end if
-
- end subroutine get_cp_1hd
+ end subroutine get_cp_1hd
!===========================================================================
- subroutine get_cp_2hd(tracer, inv_cp, cp, dp_dry, active_species_idx_dycore)
+ subroutine get_cp_2hd(tracer, inv_cp, cp, factor, active_species_idx_dycore, cpdry)
! Version of get_cp for arrays that have a second horizontal index
use cam_abortutils, only: endrun
use string_utils, only: int2str
! Dummy arguments
! tracer: Tracer array
+ !
real(r8), intent(in) :: tracer(:,:,:,:)
- real(r8), optional, intent(in) :: dp_dry(:,:,:)
! inv_cp: output inverse cp instead of cp
logical, intent(in) :: inv_cp
real(r8), intent(out) :: cp(:,:,:)
+ real(r8), optional, intent(in) :: factor(:,:,:)
+ real(r8), optional, intent(in) :: cpdry(:,:,:)
+
! active_species_idx_dycore: array of indicies for index of
! thermodynamic active species in dycore tracer array
! (if different from physics index)
@@ -842,11 +898,17 @@ subroutine get_cp_2hd(tracer, inv_cp, cp, dp_dry, active_species_idx_dycore)
character(len=*), parameter :: subname = 'get_cp_2hd: '
do jdx = 1, SIZE(cp, 2)
- if (present(dp_dry)) then
- call get_cp(tracer(:, jdx, :, :), inv_cp, cp(:, jdx, :), &
- dp_dry=dp_dry(:, jdx, :), active_species_idx_dycore=active_species_idx_dycore)
+ if (present(factor).and.present(cpdry)) then
+ call get_cp(tracer(:, jdx, :, :), inv_cp, cp(:, jdx, :),&
+ factor=factor(:, jdx, :), active_species_idx_dycore=active_species_idx_dycore, cpdry=cpdry(:,jdx,:))
+ else if (present(factor)) then
+ call get_cp(tracer(:, jdx, :, :), inv_cp, cp(:, jdx, :),&
+ factor=factor(:, jdx, :), active_species_idx_dycore=active_species_idx_dycore)
+ else if (present(cpdry)) then
+ call get_cp(tracer(:, jdx, :, :), inv_cp, cp(:, jdx, :),&
+ active_species_idx_dycore=active_species_idx_dycore, cpdry=cpdry(:,jdx,:))
else
- call get_cp(tracer(:, jdx, :, :), inv_cp, cp(:, jdx, :), &
+ call get_cp(tracer(:, jdx, :, :), inv_cp, cp(:, jdx, :),&
active_species_idx_dycore=active_species_idx_dycore)
end if
end do
@@ -955,9 +1017,10 @@ end subroutine get_R_dry_2hd
!
!***************************************************************************
!
- subroutine get_R_1hd(tracer, active_species_idx, R, fact)
+ subroutine get_R_1hd(tracer, active_species_idx, R, fact, Rdry)
use cam_abortutils, only: endrun
use string_utils, only: int2str
+ use physconst, only: rair
! Dummy arguments
! tracer: !tracer array
@@ -968,6 +1031,7 @@ subroutine get_R_1hd(tracer, active_species_idx, R, fact)
real(r8), intent(out) :: R(:, :)
! fact: optional factor for converting tracer to dry mixing ratio
real(r8), optional, intent(in) :: fact(:, :)
+ real(r8), optional, intent(in) :: Rdry(:, :)
! Local variables
integer :: qdx, itrac
@@ -986,12 +1050,19 @@ subroutine get_R_1hd(tracer, active_species_idx, R, fact)
call endrun(subname//"SIZE mismatch in dimension 2 "// &
int2str(SIZE(fact, 2))//' /= '//int2str(SIZE(factor, 2)))
end if
- call get_R_dry(tracer, active_species_idx, R, fact=fact)
factor = fact(:,:)
else
- call get_R_dry(tracer, active_species_idx, R)
factor = 1.0_r8
end if
+
+ if (dry_air_species_num == 0) then
+ R = rair
+ else if (present(Rdry)) then
+ R = Rdry
+ else
+ call get_R_dry(tracer, active_species_idx, R, fact=factor)
+ end if
+
idx_local = active_species_idx
sum_species = 1.0_r8 ! all dry air species sum to 1
do qdx = dry_air_species_num + 1, thermodynamic_active_species_num
@@ -1046,7 +1117,7 @@ end subroutine get_R_2hd
!*************************************************************************************************************************
!
subroutine get_mbarv_1hd(tracer, active_species_idx, mbarv_in, fact)
- use physconst, only: mwdry, rair, cpair
+ use physconst, only: mwdry
real(r8), intent(in) :: tracer(:,:,:) !tracer array
integer, intent(in) :: active_species_idx(:) !index of active species in tracer
real(r8), intent(out) :: mbarv_in(:,:) !molecular weight of dry air
diff --git a/src/utils/cam_grid_support.F90 b/src/utils/cam_grid_support.F90
index 30ffe78576..d86c829e77 100644
--- a/src/utils/cam_grid_support.F90
+++ b/src/utils/cam_grid_support.F90
@@ -314,6 +314,8 @@ end subroutine print_attr_spec
public :: cam_grid_is_zonal
! Functions for dealing with patch masks
public :: cam_grid_compute_patch
+ ! Functions for dealing with grid areas
+ public :: cam_grid_get_areawt
interface cam_grid_attribute_register
module procedure add_cam_grid_attribute_0d_int
@@ -1616,6 +1618,59 @@ function cam_grid_get_lonvals(id) result(lonvals)
end if
end function cam_grid_get_lonvals
+ function cam_grid_get_areawt(id) result(wtvals)
+
+ ! Dummy argument
+ integer, intent(in) :: id
+ real(r8), pointer :: wtvals(:)
+
+ ! Local variables
+ character(len=max_chars) :: wtname
+ integer :: gridind
+ class(cam_grid_attribute_t), pointer :: attrptr
+ character(len=120) :: errormsg
+
+ nullify(attrptr)
+ gridind = get_cam_grid_index(id)
+ if (gridind > 0) then
+ select case(cam_grids(gridind)%name)
+ case('GLL')
+ wtname='area_weight_gll'
+ case('EUL')
+ wtname='gw'
+ case('FV')
+ wtname='gw'
+ case('INI')
+ wtname='area_weight_ini'
+ case('physgrid')
+ wtname='areawt'
+ case('FVM')
+ wtname='area_weight_fvm'
+ case('mpas_cell')
+ wtname='area_weight_mpas'
+ case default
+ call endrun('cam_grid_get_areawt: Invalid gridname:'//trim(cam_grids(gridind)%name))
+ end select
+
+ call find_cam_grid_attr(gridind, trim(wtname), attrptr)
+ if (.not.associated(attrptr)) then
+ write(errormsg, '(4a)') &
+ 'cam_grid_get_areawt: error retrieving weight attribute ', trim(wtname), &
+ ' for cam grid ', cam_grids(gridind)%name
+ call endrun(errormsg)
+ else
+ call attrptr%print_attr()
+ select type(attrptr)
+ type is (cam_grid_attribute_1d_r8_t)
+ wtvals => attrptr%values
+ class default
+ call endrun('cam_grid_get_areawt: wt attribute is not a real datatype')
+ end select
+ end if
+ end if
+
+ end function cam_grid_get_areawt
+
! Find the longitude and latitude of a range of map entries
! beg and end are the range of the first source index. blk is a block or chunk index
subroutine cam_grid_get_coords(id, beg, end, blk, lon, lat)
@@ -2125,7 +2180,6 @@ subroutine write_cam_grid_attr_0d_int(attr, File)
type(file_desc_t), intent(inout) :: File ! PIO file Handle
! Local variables
- character(len=120) :: errormsg
integer :: attrtype
integer(imap) :: attrlen
integer :: ierr
@@ -2172,7 +2226,6 @@ subroutine write_cam_grid_attr_0d_char(attr, File)
type(file_desc_t), intent(inout) :: File ! PIO file Handle
! Local variables
- character(len=120) :: errormsg
integer :: attrtype
integer(imap) :: attrlen
integer :: ierr
@@ -2335,7 +2388,6 @@ end subroutine cam_grid_attribute_copy
!---------------------------------------------------------------------------
subroutine cam_grid_write_attr(File, grid_id, header_info)
use pio, only: file_desc_t, PIO_BCAST_ERROR, pio_seterrorhandling
- use pio, only: pio_inq_dimid
! Dummy arguments
type(file_desc_t), intent(inout) :: File ! PIO file Handle
@@ -2414,14 +2466,13 @@ subroutine cam_grid_write_attr(File, grid_id, header_info)
end subroutine cam_grid_write_attr
subroutine write_cam_grid_val_0d_int(attr, File)
- use pio, only: file_desc_t, pio_inq_varid, pio_put_var
+ use pio, only: file_desc_t, pio_put_var
! Dummy arguments
class(cam_grid_attribute_0d_int_t), intent(inout) :: attr
type(file_desc_t), intent(inout) :: File
! Local variables
- character(len=120) :: errormsg
integer :: ierr
! We only write this var if it is a variable
@@ -2448,7 +2499,7 @@ end subroutine write_cam_grid_val_0d_char
subroutine write_cam_grid_val_1d_int(attr, File)
use pio, only: file_desc_t, pio_put_var, pio_int, &
- pio_inq_varid, pio_write_darray, io_desc_t, pio_freedecomp
+ pio_write_darray, io_desc_t, pio_freedecomp
use cam_pio_utils, only: cam_pio_newdecomp
! Dummy arguments
@@ -2456,7 +2507,6 @@ subroutine write_cam_grid_val_1d_int(attr, File)
type(file_desc_t), intent(inout) :: File
! Local variables
- character(len=120) :: errormsg
integer :: ierr
type(io_desc_t), pointer :: iodesc
@@ -2486,7 +2536,7 @@ end subroutine write_cam_grid_val_1d_int
subroutine write_cam_grid_val_1d_r8(attr, File)
use pio, only: file_desc_t, pio_put_var, pio_double, &
- pio_inq_varid, pio_write_darray, io_desc_t, pio_freedecomp
+ pio_write_darray, io_desc_t, pio_freedecomp
use cam_pio_utils, only: cam_pio_newdecomp
! Dummy arguments
@@ -2494,7 +2544,6 @@ subroutine write_cam_grid_val_1d_r8(attr, File)
type(file_desc_t), intent(inout) :: File
! Local variables
- character(len=120) :: errormsg
integer :: ierr
type(io_desc_t), pointer :: iodesc
@@ -2999,7 +3048,7 @@ subroutine cam_grid_find_dimids(this, File, dimids)
integer, intent(out) :: dimids(:)
! Local vaariables
- integer :: dsize, ierr
+ integer :: ierr
integer :: err_handling
character(len=max_hcoordname_len) :: dimname1, dimname2
@@ -3880,8 +3929,6 @@ subroutine cam_grid_patch_get_decomp(this, field_lens, file_lens, dtype, &
end subroutine cam_grid_patch_get_decomp
subroutine cam_grid_patch_compact(this, collected_output)
- use spmd_utils, only: mpi_sum, mpi_integer, mpicom
- use shr_mpi_mod, only: shr_mpi_chkerr
! Dummy arguments
class(cam_grid_patch_t) :: this
diff --git a/src/utils/cam_thermo.F90 b/src/utils/cam_thermo.F90
index eaea52f328..f65649c4ef 100644
--- a/src/utils/cam_thermo.F90
+++ b/src/utils/cam_thermo.F90
@@ -7,7 +7,6 @@ module cam_thermo
use air_composition, only: thermodynamic_active_species_idx
use air_composition, only: thermodynamic_active_species_idx_dycore
use air_composition, only: thermodynamic_active_species_cp
- use air_composition, only: thermodynamic_active_species_cv
use air_composition, only: thermodynamic_active_species_R
use air_composition, only: thermodynamic_active_species_mwi
use air_composition, only: thermodynamic_active_species_kv
@@ -18,6 +17,7 @@ module cam_thermo
use air_composition, only: thermodynamic_active_species_liq_idx_dycore
use air_composition, only: thermodynamic_active_species_ice_idx
use air_composition, only: thermodynamic_active_species_ice_idx_dycore
+ use air_composition, only: dry_air_species_num
use air_composition, only: enthalpy_reference_state
use air_composition, only: mmro2, mmrn2, o2_mwi, n2_mwi, mbar
@@ -33,8 +33,10 @@ module cam_thermo
! cam_thermo_init: Initialize constituent dependent properties
public :: cam_thermo_init
- ! cam_thermo_update: Update constituent dependent properties
- public :: cam_thermo_update
+ ! cam_thermo_dry_air_update: Update dry air composition dependent properties
+ public :: cam_thermo_dry_air_update
+ ! cam_thermo_water_update: Update water dependent properties
+ public :: cam_thermo_water_update
! get_enthalpy: enthalpy quantity = dp*cp*T
public :: get_enthalpy
! get_virtual_temp: virtual temperature
@@ -170,6 +172,38 @@ module cam_thermo
! 2-d interface is not needed (but can easily be added)
end interface get_hydrostatic_energy
+ integer, public, parameter :: thermo_budget_num_vars = 10
+ integer, public, parameter :: wvidx = 1
+ integer, public, parameter :: wlidx = 2
+ integer, public, parameter :: wiidx = 3
+ integer, public, parameter :: seidx = 4 ! enthalpy or internal energy (W/m2) index
+ integer, public, parameter :: poidx = 5 ! surface potential or potential energy index
+ integer, public, parameter :: keidx = 6 ! kinetic energy index
+ integer, public, parameter :: mridx = 7
+ integer, public, parameter :: moidx = 8
+ integer, public, parameter :: ttidx = 9
+ integer, public, parameter :: teidx = 10
+ character (len = 2) ,public, dimension(thermo_budget_num_vars) :: thermo_budget_vars = &
+ (/"WV" ,"WL" ,"WI" ,"SE" ,"PO" ,"KE" ,"MR" ,"MO" ,"TT" ,"TE" /)
+ character (len = 46) ,public, dimension(thermo_budget_num_vars) :: thermo_budget_vars_descriptor = (/&
+ "Total column water vapor ",&
+ "Total column liquid water ",&
+ "Total column frozen water ",&
+ "Total column enthalpy or internal energy ",&
+ "Total column srf potential or potential energy",&
+ "Total column kinetic energy ",&
+ "Total column wind axial angular momentum ",&
+ "Total column mass axial angular momentum ",&
+ "Total column test_tracer ",&
+ "Total column energy (ke + se + po) "/)
+
+ character (len = 14), public, dimension(thermo_budget_num_vars) :: &
+ thermo_budget_vars_unit = (/&
+ "kg/m2 ","kg/m2 ","kg/m2 ","J/m2 ",&
+ "J/m2 ","J/m2 ","kg*m2/s*rad2 ","kg*m2/s*rad2 ",&
+ "kg/m2 ","J/m2 "/)
+ logical ,public, dimension(thermo_budget_num_vars) :: thermo_budget_vars_massv = (/&
+ .true.,.true.,.true.,.false.,.false.,.false.,.false.,.false.,.true.,.false./)
CONTAINS
!===========================================================================
@@ -177,7 +211,6 @@ module cam_thermo
subroutine cam_thermo_init()
use shr_infnan_mod, only: assignment(=), shr_infnan_qnan
use ppgrid, only: pcols, pver, pverp, begchunk, endchunk
- use physconst, only: cpair, rair, mwdry
integer :: ierr
character(len=*), parameter :: subname = "cam_thermo_init"
@@ -202,48 +235,65 @@ subroutine cam_thermo_init()
kmcnd(:pcols, :pver, begchunk:endchunk) = shr_infnan_qnan
end subroutine cam_thermo_init
-
- !===========================================================================
-
+ !
!***************************************************************************
!
- ! cam_thermo_update: update species dependent constants for physics
+ ! cam_thermo_dry_air_update: update dry air species dependent constants for physics
!
!***************************************************************************
!
- subroutine cam_thermo_update(mmr, T, lchnk, ncol, to_moist_factor)
- use air_composition, only: air_composition_update
+ subroutine cam_thermo_dry_air_update(mmr, T, lchnk, ncol, to_dry_factor)
+ use air_composition, only: dry_air_composition_update
use string_utils, only: int2str
- !-----------------------------------------------------------------------
- ! Update the physics "constants" that vary
- !-------------------------------------------------------------------------
-
!------------------------------Arguments----------------------------------
-
+ !(mmr = dry mixing ratio, if not use to_dry_factor to convert)
real(r8), intent(in) :: mmr(:,:,:) ! constituents array
real(r8), intent(in) :: T(:,:) ! temperature
integer, intent(in) :: lchnk ! Chunk number
integer, intent(in) :: ncol ! number of columns
- real(r8), optional, intent(in) :: to_moist_factor(:,:)
+ real(r8), optional, intent(in) :: to_dry_factor(:,:)!if mmr moist convert
!
!---------------------------Local storage-------------------------------
real(r8):: sponge_factor(SIZE(mmr, 2))
character(len=*), parameter :: subname = 'cam_thermo_update: '
-
- if (present(to_moist_factor)) then
- if (SIZE(to_moist_factor, 1) /= ncol) then
- call endrun(subname//'DIM 1 of to_moist_factor is'//int2str(SIZE(to_moist_factor,1))//'but should be'//int2str(ncol))
- end if
+ if (present(to_dry_factor)) then
+ if (SIZE(to_dry_factor, 1) /= ncol) then
+ call endrun(subname//'DIM 1 of to_dry_factor is'//int2str(SIZE(to_dry_factor,1))//'but should be'//int2str(ncol))
+ end if
end if
- sponge_factor = 1.0_r8
- call air_composition_update(mmr, lchnk, ncol, to_moist_factor=to_moist_factor)
+ sponge_factor = 1.0_r8
+ call dry_air_composition_update(mmr, lchnk, ncol, to_dry_factor=to_dry_factor)
call get_molecular_diff_coef(T(:ncol,:), .true., sponge_factor, kmvis(:ncol,:,lchnk), &
- kmcnd(:ncol,:,lchnk), tracer=mmr(:ncol,:,:), fact=to_moist_factor, &
+ kmcnd(:ncol,:,lchnk), tracer=mmr(:ncol,:,:), fact=to_dry_factor, &
active_species_idx_dycore=thermodynamic_active_species_idx)
+ end subroutine cam_thermo_dry_air_update
+ !
+ !***************************************************************************
+ !
+ ! cam_thermo_water+update: update water species dependent constants for physics
+ !
+ !***************************************************************************
+ !
+ subroutine cam_thermo_water_update(mmr, lchnk, ncol, vcoord, to_dry_factor)
+ use air_composition, only: water_composition_update
+ !-----------------------------------------------------------------------
+ ! Update the physics "constants" that vary
+ !-------------------------------------------------------------------------
+
+ !------------------------------Arguments----------------------------------
+
+ real(r8), intent(in) :: mmr(:,:,:) ! constituents array
+ integer, intent(in) :: lchnk ! Chunk number
+ integer, intent(in) :: ncol ! number of columns
+ integer, intent(in) :: vcoord
+ real(r8), optional, intent(in) :: to_dry_factor(:,:)
+ !
+ logical :: lcp
- end subroutine cam_thermo_update
+ call water_composition_update(mmr, lchnk, ncol, vcoord, to_dry_factor=to_dry_factor)
+ end subroutine cam_thermo_water_update
!===========================================================================
@@ -687,7 +737,6 @@ subroutine get_pmid_from_dpdry_1hd(tracer, mixing_ratio, active_species_idx, dp_
real(r8) :: dp_local(SIZE(tracer, 1), SIZE(tracer, 2)) ! local pressure level thickness
real(r8) :: pint_local(SIZE(tracer, 1), SIZE(tracer, 2) + 1)! local interface pressure
- integer :: kdx
call get_dp(tracer, mixing_ratio, active_species_idx, dp_dry, dp_local)
@@ -1258,7 +1307,8 @@ subroutine get_molecular_diff_coef_1hd(temp, get_at_interfaces, sponge_factor, k
real(r8), intent(in) :: temp(:,:) ! temperature
logical, intent(in) :: get_at_interfaces ! true: compute kmvis and kmcnd at interfaces
! false: compute kmvis and kmcnd at mid-levels
- real(r8), intent(in) :: sponge_factor(:) ! multiply kmvis and kmcnd with sponge_factor (for sponge layer)
+ real(r8), intent(in) :: sponge_factor(:) ! multiply kmvis and kmcnd with sponge_factor
+ ! (for sponge layer)
real(r8), intent(out) :: kmvis(:,:)
real(r8), intent(out) :: kmcnd(:,:)
real(r8), intent(in) :: tracer(:,:,:) ! tracer array
@@ -1334,7 +1384,8 @@ subroutine get_molecular_diff_coef_1hd(temp, get_at_interfaces, sponge_factor, k
residual = 1.0_r8
do icnst = 1, dry_air_species_num
ispecies = idx_local(icnst)
- mm = 0.5_r8 * (tracer(idx, kdx, ispecies) * factor(idx, kdx) + tracer(idx, kdx - 1, ispecies) * factor(idx, kdx-1))
+ mm = 0.5_r8 * (tracer(idx, kdx, ispecies) * factor(idx, kdx) + &
+ tracer(idx, kdx - 1, ispecies) * factor(idx, kdx-1))
kmvis(idx, kdx) = kmvis(idx, kdx) + thermodynamic_active_species_kv(icnst) * &
thermodynamic_active_species_mwi(icnst) * mm
kmcnd(idx, kdx) = kmcnd(idx, kdx) + thermodynamic_active_species_kc(icnst) * &
@@ -1396,7 +1447,8 @@ subroutine get_molecular_diff_coef_2hd(temp, get_at_interfaces, sponge_factor, k
real(r8), intent(in) :: temp(:,:,:) ! temperature
logical, intent(in) :: get_at_interfaces ! true: compute kmvis and kmcnd at interfaces
! false: compute kmvis and kmcnd at mid-levels
- real(r8), intent(in) :: sponge_factor(:) ! multiply kmvis and kmcnd with sponge_factor (for sponge layer)
+ real(r8), intent(in) :: sponge_factor(:) ! multiply kmvis and kmcnd with sponge_factor
+ ! (for sponge layer)
real(r8), intent(out) :: kmvis(:,:,:)
real(r8), intent(out) :: kmcnd(:,:,:)
real(r8), intent(in) :: tracer(:,:,:,:) ! tracer array
@@ -1523,20 +1575,23 @@ end subroutine cam_thermo_calc_kappav_2hd
!
!***************************************************************************
!
- subroutine get_hydrostatic_energy_1hd(tracer, pdel, cp_or_cv, U, V, T, &
- vcoord, ps, phis, z_mid, dycore_idx, qidx, te, se, ke, &
- wv, H2O, liq, ice)
+ subroutine get_hydrostatic_energy_1hd(tracer, moist_mixing_ratio, pdel_in, &
+ cp_or_cv, U, V, T, vcoord, ptop, phis, z_mid, dycore_idx, qidx, &
+ te, se, po, ke, wv, H2O, liq, ice)
use cam_logfile, only: iulog
use dyn_tests_utils, only: vc_height, vc_moist_pressure, vc_dry_pressure
use air_composition, only: wv_idx
- use physconst, only: gravit, latvap, latice
+ use physconst, only: rga, latvap, latice
! Dummy arguments
! tracer: tracer mixing ratio
+ !
+ ! note - if pdeldry passed to subroutine then tracer mixing ratio must be dry
real(r8), intent(in) :: tracer(:,:,:)
+ logical, intent(in) :: moist_mixing_ratio
! pdel: pressure level thickness
- real(r8), intent(in) :: pdel(:,:)
+ real(r8), intent(in) :: pdel_in(:,:)
! cp_or_cv: dry air heat capacity under constant pressure or
! constant volume (depends on vcoord)
real(r8), intent(in) :: cp_or_cv(:,:)
@@ -1544,7 +1599,7 @@ subroutine get_hydrostatic_energy_1hd(tracer, pdel, cp_or_cv, U, V, T, &
real(r8), intent(in) :: V(:,:)
real(r8), intent(in) :: T(:,:)
integer, intent(in) :: vcoord ! vertical coordinate
- real(r8), intent(in), optional :: ps(:)
+ real(r8), intent(in), optional :: ptop(:)
real(r8), intent(in), optional :: phis(:)
real(r8), intent(in), optional :: z_mid(:,:)
! dycore_idx: use dycore index for thermodynamic active species
@@ -1557,8 +1612,12 @@ subroutine get_hydrostatic_energy_1hd(tracer, pdel, cp_or_cv, U, V, T, &
real(r8), intent(out), optional :: te (:)
! KE: vertically integrated kinetic energy
real(r8), intent(out), optional :: ke (:)
- ! SE: vertically integrated internal+geopotential energy
+ ! SE: vertically integrated enthalpy (pressure coordinate)
+ ! or internal energy (z coordinate)
real(r8), intent(out), optional :: se (:)
+ ! PO: vertically integrated PHIS term (pressure coordinate)
+ ! or potential energy (z coordinate)
+ real(r8), intent(out), optional :: po (:)
! WV: vertically integrated water vapor
real(r8), intent(out), optional :: wv (:)
! liq: vertically integrated liquid
@@ -1568,10 +1627,12 @@ subroutine get_hydrostatic_energy_1hd(tracer, pdel, cp_or_cv, U, V, T, &
! Local variables
real(r8) :: ke_vint(SIZE(tracer, 1)) ! Vertical integral of KE
- real(r8) :: se_vint(SIZE(tracer, 1)) ! Vertical integral of SE
+ real(r8) :: se_vint(SIZE(tracer, 1)) ! Vertical integral of enthalpy or internal energy
+ real(r8) :: po_vint(SIZE(tracer, 1)) ! Vertical integral of PHIS or potential energy
real(r8) :: wv_vint(SIZE(tracer, 1)) ! Vertical integral of wv
real(r8) :: liq_vint(SIZE(tracer, 1)) ! Vertical integral of liq
real(r8) :: ice_vint(SIZE(tracer, 1)) ! Vertical integral of ice
+ real(r8) :: pdel(SIZE(tracer, 1),SIZE(tracer, 2)) !moist pressure level thickness
real(r8) :: latsub ! latent heat of sublimation
integer :: ierr
@@ -1618,51 +1679,56 @@ subroutine get_hydrostatic_energy_1hd(tracer, pdel, cp_or_cv, U, V, T, &
wvidx = wv_idx
end if
+ if (moist_mixing_ratio) then
+ pdel = pdel_in
+ else
+ pdel = pdel_in
+ do qdx = dry_air_species_num+1, thermodynamic_active_species_num
+ pdel(:,:) = pdel(:,:) + pdel_in(:, :)*tracer(:,:,species_idx(qdx))
+ end do
+ end if
+
+ ke_vint = 0._r8
+ se_vint = 0._r8
select case (vcoord)
case(vc_moist_pressure, vc_dry_pressure)
- if ((.not. present(ps)) .or. (.not. present(phis))) then
- write(iulog, *) subname, ' ps and phis must be present for ', &
+ if (.not. present(ptop).or. (.not. present(phis))) then
+ write(iulog, *) subname, ' ptop and phis must be present for ', &
'moist/dry pressure vertical coordinate'
- call endrun(subname//': ps and phis must be present for '// &
+ call endrun(subname//': ptop and phis must be present for '// &
'moist/dry pressure vertical coordinate')
end if
- ke_vint = 0._r8
- se_vint = 0._r8
- wv_vint = 0._r8
+ po_vint = ptop
do kdx = 1, SIZE(tracer, 2)
do idx = 1, SIZE(tracer, 1)
ke_vint(idx) = ke_vint(idx) + (pdel(idx, kdx) * &
- 0.5_r8 * (U(idx, kdx)**2 + V(idx, kdx)**2) / gravit)
+ 0.5_r8 * (U(idx, kdx)**2 + V(idx, kdx)**2)) * rga
se_vint(idx) = se_vint(idx) + (T(idx, kdx) * &
- cp_or_cv(idx, kdx) * pdel(idx, kdx) / gravit)
- wv_vint(idx) = wv_vint(idx) + (tracer(idx, kdx, wvidx) * &
- pdel(idx, kdx) / gravit)
+ cp_or_cv(idx, kdx) * pdel(idx, kdx) * rga)
+ po_vint(idx) = po_vint(idx)+pdel(idx, kdx)
+
end do
end do
do idx = 1, SIZE(tracer, 1)
- se_vint(idx) = se_vint(idx) + (phis(idx) * ps(idx) / gravit)
+ po_vint(idx) = (phis(idx) * po_vint(idx) * rga)
end do
case(vc_height)
- if (.not. present(z_mid)) then
- write(iulog, *) subname, &
- ' z_mid must be present for height vertical coordinate'
- call endrun(subname//': z_mid must be present for height '// &
- 'vertical coordinate')
+ if (.not. present(phis)) then
+ write(iulog, *) subname, ' phis must be present for ', &
+ 'heigt-based vertical coordinate'
+ call endrun(subname//': phis must be present for '// &
+ 'height-based vertical coordinate')
end if
- ke_vint = 0._r8
- se_vint = 0._r8
- wv_vint = 0._r8
+ po_vint = 0._r8
do kdx = 1, SIZE(tracer, 2)
do idx = 1, SIZE(tracer, 1)
ke_vint(idx) = ke_vint(idx) + (pdel(idx, kdx) * &
- 0.5_r8 * (U(idx, kdx)**2 + V(idx, kdx)**2) / gravit)
+ 0.5_r8 * (U(idx, kdx)**2 + V(idx, kdx)**2) * rga)
se_vint(idx) = se_vint(idx) + (T(idx, kdx) * &
- cp_or_cv(idx, kdx) * pdel(idx, kdx) / gravit)
+ cp_or_cv(idx, kdx) * pdel(idx, kdx) * rga)
! z_mid is height above ground
- se_vint(idx) = se_vint(idx) + (z_mid(idx, kdx) + &
- phis(idx) / gravit) * pdel(idx, kdx)
- wv_vint(idx) = wv_vint(idx) + (tracer(idx, kdx, wvidx) * &
- pdel(idx, kdx) / gravit)
+ po_vint(idx) = po_vint(idx) + (z_mid(idx, kdx) + &
+ phis(idx) * rga) * pdel(idx, kdx)
end do
end do
case default
@@ -1670,26 +1736,39 @@ subroutine get_hydrostatic_energy_1hd(tracer, pdel, cp_or_cv, U, V, T, &
call endrun(subname//': vertical coordinate not supported')
end select
if (present(te)) then
- te = se_vint + ke_vint
+ te = se_vint + po_vint+ ke_vint
end if
if (present(se)) then
se = se_vint
end if
+ if (present(po)) then
+ po = po_vint
+ end if
if (present(ke)) then
ke = ke_vint
end if
- if (present(wv)) then
- wv = wv_vint
- end if
!
! vertical integral of total liquid water
!
+ if (.not.moist_mixing_ratio) then
+ pdel = pdel_in! set pseudo density to dry
+ end if
+
+ wv_vint = 0._r8
+ do kdx = 1, SIZE(tracer, 2)
+ do idx = 1, SIZE(tracer, 1)
+ wv_vint(idx) = wv_vint(idx) + (tracer(idx, kdx, wvidx) * &
+ pdel(idx, kdx) * rga)
+ end do
+ end do
+ if (present(wv)) wv = wv_vint
+
liq_vint = 0._r8
do qdx = 1, thermodynamic_active_species_liq_num
do kdx = 1, SIZE(tracer, 2)
do idx = 1, SIZE(tracer, 1)
- liq_vint(idx) = liq_vint(idx) + (pdel(idx, kdx) * &
- tracer(idx, kdx, species_liq_idx(qdx)) / gravit)
+ liq_vint(idx) = liq_vint(idx) + (pdel(idx, kdx) * &
+ tracer(idx, kdx, species_liq_idx(qdx)) * rga)
end do
end do
end do
@@ -1703,7 +1782,7 @@ subroutine get_hydrostatic_energy_1hd(tracer, pdel, cp_or_cv, U, V, T, &
do kdx = 1, SIZE(tracer, 2)
do idx = 1, SIZE(tracer, 1)
ice_vint(idx) = ice_vint(idx) + (pdel(idx, kdx) * &
- tracer(idx, kdx, species_ice_idx(qdx)) / gravit)
+ tracer(idx, kdx, species_ice_idx(qdx)) * rga)
end do
end do
end do
@@ -1731,9 +1810,6 @@ subroutine get_hydrostatic_energy_1hd(tracer, pdel, cp_or_cv, U, V, T, &
end select
end if
deallocate(species_idx, species_liq_idx, species_ice_idx)
-
- end subroutine get_hydrostatic_energy_1hd
-
- !===========================================================================
+ end subroutine get_hydrostatic_energy_1hd
end module cam_thermo
diff --git a/src/utils/zonal_mean_mod.F90 b/src/utils/zonal_mean_mod.F90
index 3c41a4b4ec..25e3f8564a 100644
--- a/src/utils/zonal_mean_mod.F90
+++ b/src/utils/zonal_mean_mod.F90
@@ -1318,105 +1318,32 @@ subroutine Invert_Matrix(I_Mat,Nbas,O_InvMat)
!
! Invert_Matrix: Given the NbasxNbas matrix, calculate and return
! the inverse of the matrix.
+ !
+ ! Implemented with the LAPACK DGESV routine.
+ !
!====================================================================
- real(r8),parameter:: TINY = 1.e-20_r8
!
! Passed Variables
!------------------
- real(r8),intent(in ):: I_Mat (:,:)
- integer ,intent(in ):: Nbas
- real(r8),intent(out):: O_InvMat(:,:)
+ real(r8), intent(inout) :: I_Mat(:,:) ! input matrix contains P*L*U
+ ! decomposition on output
+ integer, intent(in) :: Nbas
+ real(r8), intent(out) :: O_InvMat(:,:)
!
! Local Values
!-------------
- real(r8),allocatable:: Mwrk(:,:),Rscl(:)
- integer ,allocatable:: Indx(:)
- real(r8):: Psgn,Mmax,Mval,Sval
- integer :: ii,jj,kk,ndx,i2,ii_max, astat
+ integer, allocatable :: Indx(:) ! pivot indices
+ integer :: astat, ii
character(len=*), parameter :: subname = 'Invert_Matrix'
+ character(len=80) :: msg
+
+ external DGESV
! Allocate work space
!---------------------
- allocate(Mwrk(Nbas,Nbas), stat=astat)
- call handle_allocate_error(astat, subname, 'Mwrk')
- allocate(Rscl(Nbas), stat=astat)
- call handle_allocate_error(astat, subname, 'Rscl')
allocate(Indx(Nbas), stat=astat)
call handle_allocate_error(astat, subname, 'Indx')
- ! Copy the Input matrix so it can be decomposed
- !-------------------------------------------------
- Mwrk(1:Nbas,1:Nbas) = I_Mat(1:Nbas,1:Nbas)
-
- ! Initailize Row scales
- !----------------------
- Psgn = 1._r8
- do ii=1,Nbas
- Mmax = 0._r8
- do jj=1,Nbas
- if(abs(Mwrk(ii,jj))>Mmax) Mmax = abs(Mwrk(ii,jj))
- end do
- if(Mmax==0._r8) then
- call endrun('Invert_Matrix: Singular Matrix')
- endif
- Rscl(ii) = 1._r8/Mmax
- end do
-
- ! Decompose the matrix
- !-----------------------
- do jj=1,Nbas
-
- if(jj>1) then
- do ii=1,(jj-1)
- Sval = Mwrk(ii,jj)
- if(ii>1) then
- do kk=1,(ii-1)
- Sval = Sval - Mwrk(ii,kk)*Mwrk(kk,jj)
- end do
- Mwrk(ii,jj) = Sval
- endif
- end do
- endif
-
- Mmax = 0._r8
- do ii=jj,Nbas
- Sval = Mwrk(ii,jj)
- if(jj>1) then
- do kk=1,(jj-1)
- Sval = Sval - Mwrk(ii,kk)*Mwrk(kk,jj)
- end do
- Mwrk(ii,jj) = Sval
- endif
- Mval = Rscl(ii)*abs(Sval)
- if(Mval>=Mmax) then
- ii_max = ii
- Mmax = Mval
- endif
- end do
-
- if(jj/=ii_max) then
- do kk=1,Nbas
- Mval = Mwrk(ii_max,kk)
- Mwrk(ii_max,kk) = Mwrk(jj,kk)
- Mwrk(jj,kk) = Mval
- end do
- Psgn = -Psgn
- Rscl(ii_max) = Rscl(jj)
- endif
-
- Indx(jj) = ii_max
- if(jj/=Nbas) then
- if(Mwrk(jj,jj)==0._r8) Mwrk(jj,jj) = TINY
- Mval = 1._r8/Mwrk(jj,jj)
- do ii=(jj+1),Nbas
- Mwrk(ii,jj) = Mwrk(ii,jj)*Mval
- end do
- endif
-
- end do ! jj=1,Nbas
-
- if(Mwrk(Nbas,Nbas)==0._r8) Mwrk(Nbas,Nbas) = TINY
-
! Initialize the inverse array with the identity matrix
!-------------------------------------------------------
O_InvMat(:,:) = 0._r8
@@ -1424,41 +1351,15 @@ subroutine Invert_Matrix(I_Mat,Nbas,O_InvMat)
O_InvMat(ii,ii) = 1._r8
end do
- ! Back substitution to construct the inverse
- !---------------------------------------------
- do kk=1,Nbas
-
- i2 = 0
- do ii=11,Nbas
- ndx = Indx(ii)
- Sval = O_InvMat(ndx,kk)
- O_InvMat(ndx,kk) = O_InvMat(ii,kk)
- if(i2/=0) then
- do jj=i2,(ii-1)
- Sval = Sval - Mwrk(ii,jj)*O_InvMat(jj,kk)
- end do
- elseif(Sval/=0._r8) then
- i2 = ii
- endif
- O_InvMat(ii,kk) = Sval
- end do
+ call DGESV(Nbas, Nbas, I_Mat, Nbas, Indx, O_InvMat, Nbas, astat)
- do ii=Nbas,1,-1
- Sval = O_InvMat(ii,kk)
- if(ii 0) then
+ call endrun(subname//': DGESV error return: matrix is singular')
+ end if
- ! Clean up this mess
- !---------------------
- deallocate(Mwrk)
- deallocate(Rscl)
deallocate(Indx)
end subroutine Invert_Matrix
diff --git a/test/system/archive_baseline.sh b/test/system/archive_baseline.sh
index adab681a88..8a19a4cf45 100755
--- a/test/system/archive_baseline.sh
+++ b/test/system/archive_baseline.sh
@@ -122,7 +122,7 @@ if [ -n "$CESM_TESTDIR" ]; then
cp -r $CESM_TESTDIR/baselines/. $root_baselinedir/$cam_tag
else
echo "Using bless_test_results to archive baselines."
- ../../cime/scripts/Tools/bless_test_results -p -t '' -c '' -r $CESM_TESTDIR --baseline-root $root_baselinedir -b $cam_tag -f -s
+ ../../cime/CIME/Tools/bless_test_results -p -t '' -c '' -r $CESM_TESTDIR --baseline-root $root_baselinedir -b $cam_tag -f -s
fi
echo " "