From 26eab1fc5ded5c299093ec97af47b42c394cb42d Mon Sep 17 00:00:00 2001 From: wwieder Date: Tue, 9 Jan 2024 13:30:36 -0700 Subject: [PATCH 1/8] NEONv3 updates --- .../NEON/defaults/shell_commands | 6 +- .../NEON/defaults/user_nl_datm_streams | 6 +- python/ctsm/site_and_regional/run_neon.py | 121 +++++++++--------- 3 files changed, 63 insertions(+), 70 deletions(-) diff --git a/cime_config/usermods_dirs/NEON/defaults/shell_commands b/cime_config/usermods_dirs/NEON/defaults/shell_commands index 39810dbc70..4447c3df63 100644 --- a/cime_config/usermods_dirs/NEON/defaults/shell_commands +++ b/cime_config/usermods_dirs/NEON/defaults/shell_commands @@ -19,12 +19,12 @@ TEST=`./xmlquery TEST --value` # For a transient case run the whole length and don't cycle if [[ $compset =~ ^HIST ]]; then - ./xmlchange DATM_YR_END=2022 + ./xmlchange DATM_YR_END=2023 ./xmlchange RUN_STARTDATE=2018-01-01 # Number of months that can be run for the full transient case if [[ $TEST != "TRUE" ]]; then ./xmlchange STOP_OPTION="nmonths" - ./xmlchange STOP_N=51 + ./xmlchange STOP_N=68 fi ./xmlchange CLM_NML_USE_CASE="2018-PD_transient" else @@ -43,5 +43,3 @@ fi # Explicitly set PIO Type to NETCDF since this is a single processor case (should already be set this way) ./xmlchange PIO_TYPENAME=netcdf - -./xmlchange NEONVERSION="v2" diff --git a/cime_config/usermods_dirs/NEON/defaults/user_nl_datm_streams b/cime_config/usermods_dirs/NEON/defaults/user_nl_datm_streams index bae77db6b5..dec731f337 100644 --- a/cime_config/usermods_dirs/NEON/defaults/user_nl_datm_streams +++ b/cime_config/usermods_dirs/NEON/defaults/user_nl_datm_streams @@ -23,18 +23,18 @@ !------------------------------------------------------------------------ presaero.SSP3-7.0:datafiles = $DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/aero/aerodep_clm_SSP370_b.e21.BWSSP370cmip6.f09_g17.CMIP6-SSP3-7.0-WACCM.001_2018-2030_monthly_0.9x1.25_c210826.nc presaero.SSP3-7.0:year_first=2018 -presaero.SSP3-7.0:year_last=2022 +presaero.SSP3-7.0:year_last=2023 presaero.SSP3-7.0:year_align=2018 presaero.SSP3-7.0:dtlimit=30 presndep.SSP3-7.0:datafiles = $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP3-7.0-WACCM_2018-2030_monthly_c210826.nc presndep.SSP3-7.0:year_first=2018 -presndep.SSP3-7.0:year_last=2022 +presndep.SSP3-7.0:year_last=2023 presndep.SSP3-7.0:year_align=2018 presndep.SSP3-7.0:dtlimit=30 preso3.SSP3-7.0:year_first=2018 -preso3.SSP3-7.0:year_last=2022 +preso3.SSP3-7.0:year_last=2023 preso3.SSP3-7.0:year_align=2018 preso3.SSP3-7.0:dtlimit=30 diff --git a/python/ctsm/site_and_regional/run_neon.py b/python/ctsm/site_and_regional/run_neon.py index a69dc0bdb0..4eb6d7d4e1 100755 --- a/python/ctsm/site_and_regional/run_neon.py +++ b/python/ctsm/site_and_regional/run_neon.py @@ -62,14 +62,11 @@ import time import pandas as pd -from standard_script_setup import * - # Get the ctsm util tools and then the cime tools. _CTSM_PYTHON = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "python")) sys.path.insert(1, _CTSM_PYTHON) from ctsm import add_cime_to_path - from CIME import build from CIME.case import Case from CIME.utils import safe_copy, expect, symlink_force @@ -78,6 +75,7 @@ from ctsm.utils import parse_isoduration from ctsm.download_utils import download_file + from standard_script_setup import * logger = logging.getLogger(__name__) @@ -352,7 +350,9 @@ def __init__(self, name, start_year, end_year, start_month, end_month, finidat): self.finidat = finidat def __str__(self): - return str(self.__class__) + "\n" + "\n".join((str(item) + " = " for item in self.__dict__)) + return ( + str(self.__class__) + "\n" + "\n".join((str(item) + " = " for item in (self.__dict__))) + ) def build_base_case( self, cesmroot, output_root, res, compset, overwrite=False, setup_only=False @@ -381,8 +381,8 @@ def build_base_case( output_root = os.getcwd() case_path = os.path.join(output_root, self.name) - logger.info("base_case_name : %s", self.name) - logger.info("user_mods_dir : %s", user_mods_dirs[0]) + logger.info("base_case_name : {}".format(self.name)) + logger.info("user_mods_dir : {}".format(user_mods_dirs[0])) if overwrite and os.path.isdir(case_path): print("Removing the existing case at: {}".format(case_path)) @@ -417,14 +417,12 @@ def build_base_case( if re.search("^HIST", compset, flags=re.IGNORECASE) is None: expect( match is None, - "Existing base case is a historical type and should " - + "not be -- rerun with the --overwrite option", + "Existing base case is a historical type and should not be -- rerun with the --overwrite option", ) else: expect( match is not None, - "Existing base case should be a historical type and " - + "is not -- rerun with the --overwrite option", + "Existing base case should be a historical type and is not -- rerun with the --overwrite option", ) # reset the case case.case_setup(reset=True) @@ -436,10 +434,10 @@ def build_base_case( print("---- base case build ------") print("--- This may take a while and you may see WARNING messages ---") # always walk through the build process to make sure it's up to date. - t_0 = time.time() + t0 = time.time() build.case_build(case_path, case=case) - t_1 = time.time() - total = t_1 - t_0 + t1 = time.time() + total = t1 - t0 print("Time required to building the base case: {} s.".format(total)) # update case_path to be the full path to the base case return case_path @@ -448,9 +446,23 @@ def diff_month(self): """ Determine difference between two dates in months """ - d_1 = datetime.datetime(self.end_year, self.end_month, 1) - d_2 = datetime.datetime(self.start_year, self.start_month, 1) - return (d_1.year - d_2.year) * 12 + d_1.month - d_2.month + d1 = datetime.datetime(self.end_year, self.end_month, 1) + d2 = datetime.datetime(self.start_year, self.start_month, 1) + return (d1.year - d2.year) * 12 + d1.month - d2.month + + def get_batch_query(self, case): + """ + Function for querying the batch queue query command for a case, depending on the + user's batch system. + + Args: + case: + case object + """ + + if case.get_value("BATCH_SYSTEM") == "none": + return "none" + return case.get_value("batch_query") def run_case( self, @@ -524,14 +536,12 @@ def run_case( if re.search("^HIST", compset, flags=re.IGNORECASE) is None: expect( match is None, - "Existing base case is a historical type and " - + "should not be -- rerun with the --overwrite option", + "Existing base case is a historical type and should not be -- rerun with the --overwrite option", ) else: expect( match is not None, - "Existing base case should be a historical type " - + "and is not -- rerun with the --overwrite option", + "Existing base case should be a historical type and is not -- rerun with the --overwrite option", ) if os.path.isfile(os.path.join(rundir, "ESMF_Profile.summary")): print("Case {} appears to be complete, not rerunning.".format(case_root)) @@ -545,13 +555,13 @@ def run_case( print(f"Use {batch_query} to check its run status") return else: - logger.warning("Case already exists in %s, not overwritting.", case_root) + logger.warning("Case already exists in {}, not overwritting.".format(case_root)) return if run_type == "postad": adcase_root = case_root.replace(".postad", ".ad") if not os.path.isdir(adcase_root): - logger.warning("postad requested but no ad case found in %s", adcase_root) + logger.warning("postad requested but no ad case found in {}".format(adcase_root)) return if not os.path.isdir(case_root): @@ -635,7 +645,9 @@ def set_ref_case(self, case): root = ".postad" if not os.path.isdir(ref_case_root): logger.warning( - "ERROR: spinup must be completed first, could not find directory %s", ref_case_root + "ERROR: spinup must be completed first, could not find directory {}".format( + ref_case_root + ) ) return False @@ -645,13 +657,13 @@ def set_ref_case(self, case): case.set_value("RUN_REFCASE", os.path.basename(ref_case_root)) refdate = None for reffile in glob.iglob(refrundir + "/{}{}.clm2.r.*.nc".format(self.name, root)): - mon = re.search(r"(\d\d\d\d-\d\d-\d\d)-\d\d\d\d\d.nc", reffile) - if mon: - refdate = mon.group(1) + m = re.search("(\d\d\d\d-\d\d-\d\d)-\d\d\d\d\d.nc", reffile) + if m: + refdate = m.group(1) symlink_force(reffile, os.path.join(rundir, os.path.basename(reffile))) - logger.info("Found refdate of %s", refdate) + logger.info("Found refdate of {}".format(refdate)) if not refdate: - logger.warning("Could not find refcase for %s", case_root) + logger.warning("Could not find refcase for {}".format(case_root)) return False for rpfile in glob.iglob(refrundir + "/rpointer*"): @@ -685,30 +697,13 @@ def modify_user_nl(self, case_root, run_type, rundir): "hist_mfilt = 20", "hist_nhtfrq = -8760", "hist_empty_htapes = .true.", - "hist_fincl1 = 'TOTECOSYSC', 'TOTECOSYSN', 'TOTSOMC', " - + "'TOTSOMN', 'TOTVEGC', 'TOTVEGN', 'TLAI', " - + "'GPP', 'CPOOL', 'NPP', 'TWS', 'H2OSNO'", + "hist_fincl1 = 'TOTECOSYSC', 'TOTECOSYSN', 'TOTSOMC', 'TOTSOMN', 'TOTVEGC', 'TOTVEGN', 'TLAI', 'GPP', 'CPOOL', 'NPP', 'TWS', 'H2OSNO'", ] if user_nl_lines: - with open(user_nl_fname, "a") as f_d: + with open(user_nl_fname, "a") as fd: for line in user_nl_lines: - f_d.write("{}\n".format(line)) - - -def get_batch_query(case): - """ - Function for querying the batch queue query command for a case, depending on the - user's batch system. - - Args: - case: - case object - """ - - if case.get_value("BATCH_SYSTEM") == "none": - return "none" - return case.get_value("batch_query") + fd.write("{}\n".format(line)) def check_neon_listing(valid_neon_sites): @@ -742,27 +737,27 @@ def parse_neon_listing(listing_file, valid_neon_sites): available_list = [] - d_f = pd.read_csv(listing_file) + df = pd.read_csv(listing_file) # check for finidat files for transient run - finidatlist = d_f[d_f["object"].str.contains("lnd/ctsm")] + finidatlist = df[df["object"].str.contains("lnd/ctsm")] # -- filter lines with atm/cdep - d_f = d_f[d_f["object"].str.contains("atm/cdeps/")] + df = df[df["object"].str.contains("atm/cdeps/")] # -- split the object str to extract site name - d_f = d_f["object"].str.split("/", expand=True) + df = df["object"].str.split("/", expand=True) # -- groupby site name - grouped_df = d_f.groupby(8) - for key, _ in grouped_df: + grouped_df = df.groupby(8) + for key, item in grouped_df: # -- check if it is a valid neon site if any(key in x for x in valid_neon_sites): site_name = key tmp_df = grouped_df.get_group(key) # -- filter files only ending with YYYY-MM.nc - tmp_df = tmp_df[tmp_df[9].str.contains(r"\d\d\d\d-\d\d.nc")] + tmp_df = tmp_df[tmp_df[9].str.contains("\d\d\d\d-\d\d.nc")] # -- find all the data versions # versions = tmp_df[7].unique() @@ -787,12 +782,12 @@ def parse_neon_listing(listing_file, valid_neon_sites): start_month = tmp_df2[1].iloc[0] end_month = tmp_df2[1].iloc[-1] - logger.debug("Valid neon site found: %s", site_name) - logger.debug("File version %s", latest_version) - logger.debug("start_year=%s", start_year) - logger.debug("end_year=%s", end_year) - logger.debug("start_month=%s", start_month) - logger.debug("end_month=%s", end_month) + logger.debug("Valid neon site " + site_name + " found!") + logger.debug("File version {}".format(latest_version)) + logger.debug("start_year={}".format(start_year)) + logger.debug("end_year={}".format(end_year)) + logger.debug("start_month={}".format(start_month)) + logger.debug("end_month={}".format(end_month)) finidat = None for line in finidatlist["object"]: if site_name in line: @@ -834,7 +829,7 @@ def main(description): ) = get_parser(sys.argv, description, valid_neon_sites) if output_root: - logger.debug("output_root : %s", output_root) + logger.debug("output_root : " + output_root) if not os.path.exists(output_root): os.makedirs(output_root) @@ -862,7 +857,7 @@ def main(description): cesmroot, output_root, res, compset, overwrite, setup_only ) logger.info("-----------------------------------") - logger.info("Running CTSM for neon site : %s", neon_site.name) + logger.info("Running CTSM for neon site : {}".format(neon_site.name)) neon_site.run_case( base_case_root, run_type, From c3d752bf09e6cd3f60fafbda741ac8b3e83c6c6a Mon Sep 17 00:00:00 2001 From: wwieder Date: Tue, 30 Jan 2024 10:29:48 -0700 Subject: [PATCH 2/8] turn on mimics v1 --- .../usermods_dirs/NEON/defaults/shell_commands | 12 ++++++++++++ cime_config/usermods_dirs/NEON/defaults/user_nl_clm | 9 +++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/cime_config/usermods_dirs/NEON/defaults/shell_commands b/cime_config/usermods_dirs/NEON/defaults/shell_commands index 4447c3df63..7f722743da 100644 --- a/cime_config/usermods_dirs/NEON/defaults/shell_commands +++ b/cime_config/usermods_dirs/NEON/defaults/shell_commands @@ -43,3 +43,15 @@ fi # Explicitly set PIO Type to NETCDF since this is a single processor case (should already be set this way) ./xmlchange PIO_TYPENAME=netcdf + + +# specific for MIMICS spinup +./xmlchange RUN_STARTDATE=0018-01-01 +./xmlchange RESUBMIT=1 +./xmlchange STOP_N=25 +./xmlchange STOP_OPTION=nyears +./xmlchange CLM_FORCE_COLDSTART=on +./xmlchange CONTINUE_RUN=False +./xmlchange JOB_QUEUE=develop +./xmlchange JOB_WALLCLOCK_TIME=1:00:00 + diff --git a/cime_config/usermods_dirs/NEON/defaults/user_nl_clm b/cime_config/usermods_dirs/NEON/defaults/user_nl_clm index 419ff0314c..c60076c58f 100644 --- a/cime_config/usermods_dirs/NEON/defaults/user_nl_clm +++ b/cime_config/usermods_dirs/NEON/defaults/user_nl_clm @@ -20,9 +20,10 @@ flanduse_timeseries = ' ' ! This isn't needed for a non transient case, but will be once we start using transient compsets fsurdat = "$DIN_LOC_ROOT/lnd/clm2/surfdata_map/NEON/surfdata_1x1_NEON_${NEONSITE}_hist_78pfts_CMIP6_simyr2000_c230601.nc" +soil_decomp_method = 'MIMICSWieder2015' ! h1 output stream -hist_fincl2 = 'AR','ELAI','FCEV','FCTR','FGEV','FIRA','FSA','FSH','GPP','H2OSOI', - 'HR','SNOW_DEPTH','TBOT','TSOI','SOILC_vr','FV','NET_NMIN_vr' -hist_mfilt(2) = 48 -hist_nhtfrq(2) = 1 +!hist_fincl2 = 'AR','ELAI','FCEV','FCTR','FGEV','FIRA','FSA','FSH','GPP','H2OSOI', +! 'HR','SNOW_DEPTH','TBOT','TSOI','SOILC_vr','FV','NET_NMIN_vr' +!hist_mfilt(2) = 48 +!hist_nhtfrq(2) = 1 From 3a9eab56549da06e59267575a5c14ab4e448aede Mon Sep 17 00:00:00 2001 From: wwieder Date: Thu, 1 Feb 2024 10:02:35 -0700 Subject: [PATCH 3/8] more mimics mods --- .../usermods_dirs/NEON/defaults/shell_commands | 5 +++-- cime_config/usermods_dirs/NEON/defaults/user_nl_clm | 11 ++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/cime_config/usermods_dirs/NEON/defaults/shell_commands b/cime_config/usermods_dirs/NEON/defaults/shell_commands index 7f722743da..2a5284e155 100644 --- a/cime_config/usermods_dirs/NEON/defaults/shell_commands +++ b/cime_config/usermods_dirs/NEON/defaults/shell_commands @@ -46,9 +46,10 @@ fi # specific for MIMICS spinup +./xmlchange DATM_YR_END=2021 ./xmlchange RUN_STARTDATE=0018-01-01 -./xmlchange RESUBMIT=1 -./xmlchange STOP_N=25 +./xmlchange RESUBMIT=20 +./xmlchange STOP_N=50 ./xmlchange STOP_OPTION=nyears ./xmlchange CLM_FORCE_COLDSTART=on ./xmlchange CONTINUE_RUN=False diff --git a/cime_config/usermods_dirs/NEON/defaults/user_nl_clm b/cime_config/usermods_dirs/NEON/defaults/user_nl_clm index c60076c58f..3906ddbbd8 100644 --- a/cime_config/usermods_dirs/NEON/defaults/user_nl_clm +++ b/cime_config/usermods_dirs/NEON/defaults/user_nl_clm @@ -22,8 +22,9 @@ flanduse_timeseries = ' ' ! This isn't needed for a non transient case, but wi fsurdat = "$DIN_LOC_ROOT/lnd/clm2/surfdata_map/NEON/surfdata_1x1_NEON_${NEONSITE}_hist_78pfts_CMIP6_simyr2000_c230601.nc" soil_decomp_method = 'MIMICSWieder2015' -! h1 output stream -!hist_fincl2 = 'AR','ELAI','FCEV','FCTR','FGEV','FIRA','FSA','FSH','GPP','H2OSOI', -! 'HR','SNOW_DEPTH','TBOT','TSOI','SOILC_vr','FV','NET_NMIN_vr' -!hist_mfilt(2) = 48 -!hist_nhtfrq(2) = 1 +hist_empty_htapes = .true. +hist_fincl1 = 'TOTLITC','TOTMICC','TOTSOMC','TOTLITN','TOTMICN','TOTSOMN', + 'LIT_MET_C_vr','LIT_STR_C_vr','MIC_COP_C_vr','MIC_OLI_C_vr', + 'SOM_AVL_C_vr', 'SOM_CHEM_C_vr', 'SOM_PHYS_C_vr', + 'TOTVEGC','TOTECOSYSC','GPP','AR','HR','ELAI' + From a004eb61c95046802ded7ed0a907175bf66e8737 Mon Sep 17 00:00:00 2001 From: wwieder Date: Thu, 1 Feb 2024 12:48:06 -0700 Subject: [PATCH 4/8] longer runs on cpu queue --- cime_config/usermods_dirs/NEON/defaults/shell_commands | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cime_config/usermods_dirs/NEON/defaults/shell_commands b/cime_config/usermods_dirs/NEON/defaults/shell_commands index 2a5284e155..500fafaa92 100644 --- a/cime_config/usermods_dirs/NEON/defaults/shell_commands +++ b/cime_config/usermods_dirs/NEON/defaults/shell_commands @@ -48,11 +48,13 @@ fi # specific for MIMICS spinup ./xmlchange DATM_YR_END=2021 ./xmlchange RUN_STARTDATE=0018-01-01 -./xmlchange RESUBMIT=20 -./xmlchange STOP_N=50 +./xmlchange RESUBMIT=5 +./xmlchange STOP_N=500 +./xmlchange REST_N=100 ./xmlchange STOP_OPTION=nyears ./xmlchange CLM_FORCE_COLDSTART=on ./xmlchange CONTINUE_RUN=False -./xmlchange JOB_QUEUE=develop -./xmlchange JOB_WALLCLOCK_TIME=1:00:00 +# Slow to run in develop queue, and this didn't wrok as intended. +#./xmlchange JOB_QUEUE=develop +#./xmlchange JOB_WALLCLOCK_TIME=1:00:00 From 34d33a4e019015bdbf5f0d593563c67e8c8c3441 Mon Sep 17 00:00:00 2001 From: wwieder Date: Fri, 9 Feb 2024 13:21:48 -0700 Subject: [PATCH 5/8] start removing fW from tau calculation & using beta --- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 65091755f5..aac933917c 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -439,12 +439,13 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat kslope_l1_m2 = params_inst%mimics_kslope(4) kslope_l2_m2 = params_inst%mimics_kslope(5) kslope_s1_m2 = params_inst%mimics_kslope(6) - vint_l1_m1 = params_inst%mimics_vint(1) - vint_l2_m1 = params_inst%mimics_vint(2) - vint_s1_m1 = params_inst%mimics_vint(3) - vint_l1_m2 = params_inst%mimics_vint(4) - vint_l2_m2 = params_inst%mimics_vint(5) - vint_s1_m2 = params_inst%mimics_vint(6) + ! WRW increased values by 30% here + vint_l1_m1 = params_inst%mimics_vint(1) * 1.3_r8 + vint_l2_m1 = params_inst%mimics_vint(2) * 1.3_r8 + vint_s1_m1 = params_inst%mimics_vint(3) * 1.3_r8 + vint_l1_m2 = params_inst%mimics_vint(4) * 1.3_r8 + vint_l2_m2 = params_inst%mimics_vint(5) * 1.3_r8 + vint_s1_m2 = params_inst%mimics_vint(6) * 1.3_r8 kint_l1_m1 = params_inst%mimics_kint(1) kint_l2_m1 = params_inst%mimics_kint(2) kint_s1_m1 = params_inst%mimics_kint(3) @@ -1175,10 +1176,13 @@ subroutine decomp_rates_mimics(bounds, num_bgc_soilc, filter_bgc_soilc, & ! tau ends up in units of per hour but is expected ! in units of per second, so convert here; alternatively ! place the conversion once in w_d_o_scalars - tau_m1 = mimics_tau_r_p1 * exp(mimics_tau_r_p2 * fmet) * tau_mod / & - secsphr - tau_m2 = mimics_tau_k_p1 * exp(mimics_tau_k_p2 * fmet) * tau_mod / & - secsphr + ! WRW remove NPP influence on turnover and increase base turnover 50% + !tau_m1 = mimics_tau_r_p1 * exp(mimics_tau_r_p2 * fmet) * tau_mod / & + ! secsphr + !tau_m2 = mimics_tau_k_p1 * exp(mimics_tau_k_p2 * fmet) * tau_mod / & + ! secsphr + tau_m1 = 1.5_r8 * mimics_tau_r_p1 * exp(mimics_tau_r_p2 * fmet) / secsphr + tau_m2 = 1.5_r8 * mimics_tau_k_p1 * exp(mimics_tau_k_p2 * fmet) / secsphr ! These two get used in SoilBiogeochemPotentialMod.F90 ! cn(c,i_cop_mic), cn(c,i_oli_mic) are CN_r, CN_k in the testbed code @@ -1288,14 +1292,20 @@ subroutine decomp_rates_mimics(bounds, num_bgc_soilc, filter_bgc_soilc, & decomp_k(c,j,i_chem_som) = (term_1 + term_2) * w_d_o_scalars ! Currently, mimics_densdep = 1 so as to have no effect - decomp_k(c,j,i_cop_mic) = tau_m1 * & - m1_conc**(mimics_densdep - 1.0_r8) * w_d_o_scalars + ! WRW, turns on beta function & removes w_d_o scalars + !decomp_k(c,j,i_cop_mic) = tau_m1 * & + ! m1_conc**(mimics_densdep - 1.0_r8) * w_d_o_scalars + decomp_k(c,j,i_cop_mic) = tau_m1 * m1_conc**(2.0_r8) + favl = min(1.0_r8, max(0.0_r8, 1.0_r8 - fphys_m1(c,j) - fchem_m1)) pathfrac_decomp_cascade(c,j,i_m1s1) = favl pathfrac_decomp_cascade(c,j,i_m1s2) = fchem_m1 - decomp_k(c,j,i_oli_mic) = tau_m2 * & - m2_conc**(mimics_densdep - 1.0_r8) * w_d_o_scalars + ! WRW turns on beta function & removes w_d_o scalars + !decomp_k(c,j,i_oli_mic) = tau_m2 * & + ! m2_conc**(mimics_densdep - 1.0_r8) * w_d_o_scalars + decomp_k(c,j,i_oli_mic) = tau_m2 * m2_conc**(2.0_r8) + favl = min(1.0_r8, max(0.0_r8, 1.0_r8 - fphys_m2(c,j) - fchem_m2)) pathfrac_decomp_cascade(c,j,i_m2s1) = favl pathfrac_decomp_cascade(c,j,i_m2s2) = fchem_m2 From a8c322cc17144aac77986cc5952d86707c52c443 Mon Sep 17 00:00:00 2001 From: wwieder Date: Sat, 10 Feb 2024 15:02:48 -0700 Subject: [PATCH 6/8] remove w_scalar from tau, correct beta --- .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 34 +++++++------------ 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index aac933917c..7232f7a168 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -439,13 +439,12 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat kslope_l1_m2 = params_inst%mimics_kslope(4) kslope_l2_m2 = params_inst%mimics_kslope(5) kslope_s1_m2 = params_inst%mimics_kslope(6) - ! WRW increased values by 30% here - vint_l1_m1 = params_inst%mimics_vint(1) * 1.3_r8 - vint_l2_m1 = params_inst%mimics_vint(2) * 1.3_r8 - vint_s1_m1 = params_inst%mimics_vint(3) * 1.3_r8 - vint_l1_m2 = params_inst%mimics_vint(4) * 1.3_r8 - vint_l2_m2 = params_inst%mimics_vint(5) * 1.3_r8 - vint_s1_m2 = params_inst%mimics_vint(6) * 1.3_r8 + vint_l1_m1 = params_inst%mimics_vint(1) + vint_l2_m1 = params_inst%mimics_vint(2) + vint_s1_m1 = params_inst%mimics_vint(3) + vint_l1_m2 = params_inst%mimics_vint(4) + vint_l2_m2 = params_inst%mimics_vint(5) + vint_s1_m2 = params_inst%mimics_vint(6) kint_l1_m1 = params_inst%mimics_kint(1) kint_l2_m1 = params_inst%mimics_kint(2) kint_s1_m1 = params_inst%mimics_kint(3) @@ -1176,13 +1175,10 @@ subroutine decomp_rates_mimics(bounds, num_bgc_soilc, filter_bgc_soilc, & ! tau ends up in units of per hour but is expected ! in units of per second, so convert here; alternatively ! place the conversion once in w_d_o_scalars - ! WRW remove NPP influence on turnover and increase base turnover 50% - !tau_m1 = mimics_tau_r_p1 * exp(mimics_tau_r_p2 * fmet) * tau_mod / & - ! secsphr - !tau_m2 = mimics_tau_k_p1 * exp(mimics_tau_k_p2 * fmet) * tau_mod / & - ! secsphr - tau_m1 = 1.5_r8 * mimics_tau_r_p1 * exp(mimics_tau_r_p2 * fmet) / secsphr - tau_m2 = 1.5_r8 * mimics_tau_k_p1 * exp(mimics_tau_k_p2 * fmet) / secsphr + tau_m1 = mimics_tau_r_p1 * exp(mimics_tau_r_p2 * fmet) * tau_mod / & + secsphr + tau_m2 = mimics_tau_k_p1 * exp(mimics_tau_k_p2 * fmet) * tau_mod / & + secsphr ! These two get used in SoilBiogeochemPotentialMod.F90 ! cn(c,i_cop_mic), cn(c,i_oli_mic) are CN_r, CN_k in the testbed code @@ -1292,19 +1288,13 @@ subroutine decomp_rates_mimics(bounds, num_bgc_soilc, filter_bgc_soilc, & decomp_k(c,j,i_chem_som) = (term_1 + term_2) * w_d_o_scalars ! Currently, mimics_densdep = 1 so as to have no effect - ! WRW, turns on beta function & removes w_d_o scalars - !decomp_k(c,j,i_cop_mic) = tau_m1 * & - ! m1_conc**(mimics_densdep - 1.0_r8) * w_d_o_scalars - decomp_k(c,j,i_cop_mic) = tau_m1 * m1_conc**(2.0_r8) + decomp_k(c,j,i_cop_mic) = tau_m1 * m1_conc**(mimics_densdep) favl = min(1.0_r8, max(0.0_r8, 1.0_r8 - fphys_m1(c,j) - fchem_m1)) pathfrac_decomp_cascade(c,j,i_m1s1) = favl pathfrac_decomp_cascade(c,j,i_m1s2) = fchem_m1 - ! WRW turns on beta function & removes w_d_o scalars - !decomp_k(c,j,i_oli_mic) = tau_m2 * & - ! m2_conc**(mimics_densdep - 1.0_r8) * w_d_o_scalars - decomp_k(c,j,i_oli_mic) = tau_m2 * m2_conc**(2.0_r8) + decomp_k(c,j,i_oli_mic) = tau_m2 * m2_conc**(mimics_densdep) favl = min(1.0_r8, max(0.0_r8, 1.0_r8 - fphys_m2(c,j) - fchem_m2)) pathfrac_decomp_cascade(c,j,i_m2s1) = favl From 3380488558bbf0ef1588d9dd0dc830ae4f35b2fa Mon Sep 17 00:00:00 2001 From: wwieder Date: Mon, 18 Mar 2024 06:44:40 -0600 Subject: [PATCH 7/8] adding Fi fluxes from @slevis-lmwg --- src/biogeochem/CNCStateUpdate1Mod.F90 | 23 +++++++++++++++---- src/biogeochem/CNNStateUpdate1Mod.F90 | 23 +++++++++++++++---- src/main/clm_varpar.F90 | 3 +++ src/main/pftconMod.F90 | 11 +++++++++ .../SoilBiogeochemDecompCascadeMIMICSMod.F90 | 17 ++++++-------- 5 files changed, 57 insertions(+), 20 deletions(-) diff --git a/src/biogeochem/CNCStateUpdate1Mod.F90 b/src/biogeochem/CNCStateUpdate1Mod.F90 index 5e38de2676..a0e0a5997e 100644 --- a/src/biogeochem/CNCStateUpdate1Mod.F90 +++ b/src/biogeochem/CNCStateUpdate1Mod.F90 @@ -12,6 +12,7 @@ module CNCStateUpdate1Mod use clm_varpar , only : ndecomp_cascade_transitions, nlevdecomp use clm_time_manager , only : get_step_size_real use clm_varpar , only : i_litr_min, i_litr_max, i_cwd + use clm_varpar , only : i_met_lit, i_str_lit, i_phys_som, i_chem_som use pftconMod , only : npcropmin, nc3crop, pftcon use abortutils , only : endrun use decompMod , only : bounds_type @@ -20,7 +21,7 @@ module CNCStateUpdate1Mod use CropType , only : crop_type use CropReprPoolsMod , only : nrepr, repr_grain_min, repr_grain_max use CropReprPoolsMod , only : repr_structure_min, repr_structure_max - use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con, use_soil_matrixcn + use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con, decomp_method, mimics_decomp, use_soil_matrixcn use SoilBiogeochemCarbonFluxType , only : soilbiogeochem_carbonflux_type use SoilBiogeochemCarbonStateType , only : soilbiogeochem_carbonstate_type use PatchType , only : patch @@ -172,6 +173,7 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & associate( & ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type + mimics_fi => pftcon%mimics_fi , & ! Input: MIMICS parameter fi woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) cascade_donor_pool => decomp_cascade_con%cascade_donor_pool , & ! Input: [integer (:) ] which pool is C taken from for a given decomposition step @@ -210,10 +212,21 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & ! if (.not. use_soil_matrixcn) then ! phenology and dynamic land cover fluxes - do i = i_litr_min, i_litr_max - cf_soil%decomp_cpools_sourcesink_col(c,j,i) = & - cf_veg%phenology_c_to_litr_c_col(c,j,i) * dt - end do + if (decomp_method == mimics_decomp) then + do i = i_litr_min, i_litr_max ! in MIMICS these are 1 and 2 + cf_soil%decomp_cpools_sourcesink_col(c,j,i) = (1 - mimics_fi(i)) * & + cf_veg%phenology_c_to_litr_c_col(c,j,i) * dt + end do + cf_soil%decomp_cpools_sourcesink_col(c,j,i_phys_som) = mimics_fi(1) * & + cf_veg%phenology_c_to_litr_c_col(c,j,i_met_lit) * dt + cf_soil%decomp_cpools_sourcesink_col(c,j,i_chem_som) = mimics_fi(2) * & + cf_veg%phenology_c_to_litr_c_col(c,j,i_str_lit) * dt + else + do i = i_litr_min, i_litr_max + cf_soil%decomp_cpools_sourcesink_col(c,j,i) = & + cf_veg%phenology_c_to_litr_c_col(c,j,i) * dt + end do + end if ! NOTE(wjs, 2017-01-02) This used to be set to a non-zero value, but the ! terms have been moved to CStateUpdateDynPatch. I think this is zeroed every diff --git a/src/biogeochem/CNNStateUpdate1Mod.F90 b/src/biogeochem/CNNStateUpdate1Mod.F90 index 833a65cbc3..e075cffb71 100644 --- a/src/biogeochem/CNNStateUpdate1Mod.F90 +++ b/src/biogeochem/CNNStateUpdate1Mod.F90 @@ -12,8 +12,9 @@ module CNNStateUpdate1Mod use clm_time_manager , only : get_step_size_real use clm_varpar , only : nlevdecomp use clm_varpar , only : i_litr_min, i_litr_max, i_cwd + use clm_varpar , only : i_met_lit, i_str_lit, i_phys_som, i_chem_som use clm_varctl , only : iulog, use_nitrif_denitrif - use SoilBiogeochemDecompCascadeConType, only : use_soil_matrixcn + use SoilBiogeochemDecompCascadeConType, only : decomp_method, mimics_decomp, use_soil_matrixcn use CNSharedParamsMod , only : use_matrixcn use clm_varcon , only : nitrif_n2o_loss_frac use pftconMod , only : npcropmin, pftcon @@ -129,6 +130,7 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & associate( & ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type + mimics_fi => pftcon%mimics_fi , & ! Input: MIMICS parameter fi woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) nf_veg => cnveg_nitrogenflux_inst , & ! Input: @@ -163,10 +165,21 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & ! State update without the matrix solution ! if (.not. use_soil_matrixcn) then ! to be consistent with C - do i = i_litr_min, i_litr_max - nf_soil%decomp_npools_sourcesink_col(c,j,i) = & - nf_veg%phenology_n_to_litr_n_col(c,j,i) * dt - end do + if (decomp_method == mimics_decomp) then + do i = i_litr_min, i_litr_max ! in MIMICS these are 1 and 2 + nf_soil%decomp_npools_sourcesink_col(c,j,i) = (1 - mimics_fi(i)) * & + nf_veg%phenology_n_to_litr_n_col(c,j,i) * dt + end do + nf_soil%decomp_npools_sourcesink_col(c,j,i_phys_som) = mimics_fi(1) * & + nf_veg%phenology_n_to_litr_n_col(c,j,i_met_lit) * dt + nf_soil%decomp_npools_sourcesink_col(c,j,i_chem_som) = mimics_fi(2) * & + nf_veg%phenology_n_to_litr_n_col(c,j,i_str_lit) * dt + else + do i = i_litr_min, i_litr_max + nf_soil%decomp_npools_sourcesink_col(c,j,i) = & + nf_veg%phenology_n_to_litr_n_col(c,j,i) * dt + end do + end if ! NOTE(wjs, 2017-01-02) This used to be set to a non-zero value, but the ! terms have been moved to CStateUpdateDynPatch. I think this is zeroed every diff --git a/src/main/clm_varpar.F90 b/src/main/clm_varpar.F90 index ffa851482a..7af8271454 100644 --- a/src/main/clm_varpar.F90 +++ b/src/main/clm_varpar.F90 @@ -82,6 +82,9 @@ module clm_varpar integer, public :: i_litr_min = -9 ! min index of litter pools; overwritten in SoilBiogeochemDecompCascade*Mod integer, public :: i_litr_max = -9 ! max index of litter pools; overwritten in SoilBiogeochemDecompCascade*Mod integer, public :: i_met_lit = -9 ! index of metabolic litter pool; overwritten in SoilBiogeochemDecompCascade*Mod + integer, public :: i_str_lit = -9 ! index of structural litter pool; overwritten in SoilBiogeochemDecompCascade*Mod + integer, public :: i_phys_som = -9 ! index of physically protected Soil Organic Matter (SOM); overwritten in SoilBiogeochemDecompCascade*Mod + integer, public :: i_chem_som = -9 ! index of chemically protected Soil Organic Matter (SOM); overwritten in SoilBiogeochemDecompCascade*Mod integer, public :: i_cop_mic = -9 ! index of copiotrophic microbial pool; overwritten in SoilBiogeochemDecompCascade*Mod integer, public :: i_oli_mic = -9 ! index of oligotrophic microbial pool; overwritten in SoilBiogeochemDecompCascade*Mod integer, public :: i_cwd = -9 ! index of cwd pool; overwritten in SoilBiogeochemDecompCascade*Mod diff --git a/src/main/pftconMod.F90 b/src/main/pftconMod.F90 index e5379100e0..9e1ff005b7 100644 --- a/src/main/pftconMod.F90 +++ b/src/main/pftconMod.F90 @@ -163,6 +163,9 @@ module pftconMod real(r8), allocatable :: rstem_per_dbh (:) ! stem resistance per dbh (s/m/m) real(r8), allocatable :: wood_density (:) ! wood density (kg/m3) + ! MIMICS + real(r8), allocatable :: mimics_fi(:) + ! crop ! These arrays give information about the merge of unused crop types to the types CLM @@ -506,6 +509,8 @@ subroutine InitAllocate (this) allocate( this%taper (0:mxpft) ) allocate( this%rstem_per_dbh (0:mxpft) ) allocate( this%wood_density (0:mxpft) ) + + allocate( this%mimics_fi(2) ) end subroutine InitAllocate @@ -1090,6 +1095,9 @@ subroutine InitRead(this) ! ! clm 5 nitrogen variables ! + call ncd_io('mimics_fi',this%mimics_fi, 'read', ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + if (use_flexibleCN) then call ncd_io('i_vcad', this%i_vcad, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) @@ -1132,6 +1140,7 @@ subroutine InitRead(this) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) call ncd_io('wood_density',this%wood_density, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + else this%dbh = 0.0_r8 this%fbw = 0.0_r8 @@ -1595,6 +1604,8 @@ subroutine Clean(this) deallocate( this%rstem_per_dbh) deallocate( this%wood_density) deallocate( this%taper) + + deallocate( this%mimics_fi) end subroutine Clean end module pftconMod diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index 7232f7a168..d554d59f8a 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -10,7 +10,7 @@ module SoilBiogeochemDecompCascadeMIMICSMod use shr_const_mod , only : SHR_CONST_TKFRZ use shr_log_mod , only : errMsg => shr_log_errMsg use clm_varpar , only : nlevdecomp, ndecomp_pools_max - use clm_varpar , only : i_met_lit, i_cop_mic, i_oli_mic, i_cwd + use clm_varpar , only : i_phys_som, i_chem_som, i_str_lit, i_met_lit, i_cop_mic, i_oli_mic, i_cwd use clm_varpar , only : i_litr_min, i_litr_max, i_cwdl2 use clm_varctl , only : iulog, spinup_state, anoxia, use_lch4, use_fates use clm_varcon , only : zsoi @@ -48,10 +48,7 @@ module SoilBiogeochemDecompCascadeMIMICSMod real(r8), private, allocatable :: fphys_m1(:,:) real(r8), private, allocatable :: fphys_m2(:,:) real(r8), private, allocatable :: p_scalar(:,:) - integer, private :: i_phys_som ! index of physically protected Soil Organic Matter (SOM) - integer, private :: i_chem_som ! index of chemically protected SOM integer, private :: i_avl_som ! index of available (aka active) SOM - integer, private :: i_str_lit ! index of structural litter pool integer, private :: i_l1m1 ! indices of transitions, eg l1m1: litter 1 -> first microbial pool integer, private :: i_l1m2 integer, private :: i_l2m1 @@ -439,12 +436,12 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat kslope_l1_m2 = params_inst%mimics_kslope(4) kslope_l2_m2 = params_inst%mimics_kslope(5) kslope_s1_m2 = params_inst%mimics_kslope(6) - vint_l1_m1 = params_inst%mimics_vint(1) - vint_l2_m1 = params_inst%mimics_vint(2) - vint_s1_m1 = params_inst%mimics_vint(3) - vint_l1_m2 = params_inst%mimics_vint(4) - vint_l2_m2 = params_inst%mimics_vint(5) - vint_s1_m2 = params_inst%mimics_vint(6) + vint_l1_m1 = params_inst%mimics_vint(1) + vint_l2_m1 = params_inst%mimics_vint(2) + vint_s1_m1 = params_inst%mimics_vint(3) + vint_l1_m2 = params_inst%mimics_vint(4) + vint_l2_m2 = params_inst%mimics_vint(5) + vint_s1_m2 = params_inst%mimics_vint(6) kint_l1_m1 = params_inst%mimics_kint(1) kint_l2_m1 = params_inst%mimics_kint(2) kint_s1_m1 = params_inst%mimics_kint(3) From f2dd8737737483b1cb3e486dae5ee8ace5d57d83 Mon Sep 17 00:00:00 2001 From: wwieder Date: Fri, 6 Sep 2024 16:29:25 -0600 Subject: [PATCH 8/8] usermods for MIMICS cases --- cime_config/usermods_dirs/NEON/defaults/user_nl_clm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cime_config/usermods_dirs/NEON/defaults/user_nl_clm b/cime_config/usermods_dirs/NEON/defaults/user_nl_clm index 0a22e746a3..1abf666dd0 100644 --- a/cime_config/usermods_dirs/NEON/defaults/user_nl_clm +++ b/cime_config/usermods_dirs/NEON/defaults/user_nl_clm @@ -19,10 +19,14 @@ !---------------------------------------------------------------------------------- soil_decomp_method = 'MIMICSWieder2015' +fsurdat = "/glade/derecho/scratch/wwieder/neon_AK/mods/surfdata_1x1_NEON_TOOL_test7.nc" +paramfile='/glade/derecho/scratch/wwieder/neon_AK/mods/ctsm60_params_vint1.3_taumod1.5_beta1.5.c240822.nc' hist_empty_htapes = .true. hist_fincl1 = 'TOTLITC','TOTMICC','TOTSOMC','TOTLITN','TOTMICN','TOTSOMN', + 'TOTECOSYSC','TOTVEGC','TOTECOSYSN','TOTVEGN', 'LIT_MET_C_vr','LIT_STR_C_vr','MIC_COP_C_vr','MIC_OLI_C_vr', 'SOM_AVL_C_vr', 'SOM_CHEM_C_vr', 'SOM_PHYS_C_vr', - 'TOTVEGC','TOTECOSYSC','GPP','AR','HR','ELAI' + 'GPP','AR','HR','ELAI','NBP','NEE','NEP', + 'TLAI','CPOOL','NPP','TWS','H2OSNO'