From d0e7e3b77f2cc3401f3f097e444ef28ff827f549 Mon Sep 17 00:00:00 2001 From: kvrigor Date: Mon, 22 Mar 2021 07:30:20 +0100 Subject: [PATCH] clm5nl-gen - CLM5 namelist generator script (#3) * Imported CLM5 namelist generator scripts * Made namelist generator installable with pip * Used PEP517 approach to packaging, with setuptools as build backend. More info: https://setuptools.readthedocs.io/en/latest/userguide/quickstart.html * Renamed 'build-clm5nl' to 'clm5nl-gen'. 'clm5nl-gen' sounds more unique which makes it easier to be "tab-completed" by the shell. --- .gitignore | 3 + namelist_generator/clm5nl-gen | 65 + .../clm5nl/generators/__init__.py | 0 .../clm5nl/generators/gen_lnd_in.py | 1447 +++++++++++ .../clm5nl/structures/__init__.py | 7 + .../clm5nl/structures/namelist.py | 106 + .../clm5nl/structures/nl_datm_in.py | 325 +++ .../clm5nl/structures/nl_drv_flds_in.py | 80 + .../clm5nl/structures/nl_drv_in.py | 2006 ++++++++++++++++ .../clm5nl/structures/nl_lnd_in.py | 2113 +++++++++++++++++ namelist_generator/clm5nl/structures/utils.py | 100 + namelist_generator/model_params_example.yaml | 63 + namelist_generator/pyproject.toml | 3 + namelist_generator/setup.cfg | 23 + namelist_generator/setup.py | 2 + 15 files changed, 6343 insertions(+) create mode 100755 namelist_generator/clm5nl-gen create mode 100644 namelist_generator/clm5nl/generators/__init__.py create mode 100755 namelist_generator/clm5nl/generators/gen_lnd_in.py create mode 100644 namelist_generator/clm5nl/structures/__init__.py create mode 100644 namelist_generator/clm5nl/structures/namelist.py create mode 100644 namelist_generator/clm5nl/structures/nl_datm_in.py create mode 100644 namelist_generator/clm5nl/structures/nl_drv_flds_in.py create mode 100644 namelist_generator/clm5nl/structures/nl_drv_in.py create mode 100644 namelist_generator/clm5nl/structures/nl_lnd_in.py create mode 100644 namelist_generator/clm5nl/structures/utils.py create mode 100644 namelist_generator/model_params_example.yaml create mode 100644 namelist_generator/pyproject.toml create mode 100644 namelist_generator/setup.cfg create mode 100644 namelist_generator/setup.py diff --git a/.gitignore b/.gitignore index 61a70ed75f..9aaf87ea63 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ src/externals/mct/Makefile.conf src/externals/mct/config.h src/externals/mct/config.log src/externals/mct/config.status + +# Python byte-compiled / optimized / DLL files +*.py[cod] \ No newline at end of file diff --git a/namelist_generator/clm5nl-gen b/namelist_generator/clm5nl-gen new file mode 100755 index 0000000000..4b9f4811da --- /dev/null +++ b/namelist_generator/clm5nl-gen @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 + +"""clm5nl-gen - CLM5 namelist generator + +Generates CLM5 namelists from model parameters file and saves +the outputs to a specified directory. If no directory is +specified, the namelists are saved to the current directory. + +Usage: + clm5nl-gen [--out DIR] PARAMFILE + clm5nl-gen (-h | --help) + clm5nl-gen (-v | --version) + +Arguments: + PARAMFILE model parameters file (.yaml) + +Options: + -o DIR --out DIR Save generated namelists to this directory. + -h --help Show this screen. + -v --version Show version. +""" +import sys +from pathlib import Path +from docopt import docopt +from ruamel.yaml import YAML +from clm5nl.generators.gen_lnd_in import build_lnd_in + +__version__ = "0.1" +args = docopt(__doc__, version="clm5nl-gen v" + __version__) +invalid_args = False +params_file = Path(args["PARAMFILE"]).absolute() +out_nl_file = "lnd_in" + +# Validate input args +if (not params_file.exists()): + print("clm5nl-gen error: Model parameter file '{}' not found.".format(params_file), file=sys.stderr) + invalid_args = True + +if (args["--out"] is None): + out_dir = Path.cwd() +else: + out_dir = Path(args["--out"]).absolute() + if (not out_dir.is_dir()): + print("clm5nl-gen error: Directory '{}' does not exist.".format(out_dir), file=sys.stderr) + invalid_args = True + +if invalid_args: sys.exit(-1) + +# Parse model parameters file +yaml = YAML(typ='safe') +print("Reading model parameters file from '{}'".format(params_file)) +config = yaml.load(open(params_file, "r")) + +opts, nl, drv_flds = {}, {}, {} +for category in config: + if category == "general_options": + opts = {k:(v if str(v).lower() != "none" else None) for k, v in config[category].items()} + elif category == "lnd_in": + nl = {k:v for k, v in config[category].items()} + elif category == "drv_flds_in": + drv_flds = {k:v for k, v in config[category].items()} + +# Build namelists +build_lnd_in(opts, nl, drv_flds, Path(out_dir, out_nl_file)) +print("Successfully generated '{}'".format(Path(out_dir, out_nl_file))) \ No newline at end of file diff --git a/namelist_generator/clm5nl/generators/__init__.py b/namelist_generator/clm5nl/generators/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/namelist_generator/clm5nl/generators/gen_lnd_in.py b/namelist_generator/clm5nl/generators/gen_lnd_in.py new file mode 100755 index 0000000000..82ea31ebb5 --- /dev/null +++ b/namelist_generator/clm5nl/generators/gen_lnd_in.py @@ -0,0 +1,1447 @@ +""" +Contains the core logic how the parameters in lnd_in are generated. +The codes are ported from the Perl script [CLMBuildNamelist.pm]. + +STATUS: This module is still **under heavy development**. Testing was done +only on one specific case. More work still needs to be done to cover all +CLM5 model capabilities. + +[CLMBuildNamelist.pm]: https://github.com/ESCOMP/CTSM/blob/03954bf6f697a019f289632636007a29a21e79d2/bld/CLMBuildNamelist.pm +""" +from ..structures import lnd_in, drv_in, drv_flds_in + +__all__ = ['build_lnd_in'] + +# Module-level variables +_env = {} +_in_opts = {} +_in_nl = {} +_in_nl_drv_flds = {} +_nl = lnd_in() +_nl_drv_flds = drv_flds_in() +_nl_drv = drv_in() + +def build_lnd_in(opts: dict = None, nl: dict = None, drv_flds: dict = None, nl_file: str = None): + + # Initialize module level variables + global _in_opts, _in_nl, _in_nl_drv_flds + global _nl, _nl_drv_flds, _nl_drv, _env + _in_opts = opts + _in_nl = nl + _in_nl_drv_flds = drv_flds + _nl = lnd_in() + _nl_drv_flds = drv_flds_in() + _nl_drv = drv_in() + _env = {"bgc_spinup":None, + "cnfireson":None, + "finundation_res":None, + "mask":None, + "use_case_desc":None} + + # Build lnd_in namelist + process_namelist_commandline_options() # high-level options (e.g sim year, bgc mode, spinup option, ) + process_namelist_commandline_use_case() # use case (e.g. 1850, 20th century, 2000, 2010, SSPx-y.z) + process_namelist_commandline_clm_start_type() # CLM start type (startup, branch, or continue) + process_namelist_inline_logic() # rest of namelist parameters + + # Write to file + if nl_file: _nl.write(nl_file) + +def process_namelist_commandline_options(): + #setup_cmdl_chk_res() + # _in_opts["chk_res"] = 0 + + #setup_cmdl_resolution() + _in_opts["res"] = "UNSET" + + #setup_cmdl_mask() + _env["mask"] = "gx1v6" + + setup_cmdl_bgc() + setup_cmdl_fire_light_res() #? + setup_cmdl_spinup() + setup_cmdl_crop() + + #setup_cmdl_maxpft() + _nl.clm_inparm.maxpatch_pft = 79 if _nl.clm_inparm.use_crop else 17 + + #setup_cmdl_glc_nec() + _nl_drv.seq_cplflds_inparm.glc_nec = 10 + + #setup_cmdl_irrigation() + #_env["irrig"] = False #only for CLM4.0 physics + + #setup_cmdl_ssp_rcp() + _in_opts["ssp_rcp"] = "hist" + + #setup_cmdl_simulation_year() + _in_opts["sim_year_range"] = "constant" + _in_opts["sim_year"] = 2000 + + setup_cmdl_dynamic_vegetation() + setup_cmdl_fates_mode() + + #setup_cmdl_vichydro() + if _in_opts["vichydro"] == 1: + _nl.clm_inparm.use_vichydro = True + + setup_cmdl_run_type() + #setup_cmdl_output_reals() + + #setup_logic_lnd_tuning() + _in_opts["lnd_tuning_mode"] = "clm5_0_GSWP3v1" + +def process_namelist_commandline_use_case(): + #2000_control.xml + _nl.clm_inparm.irrigate = True + _in_opts["sim_year"] = 2000 + _in_opts["sim_year_range"] = "constant" + _nl.ndepdyn_nml.stream_year_first_ndep = 2000 + _nl.ndepdyn_nml.stream_year_last_ndep = 2000 + _nl.popd_streams.stream_year_first_popdens = 2000 + _nl.popd_streams.stream_year_last_popdens = 2000 + _nl.urbantv_streams.stream_year_first_urbantv = 2000 + _nl.urbantv_streams.stream_year_last_urbantv = 2000 + _env["use_case_desc"] = "Conditions to simulate 2000 land-use" + +def process_namelist_commandline_clm_start_type(): + if _in_opts["clm_start_type"] == "cold" or _in_opts["clm_start_type"] == "arb_ic": + _nl_drv.seq_infodata_inparm.start_type = "startup" + else: + _nl_drv.seq_infodata_inparm.start_type = _in_opts["clm_start_type"] + +def error(msg): + raise ValueError(msg) + +def process_namelist_inline_logic(): + + ############################## + # namelist group: clm_inparm # + ############################## + setup_logic_site_specific() + setup_logic_lnd_frac() + setup_logic_co2_type() + setup_logic_irrigate() + setup_logic_start_type() + setup_logic_delta_time() + setup_logic_decomp_performance() + setup_logic_snow() + setup_logic_glacier() + setup_logic_dynamic_plant_nitrogen_alloc() + setup_logic_luna() + setup_logic_hydrstress() + setup_logic_dynamic_roots() + setup_logic_params_file() + setup_logic_create_crop_landunit() + setup_logic_subgrid() + setup_logic_fertilizer() + setup_logic_grainproduct() + setup_logic_soilstate() + setup_logic_demand() + setup_logic_surface_dataset() + if _in_opts["clm_start_type"] != "branch": + setup_logic_initial_conditions() + setup_logic_dynamic_subgrid() + setup_logic_spinup() + setup_logic_supplemental_nitrogen() + setup_logic_snowpack() + setup_logic_fates() + + ######################################### + # namelist group: atm2lnd_inparm + ######################################### + setup_logic_atm_forcing() + + ######################################### + # namelist group: lnd2atm_inparm + ######################################### + setup_logic_lnd2atm() + + ######################################### + # namelist group: clm_humanindex_inparm # + ######################################### + setup_logic_humanindex() + + ################################# + # namelist group: cnfire_inparm # + ################################# + setup_logic_cnfire() + + ###################################### + # namelist group: cnprecision_inparm # + ###################################### + setup_logic_cnprec() + + ############################### + # namelist group: clmu_inparm # + ############################### + setup_logic_urban() + + ############################### + # namelist group: crop # + ############################### + setup_logic_crop() + + ############################### + # namelist group: ch4par_in # + ############################### + setup_logic_methane() + setup_logic_c_isotope() + + ############################### + # namelist group: ndepdyn_nml # + ############################### + setup_logic_nitrogen_deposition() + + ########################################## + # namelist group: soil_moisture_streams # + ########################################## + setup_logic_soilm_streams() + + ################################## + # namelist group: cnmresp_inparm # + ################################## + setup_logic_cnmresp() + + ################################# + # namelist group: nitrif_inparm # + ################################# + setup_logic_nitrif_params() + + #################################### + # namelist group: photosyns_inparm # + #################################### + setup_logic_photosyns() + + ################################# + # namelist group: popd_streams # + ################################# + setup_logic_popd_streams() + + #################################### + # namelist group: urbantv_streams # + #################################### + setup_logic_urbantv_streams() + + ################################## + # namelist group: light_streams # + ################################## + setup_logic_lightning_streams() + + ################################# + # namelist group: drydep_inparm # + ################################# + setup_logic_dry_deposition() + + ################################# + # namelist group: fire_emis_nl # + ################################# + setup_logic_fire_emis() + + ################################# + # namelist group: megan_emis_nl # + ################################# + setup_logic_megan() + + ################################## + # namelist group: lai_streams # + ################################## + setup_logic_lai_streams() + + ################################## + # namelist group: bgc_shared + ################################## + setup_logic_bgc_shared() + + ############################################# + # namelist group: soilwater_movement_inparm # + ############################################# + setup_logic_soilwater_movement() + + ############################################# + # namelist group: rooting_profile_inparm # + ############################################# + setup_logic_rooting_profile() + + ############################################# + # namelist group: friction_velocity # + ############################################# + setup_logic_friction_vel() + + ################################################ + # namelist group: century_soilbgcdecompcascade # + ################################################ + setup_logic_century_soilbgcdecompcascade() + + ############################# + # namelist group: cngeneral # + ############################# + setup_logic_cngeneral() + + #################################### + # namelist group: cnvegcarbonstate # + #################################### + setup_logic_cnvegcarbonstate() + + ############################################# + # namelist group: soil_resis_inparm # + ############################################# + setup_logic_soil_resis() + + ############################################# + # namelist group: canopyfluxes_inparm # + ############################################# + setup_logic_canopyfluxes() + + ############################################# + # namelist group: canopyhydrology_inparm # + ############################################# + setup_logic_canopyhydrology() + + ##################################### + # namelist group: clm_canopy_inparm # + ##################################### + setup_logic_canopy() + + ######################################## + # namelist group: soilhydrology_inparm # + ######################################## + setup_logic_hydrology_params() + + ##################################### + # namelist group: irrigation_inparm # + ##################################### + setup_logic_irrigation_parameters() + + ####################################################################### + # namelist groups: clm_hydrology1_inparm and clm_soilhydrology_inparm # + ####################################################################### + setup_logic_hydrology_switches() + + ######################################### + # namelist group: clm_initinterp_inparm # + ######################################### + setup_logic_initinterp() + +def setup_logic_site_specific(): + if _in_opts["res"] == "1x1_vancouverCAN": + _nl.clm_inparm.use_vancouver = True + elif _in_opts["res"] == "1x1_mexicocityMEX": + _nl.clm_inparm.use_mexicocity = True + elif _in_opts["res"] == "1x1_smallvilleIA" or _in_opts["res"] == "1x1_numaIA": + if not (_in_opts["res"] or _nl.clm_inparm.use_crop): + error("{} grids must use a compset with CN and CROP turned on".format(_in_opts["res"])) + +def setup_logic_lnd_frac(): + _nl.clm_inparm.fatmlndfrc = _in_opts["lnd_frac"] + +def setup_logic_co2_type(): + _nl.clm_inparm.co2_type = _in_opts["co2_type"] + if _in_opts["co2_type"] == "constant": + if _in_opts["co2_ppmv"] is None: + if _in_opts["sim_year"] == 2100: + ssp_co2_defaults = {"SSP5-8.5":1135.2, "SSP5-3.4":496.6, "SSP1-2.6":445.6} + _nl.clm_inparm.co2_ppmv = ssp_co2_defaults.get(_in_opts["ssp_rcp"], "Invalid ssp_rcp value") + else: + yearly_co2_defaults = {"1000":379.0, "1850":284.7, "2000":379.0, "2010":388.8, "2015":397.5, "PtVg":284.7} + _nl.clm_inparm.co2_ppmv = yearly_co2_defaults.get(_in_opts["sim_year"],"Invalid sim_year value") + else: + if _in_opts["co2_ppmv"] <= 0: + error("co2_ppmv can NOT be less than or equal to zero") + else: + _nl.clm_inparm.co2_ppmv = _in_opts["co2_ppmv"] + +def setup_logic_irrigate(): + _nl.clm_inparm.irrigate = not (_nl.clm_inparm.use_crop and _nl.clm_inparm.use_cndv) + +def setup_logic_start_type(): + my_start_type = _in_opts["clm_start_type"] + if not _in_opts["override_nsrest"] == None: + start_type = {0:"startup", 1:"continue", 3:"branch"} + my_start_type = start_type.get(_in_opts["override_nsrest"], "Invalid start_type value") + if my_start_type == _nl_drv.seq_infodata_inparm.start_type: + error("no need to set override_nsrest to same as start_type") + if _nl_drv.seq_infodata_inparm.start_type != "startup": + error("can NOT set override_nsrest if driver is NOT a startup type") + _nl.clm_inparm.override_nsrest = _in_opts["override_nsrest"] + + if my_start_type == "branch": + if _in_opts["nrevsn"] is None: + error("nrevsn is required for a branch type.") + else: + _nl.clm_inparm.nrevsn = _in_opts["nrevsn"] + if _in_opts["use_init_interp"]: + print("WARNING: use_init_interp will NOT happen for a branch case.") + else: + if not _in_opts["nrevsn"] is None: + error("nrevsn should ONLY be set for a branch type") + if _in_opts["use_init_interp"]: + _nl.clm_inparm.use_init_interp = True + +def setup_logic_delta_time(): + if _in_opts["l_ncpl"] is None: + _nl.clm_inparm.dtime = 1800 + else: + if _in_opts["l_ncpl"] <= 0: + error("bad value for -l_ncpl option") + if _in_opts["dtime"] is None: + _nl.clm_inparm.dtime = (3600 * 24) / _in_opts["l_ncpl"] + else: + error("can NOT set both -l_ncpl option (via LND_NCPL env variable) AND dtime namelist variable.") + +def setup_logic_decomp_performance(): + _nl.clm_inparm.nsegspc = 35 + +def setup_logic_snow(): + _nl.clm_canopyhydrology_inparm.snowveg_flag = "ON_RAD" + if _in_nl["fsnowoptics"] is not None: + _nl.clm_inparm.fsnowoptics = _in_nl["fsnowoptics"] + else: + _nl.clm_inparm.fsnowoptics = "lnd/clm2/snicardata/snicar_optics_5bnd_c090915.nc" + if _in_nl["fsnowaging"] is not None: + _nl.clm_inparm.fsnowaging = _in_nl["fsnowaging"] + else: + _nl.clm_inparm.fsnowaging = "lnd/clm2/snicardata/snicar_drdt_bst_fit_60_c070416.nc" + +def setup_logic_glacier(): + # glc_do_dynglacier is set via GLC_TWO_WAY_COUPLING; it cannot be set via + # user_nl_clm (this is because we might eventually want the coupler and glc + # to also respond to GLC_TWO_WAY_COUPLING, by not bothering to send / map + # these fields - so we want to ensure that CLM is truly listening to this + # shared xml variable and not overriding it) + with _nl.clm_inparm as n: + n.glc_do_dynglacier = _in_opts["GLC_TWO_WAY_COUPLING"] + n.maxpatch_glcmec = _in_opts["glc_nec"] + n.glc_snow_persistence_max_days = 0 + n.albice = [0.50, 0.30] + + with _nl.clm_glacier_behavior as n: + n.glacier_region_behavior = ["single_at_atm_topo", "virtual", "virtual", "multiple"] + n.glacier_region_melt_behavior = ["remains_in_place", "replaced_by_ice", "replaced_by_ice", "replaced_by_ice"] + n.glacier_region_ice_runoff_behavior = ["melted", "melted", "remains_ice", "remains_ice"] + n.glacier_region_rain_to_snow_behavior = ["converted_to_snow", "converted_to_snow", "converted_to_snow", "converted_to_snow"] + +def setup_logic_dynamic_plant_nitrogen_alloc(): + if _nl.clm_inparm.use_cn: + _nl.clm_inparm.use_cn = True + _nl.clm_inparm.use_flexibleCN = True + with _nl.clm_nitrogen as n: + n.MM_Nuptake_opt = True + n.downreg_opt = False + n.plant_ndemand_opt = 3 + n.substrate_term_opt = True + n.nscalar_opt = True + n.temp_scalar_opt = True + n.CNratio_floating = True + n.reduce_dayl_factor = False + n.vcmax_opt = 3 + n.CN_residual_opt = 1 + n.CN_partition_opt = 1 + n.CN_evergreen_phenology_opt = 1 + n.carbon_resp_opt = 0 if _nl.clm_inparm.use_fun else 1 + +def setup_logic_luna(): + _nl.clm_inparm.use_luna = not _nl.clm_inparm.use_fates + _nl.clm_inparm.use_nguardrail = _nl.clm_inparm.use_cn + if _nl.clm_inparm.use_luna or _nl.clm_nitrogen.vcmax_opt == 3 or _nl.clm_nitrogen.vcmax_opt == 4: + _nl.clm_nitrogen.lnc_opt = _nl.clm_inparm.use_cn + if _nl.clm_nitrogen.lnc_opt and not _nl.clm_inparm.use_cn: + error("Cannot turn lnc_opt to true when bgc=sp") + if _nl.clm_inparm.use_luna: + _nl.luna.jmaxb1 = 0.093563 + +def setup_logic_hydrstress(): + _nl.clm_inparm.use_hydrstress = not _nl.clm_inparm.use_fates + +def setup_logic_dynamic_roots(): + with _nl.clm_inparm as n: + n.use_dynroot = _in_opts["use_dynroot"] + if n.use_dynroot: + if _in_opts["bgc_mode"] == "sp": + error("Cannot turn dynroot mode on mode bgc=sp. Set the bgc mode to 'cn' or 'bgc'") + if n.use_hydrstress: + error("Cannot turn use_dynroot on when use_hydrstress is on") + +def setup_logic_params_file(): + if _in_nl["paramfile"] is not None: + _nl.clm_inparm.paramfile = _in_nl["paramfile"] + else: + _nl.clm_inparm.paramfile = "lnd/clm2/paramdata/clm5_params.c171117.nc" + +def setup_logic_create_crop_landunit(): + _nl.clm_inparm.create_crop_landunit = not _nl.clm_inparm.use_fates + +def setup_logic_subgrid(): + _nl.clm_inparm.run_zero_weight_urban = False + +def setup_logic_fertilizer(): + _nl.clm_inparm.use_fertilizer = _nl.clm_inparm.use_crop + +def setup_logic_grainproduct(): + _nl.clm_inparm.use_grainproduct = _nl.clm_inparm.use_crop + +def setup_logic_soilstate(): + _nl.clm_soilstate_inparm.organic_frac_squared = False + _nl.clm_inparm.soil_layerstruct = "20SL_8.5m" + _nl.clm_inparm.use_bedrock = not (_nl.clm_inparm.use_fates or _in_opts["vichydro"] == 1) + +def setup_logic_demand(): + # Deal with options that the user has said are required... + pass + +def setup_logic_surface_dataset(): + if not _nl.dynamic_subgrid.flanduse_timeseries is None: + if _nl.clm_inparm.use_cndv: error("dynamic PFT's (setting flanduse_timeseries) are incompatible with dynamic vegetation (use_cndv=.true)") + if _nl.clm_inparm.use_fates: error("dynamic PFT's (setting flanduse_timeseries) are incompatible with ecosystem dynamics (use_fates=.true)") + if _in_nl["fsurdat"] is not None: + _nl.clm_inparm.fsurdat = _in_nl["fsurdat"] + else: + surface_file = {} + if _in_opts["sim_year"] == "1850": + if _nl.clm_inparm.use_crop: + surface_file["48x96"] = "release-clm5.0.18/surfdata_48x96_hist_78pfts_CMIP6_simyr1850_c190214.nc" + surface_file["0.9x1.25"] ="release-clm5.0.18/surfdata_0.9x1.25_hist_78pfts_CMIP6_simyr1850_c190214.nc" + surface_file["1.9x2.5"] = "release-clm5.0.18/surfdata_1.9x2.5_hist_78pfts_CMIP6_simyr1850_c190304.nc" + surface_file["10x15"] = "release-clm5.0.18/surfdata_10x15_hist_78pfts_CMIP6_simyr1850_c190214.nc" + surface_file["4x5"] = "release-clm5.0.18/surfdata_4x5_hist_78pfts_CMIP6_simyr1850_c190214.nc" + surface_file["1x1_smallvilleIA"] = "release-clm5.0.18/surfdata_1x1_smallvilleIA_hist_78pfts_CMIP6_simyr1850_c190214.nc" + surface_file["1x1_numaIA"] = "release-clm5.0.18/surfdata_1x1_numaIA_hist_78pfts_CMIP6_simyr1850_c190214.nc" + surface_file["1x1_brazil"] = "release-clm5.0.18/surfdata_1x1_brazil_hist_78pfts_CMIP6_simyr1850_c190214.nc" + surface_file["ne30np4"] = "landuse.timeseries_ne30np4_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c170824.nc" + elif not _nl.clm_inparm.use_crop and _nl.clm_inparm.irrigate: + surface_file["48x96"] = "release-clm5.0.18/surfdata_48x96_hist_16pfts_Irrig_CMIP6_simyr1850_c190214.nc" + surface_file["0.9x1.25"] = "release-clm5.0.18/surfdata_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr1850_c190214.nc" + surface_file["1.9x2.5"] = "release-clm5.0.18/surfdata_1.9x2.5_hist_16pfts_Irrig_CMIP6_simyr1850_c190304.nc" + surface_file["10x15"] = "release-clm5.0.18/surfdata_10x15_hist_16pfts_Irrig_CMIP6_simyr1850_c190214.nc" + surface_file["4x5"] = "release-clm5.0.18/surfdata_4x5_hist_16pfts_Irrig_CMIP6_simyr1850_c190214.nc" + surface_file["1x1_brazil"] = "release-clm5.0.18/surfdata_1x1_brazil_hist_16pfts_Irrig_CMIP6_simyr1850_c190214.nc" + surface_file["ne30np4"] = "release-clm5.0.18/surfdata_ne30np4_hist_16pfts_Irrig_CMIP6_simyr1850_c190303.nc" + elif _in_opts["sim_year"] == "2000": + if _nl.clm_inparm.use_crop: + surface_file["0.9x1.25"] = "release-clm5.0.18/surfdata_0.9x1.25_hist_78pfts_CMIP6_simyr2000_c190214.nc" + surface_file["1.9x2.5"] = "release-clm5.0.18/surfdata_1.9x2.5_hist_78pfts_CMIP6_simyr2000_c190304.nc" + surface_file["10x15"] = "release-clm5.0.18/surfdata_10x15_hist_78pfts_CMIP6_simyr2000_c190214.nc" + surface_file["4x5"] = "release-clm5.0.18/surfdata_4x5_hist_78pfts_CMIP6_simyr2000_c190214.nc" + surface_file["1x1_numaIA"] = "release-clm5.0.18/surfdata_1x1_numaIA_hist_78pfts_CMIP6_simyr2000_c190214.nc" + surface_file["1x1_smallvilleIA"] = "release-clm5.0.18/surfdata_1x1_smallvilleIA_hist_78pfts_CMIP6_simyr2000_c190214.nc" + surface_file["ne30np4"] = "release-clm5.0.18/surfdata_ne30np4_hist_78pfts_CMIP6_simyr2000_c190303.nc" + surface_file["ne16np4"] = "release-clm5.0.18/surfdata_ne16np4_hist_78pfts_CMIP6_simyr2000_c190214.nc" + elif not _nl.clm_inparm.use_crop and _nl.clm_inparm.irrigate: + surface_file["48x96"] = "release-clm5.0.18/surfdata_48x96_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc" + surface_file["0.9x1.25"] = "release-clm5.0.18/surfdata_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc" + surface_file["1.9x2.5"] = "release-clm5.0.18/surfdata_1.9x2.5_hist_16pfts_Irrig_CMIP6_simyr2000_c190304.nc" + surface_file["4x5"] = "release-clm5.0.18/surfdata_4x5_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc" + surface_file["10x15"] = "release-clm5.0.18/surfdata_10x15_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc" + surface_file["ne30np4"] = "release-clm5.0.18/surfdata_ne30np4_hist_16pfts_Irrig_CMIP6_simyr2000_c190303.nc" + surface_file["ne16np4"] = "release-clm5.0.18/surfdata_ne16np4_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc" + surface_file["5x5_amazon"] = "release-clm5.0.18/surfdata_5x5_amazon_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc" + surface_file["1x1_brazil"] = "release-clm5.0.18/surfdata_1x1_brazil_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc" + surface_file["64x128"] = "release-clm5.0.18/surfdata_64x128_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc" + surface_file["1x1_camdenNJ"] = "release-clm5.0.18/surfdata_1x1_camdenNJ_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc" + surface_file["1x1_vancouverCAN"] = "release-clm5.0.18/surfdata_1x1_vancouverCAN_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc" + surface_file["1x1_mexicocityMEX"] = "release-clm5.0.18/surfdata_1x1_mexicocityMEX_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc" + surface_file["1x1_urbanc_alpha"] = "release-clm5.0.18/surfdata_1x1_urbanc_alpha_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc" + elif _in_opts["sim_year"] == "2100" and _nl.clm_inparm.use_crop: + if _in_opts["ssp_rcp"] == "SSP1-2.6": + surface_file["0.9x1.25"] = "release-clm5.0.30/surfdata_0.9x1.25_SSP1-2.6_78pfts_CMIP6_simyr2100_c200329.nc" + elif _in_opts["ssp_rcp"] == "SSP1-2.6": + surface_file["0.9x1.25"] = "release-clm5.0.30/surfdata_0.9x1.25_SSP5-8.5_78pfts_CMIP6_simyr2100_c200330.nc" + elif _in_opts["ssp_rcp"] == "SSP1-2.6": + surface_file["0.9x1.25"] = "release-clm5.0.30/surfdata_0.9x1.25_SSP5-3.4_78pfts_CMIP6_simyr2100_c200330.nc" + elif _in_opts["sim_year"] == "PtVg" and not _nl.clm_inparm.use_crop and not _nl.clm_inparm.irrigate: + # Potential vegetation land use dataset, crop is off, and zeroed, all areas are natural vegetation without human disturbance + surface_file["0.9x1.25"] = "surfdata_0.9x1.25_hist_16pfts_nourb_CMIP6_simyrPtVg_c181114.nc" + sf = surface_file.get(_in_opts["res"], None) + if not sf is None: + _nl.clm_inparm.fsurdat = "lnd/clm2/surfdata_map/" + sf + +def setup_logic_initial_conditions(): + if _in_opts["clm_start_type"] == "cold": + if not _in_nl["finidat"] is None: + print(""" + WARNING: setting finidat (either explicitly in your user_nl_clm or by doing a hybrid or branch RUN_TYPE) is + incomptable with using a cold start (by setting CLM_FORCE_COLDSTART=on) + Overridding input finidat file with one specifying that this is a cold start from arbitrary initial conditions.""") + _in_opts["finidat"] = "' '" + elif not _in_nl["finidat"] is None and _in_nl["finidat"] == "' '": + error("""You are setting finidat to blank which signals arbitrary initial conditions. + But, CLM_FORCE_COLDSTART is off which is a contradiction. For arbitrary initial conditions just use the CLM_FORCE_COLDSTART option + To do a cold-start set ./xmlchange CLM_FORCE_COLDSTART=on, and remove the setting of finidat in the user_nl_clm file""") + + if _in_nl["finidat"] is None: + #TODO + pass + else: + _nl.clm_inparm.finidat = _in_nl["finidat"] + +def setup_logic_dynamic_subgrid(): + # Options controlling which parts of flanduse_timeseries to use + setup_logic_do_transient_pfts() + setup_logic_do_transient_crops() + setup_logic_do_harvest() + +def setup_logic_do_transient_pfts(): + cannot_be_true = "" + default_val = True + if _nl.dynamic_subgrid.flanduse_timeseries is None: + cannot_be_true = "do_transient_pfts can only be set to true when running a transient case (flanduse_timeseries non-blank)" + elif _nl.clm_inparm.use_cndv: + cannot_be_true = "do_transient_pfts cannot be combined with use_cndv" + elif _nl.clm_inparm.use_fates: + cannot_be_true = "do_transient_pfts cannot be combined with use_fates" + + if cannot_be_true: + default_val = False + + if not cannot_be_true: + _nl.dynamic_subgrid.do_transient_pfts = default_val + + if _nl.dynamic_subgrid.do_transient_pfts and cannot_be_true: + raise_error(cannot_be_true) + +def setup_logic_do_transient_crops(): + cannot_be_true = "" + default_val = True + if _nl.dynamic_subgrid.flanduse_timeseries is None: + cannot_be_true = "do_transient_crops can only be set to true when running a transient case (flanduse_timeseries non-blank)" + elif _nl.clm_inparm.use_fates: + cannot_be_true = "do_transient_crops has not been tested with ED, so for now these two options cannot be combined" + + if cannot_be_true: + default_val = False + + if not cannot_be_true: + _nl.dynamic_subgrid.do_transient_crops = default_val + + if _nl.dynamic_subgrid.do_transient_pfts and cannot_be_true: + raise_error(cannot_be_true) + + if ((_nl.dynamic_subgrid.do_transient_crops and not _nl.dynamic_subgrid.do_transient_pfts) or + (not _nl.dynamic_subgrid.do_transient_crops and _nl.dynamic_subgrid.do_transient_pfts)): + error("do_transient_crops and do_transient_pfts do NOT agree and need to") + +def setup_logic_do_harvest(): + cannot_be_true = "" + default_val = True + if _nl.dynamic_subgrid.flanduse_timeseries is None: + cannot_be_true = "do_harvest can only be set to true when running a transient case (flanduse_timeseries non-blank)" + elif _nl.clm_inparm.use_cndv: + cannot_be_true = "do_harvest cannot be combined with use_cndv" + elif _nl.clm_inparm.use_fates: + cannot_be_true = "do_harvest cannot be combined with use_fates" + + if cannot_be_true: + default_val = False + + if not cannot_be_true: + _nl.dynamic_subgrid.do_harvest = default_val + + if _nl.dynamic_subgrid.do_transient_pfts and cannot_be_true: + raise_error(cannot_be_true) + +def setup_logic_spinup(): + with _nl.clm_inparm as n: + if _in_opts["bgc_mode"] == "sp" and n.override_bgc_restart_mismatch_dump: + error("CN must be on if override_bgc_restart_mismatch_dump is set.") + if _in_opts["clm_accelerated_spinup"] == "on": + n.hist_nhtfrq = 8760 + n.hist_empty_htapes = True + n.hist_mfilt = 20 + if _nl.clm_inparm.use_fates: + n.hist_fincl1 = ["TOTSOMC", "TOTSOMN", "TLAI", "GPP", "NPP", "TWS"] + else: + if _nl.clm_inparm.use_cn: + if _nl.clm_inparm.use_cndv: + n.hist_fincl1 = ["TOTECOSYSC", "TOTECOSYSN", "TOTSOMC", "TOTSOMN", "TOTVEGC", "TOTVEGN", "TLAI", "GPP", "NPP", "TWS", "TSAI", "HTOP", "HBOT"] + else: + n.hist_fincl1 = ["TOTECOSYSC", "TOTECOSYSN", "TOTSOMC", "TOTSOMN", "TOTVEGC", "TOTVEGN", "TLAI", "GPP", "CPOOL", "NPP", "TWS"] + else: + n.hist_fincl1 = ["TLAI" "TWS"] + +def setup_logic_supplemental_nitrogen(): + with _nl.clm_inparm as n: + if not (_in_opts["bgc_mode"] == "sp" or _in_opts["bgc_mode"] == "fates") and _nl.clm_inparm.use_crop: + n.suplnitro = "NONE" if _nl.clm_inparm.use_cn else "" + + if not n.suplnitro is None: + if _in_opts["bgc_mode"] == "sp": + error("supplemental Nitrogen (suplnitro) is set, but neither CN nor CNDV is active!") + if _nl.clm_inparm.use_crop and n.suplnitro == "PROG_CROP_ONLY": + error("supplemental Nitrogen is set to run over prognostic crops, but prognostic crop is NOT active") + if n.suplnitro == "ALL" and _env["bgc_spinup"] == "on": + print("WARNING: There is no need to use a bgc_spinup mode when supplemental Nitrogen is on for all PFT's, as these modes spinup Nitrogen") + +def setup_logic_snowpack(): + _nl.aerosol.fresh_snw_rds_max = 204.526 + with _nl.clm_inparm as n: + n.nlevsno = 12 + n.h2osno_max = 10000.0 + n.int_snow_max = 2000 + n.n_melt_glcmec = 10.0 + + with _nl.clm_snowhydrology_inparm as n: + n.wind_dependent_snow_density = True + n.snow_overburden_compaction_method = "Vionnet2012" + n.lotmp_snowdensity_method = "Slater2017" + n.upplim_destruct_metamorph = 175.0 + n.reset_snow = False + n.reset_snow_glc = False + n.reset_snow_glc_ela = 1e9 + + if n.snow_overburden_compaction_method == "Vionnet2012": + if not n.overburden_compress_Tfactor is None: + error("'overburden_compress_tfactor is set, but does not apply when using snow_overburden_compaction_method=Vionnet2012'") + else: + n.overburden_compress_Tfactor = 0.08 + +def setup_logic_fates(): + if _nl.clm_inparm.use_fates: + with _nl.clm_inparm as n: + n.fates_paramfile = "lnd/clm2/paramdata/fates_params_api.8.0.0_12pft_c191216.nc" + n.use_fates_spitfire = False + n.use_fates_planthydro = False + n.use_fates_ed_st3 = False + n.use_fates_ed_prescribed_phys = False + n.use_fates_inventory_init = False + n.use_fates_logging = False + n.fates_parteh_mode = 1 + if not n.use_fates_inventory_init is None and n.use_fates_inventory_init: + if n.fates_inventory_ctrl_filename is None: + error("fates_inventory_ctrl_filename when use_fates_inventory_init is set") + #elif invalid_file(n.fates_inventory_ctrl_filename): + # error("fates_inventory_ctrl_filename does NOT point to a valid filename") + # + +def setup_logic_atm_forcing(): + with _nl.atm2lnd_inparm as n: + n.glcmec_downscale_longwave = True + n.repartition_rain_snow = True + n.lapse_rate = 0.006 + if n.glcmec_downscale_longwave: + n.lapse_rate_longwave = 0.032 + n.longwave_downscaling_limit = 0.5 + else: + if not n.lapse_rate_longwave is None or not n.longwave_downscaling_limit is None: + error("lapse_rate_longwave/longwave_downscaling_limit can only be set if glcmec_downscale_longwave is true") + if n.repartition_rain_snow: + n.precip_repartition_glc_all_snow_t = -2.0 + n.precip_repartition_glc_all_rain_t = 0.0 + n.precip_repartition_nonglc_all_snow_t = 0.0 + n.precip_repartition_nonglc_all_rain_t = 2.0 + else: + if (not n.precip_repartition_glc_all_snow_t is None or + not n.precip_repartition_glc_all_rain_t is None or + not n.precip_repartition_nonglc_all_snow_t is None or + not n.precip_repartition_nonglc_all_rain_t is None): + error("precip_repartition_glc_all_snow_t/precip_repartition_glc_all_ can only be set if precip_repartition_glc_all_snow_t is true") + +def setup_logic_lnd2atm(): + _nl.lnd2atm_inparm.melt_non_icesheet_ice_runoff = True + +def setup_logic_humanindex(): + _nl.clm_humanindex_inparm.calc_human_stress_indices = "FAST" + +def setup_logic_cnfire(): + with _nl.lifire_inparm as n: + if _nl.clm_inparm.use_cn: + if _nl.cnfire_inparm.fire_method == "li2014qianfrc": + n.rh_low = 30.0 + n.rh_hgh = 80.0 + n.bt_min = 0.3 + n.bt_max = 0.7 + n.cli_scale = 0.035 + n.boreal_peatfire_c = 4.2e-5 + n.non_boreal_peatfire_c = 0.001 + n.pot_hmn_ign_counts_alpha = 0.035 + n.cropfire_a1 = 0.3 + n.occur_hi_gdp_tree = 0.39 + n.lfuel = 75.0 + n.ufuel = 1050.0 + n.cmb_cmplt_fact = [0.5, 0.25] + elif _nl.cnfire_inparm.fire_method == "li2016crufrc": + if _in_opts["lnd_tuning_mode"] == "clm5_0_GSWP3v1" or _in_opts["lnd_tuning_mode"] == "clm5_0_CRUv7": + n.rh_low = 30.0 + n.pot_hmn_ign_counts_alpha = 0.010 + elif _in_opts["lnd_tuning_mode"] == "clm5_0_cam6.0": + n.rh_low = 20.0 + n.pot_hmn_ign_counts_alpha = 0.008 + n.rh_hgh = 80.0 + n.bt_min = 0.85 + n.bt_max = 0.98 + n.cli_scale = 0.033 + n.boreal_peatfire_c = 0.09e-4 + n.non_boreal_peatfire_c = 0.17e-3 + n.cropfire_a1 = 1.6e-4 + n.occur_hi_gdp_tree = 0.33 + n.lfuel = 105.0 + n.ufuel = 1050.0 + n.cmb_cmplt_fact = [0.5, 0.28] + else: + pass + +def setup_logic_cnprec(): + if _nl.clm_inparm.use_cn: + _nl.cnprecision_inparm.ncrit = 1e-9 + _nl.cnprecision_inparm.cnegcrit = -60.0 + _nl.cnprecision_inparm.nnegcrit = -6.0 + +def setup_logic_urban(): + _nl.clmu_inparm.building_temp_method = 1 + _nl.clmu_inparm.urban_hac = "ON_WASTEHEAT" + _nl.clmu_inparm.urban_traffic = False + +def setup_logic_crop(): + if _nl.clm_inparm.use_crop: + _nl.crop.baset_mapping = "varytropicsbylat" + _nl.crop.baset_latvary_slope = 0.4 + _nl.crop.baset_latvary_intercept = 12.0 + _nl.cnphenology.initial_seed_at_planting = 3.0 + else: + error("Can NOT be set without crop on") + +def setup_logic_methane(): + if _nl.clm_inparm.use_lch4: + _nl.ch4par_in.finundation_method = "TWS_inversion" + _env["finundation_res"] = "1.9x2.5" + _nl.ch4finundated.stream_fldfilename_ch4finundated = "lnd/clm2/paramdata/finundated_inversiondata_0.9x1.25_c170706.nc" + _nl.ch4par_in.use_aereoxid_prog = True + # TODO: Ch4 namelist checking + # Unknown nl params: + # lake_decomp_fact + # pftspecific_rootingprofile + # rootprof_exp + else: + error("ch4par_in namelist variables were set, but Methane model NOT defined in the configuration (use_lch4)") + +def setup_logic_c_isotope(): + with _nl.clm_inparm as n: + if _env["bgc_spinup"] != "sp" and _env["bgc_spinup"] != "fates": + if _env["bgc_spinup"] != "bgc": + if not n.use_c13 is None and n.use_c13: + print("WARNING: use_c13 is ONLY scientifically validated with the bgc=BGC configuration") + if not n.use_c14 is None and n.use_c14: + print("WARNING: use_c14 is ONLY scientifically validated with the bgc=BGC configuration") + if not n.use_c14 is None: + if n.use_c14: + if n.use_c14_bombspike: + atm_c14_filename = {"hist":"lnd/clm2/isotopes/atm_delta_C14_CMIP6_3x1_global_1850-2015_yearly_v2.0_c190528.nc", + "SSP1-1.9":"lnd/clm2/isotopes/atm_delta_C14_CMIP6_SSP119_3x1_global_1850-2100_yearly_c181209.nc", + "SSP1-2.6":"lnd/clm2/isotopes/atm_delta_C14_CMIP6_SSP126_3x1_global_1850-2100_yearly_c181209.nc", + "SSP2-4.5":"lnd/clm2/isotopes/atm_delta_C14_CMIP6_SSP245_3x1_global_1850-2100_yearly_c181209.nc", + "SSP3-7.0":"lnd/clm2/isotopes/atm_delta_C14_CMIP6_SSP3B_3x1_global_1850-2100_yearly_c181209.nc", + "SSP5-3.4":"lnd/clm2/isotopes/atm_delta_C14_CMIP6_SSP534os_3x1_global_1850-2100_yearly_c181209.nc", + "SSP5-8.5":"lnd/clm2/isotopes/atm_delta_C14_CMIP6_SSP5B_3x1_global_1850-2100_yearly_c181209.nc"} + n.atm_c14_filename = atm_c14_filename.get(_in_opts["ssp_rcp"], None) + else: + if not (n.atm_c14_filename is None and n.use_c14_bombspike is None): + error("use_c14 is FALSE and use_c14_bombspike or atm_c14_filename set") + else: + if not (n.atm_c14_filename is None and n.use_c14_bombspike is None): + error("use_c14 NOT set to .true., but use_c14_bompspike/atm_c14_filename defined.") + + if not n.use_c13 is None: + if n.use_c13: + if not n.use_c13_timeseries is None and n.use_c13_timeseries: + atm_c13_filename = {"hist":"lnd/clm2/isotopes/atm_delta_C13_CMIP6_1850-2015_yearly_v2.0_c190528.nc", + "SSP1-1.9":"lnd/clm2/isotopes/atm_delta_C13_CMIP6_SSP119_1850-2100_yearly_c181209.nc", + "SSP1-2.6":"lnd/clm2/isotopes/atm_delta_C13_CMIP6_SSP126_1850-2100_yearly_c181209.nc", + "SSP2-4.5":"lnd/clm2/isotopes/atm_delta_C13_CMIP6_SSP245_1850-2100_yearly_c181209.nc", + "SSP3-7.0":"lnd/clm2/isotopes/atm_delta_C13_CMIP6_SSP3B_1850-2100_yearly_c181209.nc", + "SSP5-3.4":"lnd/clm2/isotopes/atm_delta_C13_CMIP6_SSP534os_1850-2100_yearly_c181209.nc", + "SSP5-8.5":"lnd/clm2/isotopes/atm_delta_C13_CMIP6_SSP5B_1850-2100_yearly_c181209.nc"} + n.atm_c13_filename = atm_c13_filename.get(_in_opts["ssp_rcp"], None) + else: + if not (n.atm_c13_filename is None and n.use_c13_timeseries is None): + error("use_c13 is FALSE and use_c13_timeseries or atm_c13_filename set") + else: + if not (n.atm_c13_filename is None and n.use_c13_timeseries is None): + error("use_c13 NOT set to .true., but use_c13_bompspike/atm_c13_filename defined.") + else: + if (not n.use_c13 is None or + not n.use_c14 is None or + not n.use_c14_bombspike is None or + not n.atm_c14_filename is None or + not n.use_c13_timeseries is None or + not n.atm_c13_filename is None): + error("bgc=sp and C isotope namelist variables were set, both can't be used at the same time") + +def setup_logic_nitrogen_deposition(): + with _nl.ndepdyn_nml as n: + if _in_opts["bgc_mode"] == "cn" or _in_opts["bgc_mode"] == "bgc": + if _nl.clm_inparm.use_cn: + if _in_opts["res"] in ["1x1_brazil", "1x1_mexicocityMEX", "1x1_vancouverCAN", "1x1_urbanc_alpha", + "1x1_camdenNJ", "1x1_asphaltjungleNJ", "5x5_amazon"]: + n.ndepmapalgo = "nn" + else: + n.ndepmapalgo = "bilinear" + n.ndep_taxmode = "cycle" + n.ndep_varlist = "NDEP_month" + if _in_opts["sim_year_range"] == "1850-2100": + n.stream_year_first_ndep = 2015 + n.stream_year_last_ndep = 2101 + n.model_year_align_ndep = 2015 + elif _in_opts["sim_year_range"] == "2100-2300": + n.stream_year_first_ndep = 2101 + n.stream_year_last_ndep = 2101 + n.model_year_align_ndep = 2101 + elif _in_opts["sim_year"] in ["1850", "2000", "2010"]: + n.stream_year_first_ndep = int(_in_opts["sim_year"]) + n.stream_year_last_ndep = int(_in_opts["sim_year"]) + elif _in_opts["sim_year"] == "1000": + n.stream_year_first_ndep = 2000 + n.stream_year_last_ndep = 2000 + elif (_in_opts["sim_year"] == "constant" and + (_in_opts["sim_year_range"] == "1000-1002" or _in_opts["sim_year_range"] == "1000-1004")): + n.stream_year_first_ndep = 2000 + n.stream_year_last_ndep = 2000 + stream_fldfilename_ndep = {"hist":"lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc", + "SSP5-8.5":"lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP5-8.5-WACCM_1849-2101_monthly_c191007.nc", + "SSP1-2.6":"lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP1-2.6-WACCM_1849-2101_monthly_c191007.nc", + "SSP2-4.5":"lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP2-4.5-WACCM_1849-2101_monthly_c191007.nc", + "SSP3-7.0":"lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP3-7.0-WACCM_1849-2101_monthly_c191007.nc"} + n.stream_fldfilename_ndep = stream_fldfilename_ndep.get(_in_opts["ssp_rcp"], None) + if n.stream_fldfilename_ndep is None: + print("""WARNING: Did NOT find the Nitrogen-deposition forcing file (stream_fldfilename_ndep) for this ssp_rcp. + "One way to get around this is to point to a file for another existing ssp_rcp in your user_nl_clm file. + "If you are running with CAM and WACCM chemistry Nitrogen deposition will come through the coupler. + "This file won't be used, so it doesn't matter what it points to -- but it's required to point to something.""") + else: + if (not n.stream_year_first_ndep is None or + not n.stream_year_last_ndep is None or + not n.model_year_align_ndep is None or + not n.ndep_taxmode is None or + not n.ndep_varlist is None or + not n.stream_fldfilename_ndep is None): + error("""When bgc is NOT CN or CNDV none of: stream_year_first_ndep, + stream_year_last_ndep, model_year_align_ndep, ndep_taxmod, + ndep_varlist, nor stream_fldfilename_ndep + can be set!""") + +def setup_logic_soilm_streams(): + _nl.clm_inparm.use_soil_moisture_streams = False + with _nl.soil_moisture_streams as n: + if _nl.clm_inparm.use_soil_moisture_streams: + n.soilm_tintalgo = "linear" + n.soilm_offset = 0 + n.stream_year_first_soilm = 1997 + n.stream_year_last_soilm = 1997 + if n.stream_year_first_soilm != n.stream_year_last_soilm: + n.model_year_align_soilm = 1997 + if _in_opts["res"] == "0.9x1.25": + n.stream_fldfilename_soilm = "lnd/clm2/prescribed_data/LFMIP-pdLC-SST.H2OSOI.0.9x1.25.20levsoi.natveg.1980-2014.MONS_climo.c190716.nc" + if _in_opts["use_case"] == "transient" and n.soilm_tintalgo == "linear": + print("""WARNING: For a transient case, soil moisture streams, should NOT use soilm_tintalgo='linear' + since vegetated areas could go from missing to not missing or vice versa""") + else: + if (not n.stream_year_first_soilm is None or + not n.model_year_align_soilm is None or + not n.stream_fldfilename_soilm is None or + not n.soilm_tintalgo is None or + not n.soilm_offset is None or + not n.stream_year_last_soilm is None): + error("""One of the soilm streams namelist items (stream_year_first_soilm, + model_year_align_soilm, stream_fldfilename_soilm, stream_fldfilename_soilm) + soilm_tintalgo soilm_offset is defined, but use_soil_moisture_streams option NOT set to true""") + +def setup_logic_cnmresp(): + if _in_opts["bgc_mode"] != "sp": + if _nl.clm_inparm.use_fun: + _nl.cnmresp_inparm.br_root = 0.83e-6 + else: + if not _nl.cnmresp_inparm.br_root is None: + error("br_root can NOT be set when phys==clm4_0 or bgc_mode==sp!") + +def setup_logic_nitrif_params(): + if not _nl.clm_inparm.use_nitrif_denitrif: + with _nl.nitrif_inparm as n: + if (not n.k_nitr_max is None or + not n.denitrif_respiration_coefficient is None or + not n.denitrif_respiration_exponent is None or + not n.denitrif_nitrateconc_coefficient is None or + not n.denitrif_nitrateconc_exponent is None): + error("nitrif vars are only used when use_nitrif_denitrif is turned on") + +def setup_logic_photosyns(): + with _nl.photosyns_inparm as n: + n.rootstem_acc = False + n.light_inhibit = True + n.leafresp_method = 2 if _nl.clm_inparm.use_cn else 0 + n.modifyphoto_and_lmr_forcrop = True + n.stomatalcond_method = "Medlyn2011" if _nl.clm_inparm.use_hydrstress else "Ball-Berry1987" + if _nl.clm_inparm.use_cn: + if n.leafresp_method == 0: + error("leafresp_method can NOT be set to scaled to vcmax (0) when CN is on!") + else: + if n.leafresp_method != 0: + error("leafresp_method can NOT be set to anything besides scaled to vcmax (0) when bgc_mode==sp!") + +def setup_logic_popd_streams(): + with _nl.popd_streams as n: + if _env["cnfireson"]: + if _nl.clm_inparm.use_cn: + if _in_opts["res"] in ["1x1_brazil", "1x1_mexicocityMEX", "1x1_vancouverCAN", "1x1_urbanc_alpha", + "1x1_camdenNJ", "1x1_asphaltjungleNJ", "5x5_amazon"]: + n.popdensmapalgo = "nn" + else: + n.popdensmapalgo = "bilinear" + if _in_opts["sim_year_range"] == "1850-2100": + n.stream_year_first_popdens = 2015 + n.stream_year_last_popdens = 2101 + n.model_year_align_popdens = 2015 + elif _in_opts["sim_year_range"] == "2100-2300": + n.stream_year_first_popdens = 2100 + n.stream_year_last_popdens = 2100 + n.model_year_align_popdens = 2100 + elif _in_opts["sim_year"] in ["1850", "2000", "2010"]: + n.stream_year_first_popdens = int(_in_opts["sim_year"]) + n.stream_year_last_popdens = int(_in_opts["sim_year"]) + elif _in_opts["sim_year"] == "1000": + n.stream_year_first_popdens = 2000 + n.stream_year_last_popdens = 2000 + elif (_in_opts["sim_year"] == "constant" and + (_in_opts["sim_year_range"] == "1000-1002" or _in_opts["sim_year_range"] == "1000-1004")): + n.stream_year_first_popdens = 2000 + n.stream_year_last_popdens = 2000 + stream_fldfilename_popdens = {"SSP1-1.9":"lnd/clm2/firedata/clmforc.Li_2018_SSP1_CMIP6_hdm_0.5x0.5_AVHRR_simyr1850-2100_c181205.nc", + "SSP1-2.6":"lnd/clm2/firedata/clmforc.Li_2018_SSP1_CMIP6_hdm_0.5x0.5_AVHRR_simyr1850-2100_c181205.nc", + "SSP2-4.5":"lnd/clm2/firedata/clmforc.Li_2018_SSP2_CMIP6_hdm_0.5x0.5_AVHRR_simyr1850-2100_c181205.nc", + "SSP3-7.0":"lnd/clm2/firedata/clmforc.Li_2018_SSP3_CMIP6_hdm_0.5x0.5_AVHRR_simyr1850-2100_c181205.nc", + "SSP4-6.0":"lnd/clm2/firedata/clmforc.Li_2018_SSP4_CMIP6_hdm_0.5x0.5_AVHRR_simyr1850-2100_c181205.nc", + "SSP4-3.4":"lnd/clm2/firedata/clmforc.Li_2018_SSP4_CMIP6_hdm_0.5x0.5_AVHRR_simyr1850-2100_c181205.nc", + "SSP5-8.5":"lnd/clm2/firedata/clmforc.Li_2018_SSP5_CMIP6_hdm_0.5x0.5_AVHRR_simyr1850-2100_c181205.nc", + "SSP5-3.4":"lnd/clm2/firedata/clmforc.Li_2018_SSP5_CMIP6_hdm_0.5x0.5_AVHRR_simyr1850-2100_c181205.nc"} + n.stream_fldfilename_popdens = stream_fldfilename_popdens.get(_in_opts["ssp_rcp"], "lnd/clm2/firedata/clmforc.Li_2017_HYDEv3.2_CMIP6_hdm_0.5x0.5_AVHRR_simyr1850-2016_c180202.nc") + else: + if (not n.stream_fldfilename_popdens is None or + not n.stream_year_last_popdens is None or + not n.model_year_align_popdens is None or + not n.popdens_tintalgo is None or + not n.stream_fldfilename_popdens is None): + error("""When bgc is SP (NOT CN or BGC) or fire_method==nofire none of: stream_year_first_popdens, + stream_year_last_popdens, model_year_align_popdens, popdens_tintalgo nor + stream_fldfilename_popdens can be set""") + +def setup_logic_urbantv_streams(): + with _nl.urbantv_streams as n: + n.urbantvmapalgo = "nn" + if _in_opts["sim_year_range"] == "1850-2100": + n.stream_year_first_urbantv = 2015 + n.stream_year_last_urbantv = 2106 + n.model_year_align_urbantv = 2015 + elif _in_opts["sim_year_range"] == "2100-2300": + n.stream_year_first_urbantv = 2100 + n.stream_year_last_urbantv = 2106 + n.model_year_align_urbantv = 2100 + elif _in_opts["sim_year"] in ["1850", "2000"]: + n.stream_year_first_urbantv = int(_in_opts["sim_year"]) + n.stream_year_last_urbantv = int(_in_opts["sim_year"]) + elif _in_opts["sim_year"] == "1000": + n.stream_year_first_urbantv = 2000 + n.stream_year_last_urbantv = 2000 + elif (_in_opts["sim_year"] == "constant" and + (_in_opts["sim_year_range"] == "1000-1002" or _in_opts["sim_year_range"] == "1000-1004")): + n.stream_year_first_urbantv = 2000 + n.stream_year_last_urbantv = 2000 + n.stream_fldfilename_urbantv = "lnd/clm2/urbandata/CLM50_tbuildmax_Oleson_2016_0.9x1.25_simyr1849-2106_c160923.nc" + +def setup_logic_lightning_streams(): + with _nl.light_streams as n: + if _env["cnfireson"]: + if _nl.clm_inparm.use_cn: + if _in_opts["res"] in ["1x1_brazil", "1x1_mexicocityMEX", "1x1_vancouverCAN", "1x1_urbanc_alpha", + "1x1_camdenNJ", "1x1_asphaltjungleNJ", "5x5_amazon"]: + n.lightngmapalgo = "nn" + else: + n.lightngmapalgo = "bilinear" + n.stream_year_first_lightng = 1 + n.stream_year_last_lightng = 1 + if _in_opts["light_res"] == "94x192": + n.stream_fldfilename_lightng = "atm/datm7/NASA_LIS/clmforc.Li_2012_climo1995-2011.T62.lnfm_Total_c140423.nc" + elif _in_opts["light_res"] == "360x720": + n.stream_fldfilename_lightng = "atm/datm7/NASA_LIS/clmforc.Li_2016_climo1995-2013.360x720.lnfm_Total_c160825.nc" + else: + if (not n.stream_year_first_lightng is None or + not n.stream_year_last_lightng is None or + not n.model_year_align_lightng is None or + not n.lightng_tintalgo is None or + not n.stream_fldfilename_lightng is None): + error("""When bgc is SP (NOT CN or BGC) or fire_method==nofire none of: stream_year_first_lightng, + stream_year_last_lightng, model_year_align_lightng, lightng_tintalgo nor + stream_fldfilename_lightng can be set!""") + +def setup_logic_dry_deposition(): + with _nl_drv_flds.drydep_inparm as n: + if _in_opts["drydep"]: + n.drydep_list = ["O3", "NO2", "HNO3", "NO", "HO2NO2", "CH3OOH", "CH2O", "CO", "H2O2", "CH3COOOH", + "PAN", "MPAN", "C2H5OOH", "ONIT", "POOH", "C3H7OOH", "ROOH", "CH3COCHO", + "CH3COCH3", "Pb", "ONITR", "MACROOH", "XOOH", "ISOPOOH", "CH3OH", "C2H5OH", + "CH3CHO", "GLYALD", "HYAC", "HYDRALD", "ALKOOH", "MEKOOH", "TOLOOH", "TERPOOH", + "CH3COOH", "CB1", "CB2", "OC1", "OC2", "SOA", "SO2", "SO4", "NH3", "NH4NO3"] + n.drydep_method = "xactive_lnd" + else: + if (not n.drydep_list is None or not n.drydep_method is None): + error("drydep_list or drydep_method defined, but drydep option NOT set") + +def setup_logic_fire_emis(): + with _nl_drv_flds.fire_emis_nl as n: + if _in_opts["fire_emis"]: + n.fire_emis_factors_file = "lnd/clm2/firedata/fire_emis_factors_c140116.nc" + n.fire_emis_specifier = ["bc_a1 = BC", "pom_a1 = 1.4*OC", "SO2 = SO2"] + else: + if (not n.fire_emis_elevated is None or + not n.fire_emis_factors_file is None or + not n.fire_emis_specifier is None): + error("fire_emission setting defined: fire_emis_elevated, fire_emis_factors_file, or fire_emis_specifier, but fire_emis option NOT set") + +def setup_logic_megan(): + if _in_opts["megan"] == "default": + use_megan = not _in_opts["clm_accelerated_spinup"] + else: + use_megan = bool(_in_opts["megan"]) + + with _nl_drv_flds.megan_emis_nl as n: + if use_megan: + if _nl.clm_inparm.use_fates: + error("MEGAN can NOT be on when ED is also on. Use the '-no-megan' option when '-bgc fates' is activated") + n.megan_specifier = ["ISOP = isoprene", "C10H16 = pinene_a + carene_3 + thujene_a", "CH3OH = methanol", "C2H5OH = ethanol", "CH2O = formaldehyde", "CH3CHO = acetaldehyde", "CH3COOH = acetic_acid", "CH3COCH3 = acetone"] + if _in_nl_drv_flds["megan_factors_file"] is not None: + n.megan_factors_file = _in_nl_drv_flds["megan_factors_file"] + else: + n.megan_factors_file = "atm/cam/chem/trop_mozart/emis/megan21_emis_factors_78pft_c20161108.nc" + else: + if (not n.megan_factors_file is None or n.megan_specifier is None): + error("megan_specifier or megan_factors_file defined, but megan option NOT set") + +def setup_logic_lai_streams(): + _nl.clm_inparm.use_lai_streams = False + with _nl.lai_streams as n: + if _nl.clm_inparm.use_crop and _nl.clm_inparm.use_lai_streams: + error("turning use_lai_streams on is incompatable with use_crop set to true.") + if _in_opts["bgc_mode"] == "sp": + if _nl.clm_inparm.use_lai_streams: + if _in_opts["res"] in ["1x1_brazil", "1x1_mexicocityMEX", "1x1_vancouverCAN", "1x1_urbanc_alpha", + "1x1_camdenNJ", "1x1_asphaltjungleNJ", "5x5_amazon"]: + n.lai_mapalgo = "nn" + else: + n.lai_mapalgo = "bilinear" + n.stream_year_first_lai = 2001 + n.stream_year_last_lai = 2013 + n.model_year_align_lai = 2001 + n.stream_fldfilename_lai = "lnd/clm2/lai_streams/MODISPFTLAI_0.5x0.5_c140711.nc" + else: + if (not n.stream_year_first_lai is None or + not n.stream_year_last_lai is None or + not n.model_year_align_lai is None or + not n.lai_tintalgo is None or + not n.stream_fldfilename_lai is None): + error("""When bgc is NOT SP none of the following can be set: stream_year_first_lai,\n" . + "stream_year_last_lai, model_year_align_lai, lai_tintalgo nor\n" . + "stream_fldfilename_lai (eg. don't use this option with BGC,CN,CNDV nor BGDCV""") + +def setup_logic_bgc_shared(): + if _in_opts["bgc_mode"] != "sp": + _nl.bgc_shared.constrain_stress_deciduous_onset = True + # FIXME(bja, 201606) the logic around fates / bgc_mode / + # use_century_decomp is confusing and messed up. This is a hack + # workaround. + if _nl.clm_inparm.use_century_decomp: + _nl.bgc_shared.decomp_depth_efolding = 10.0 + +def setup_logic_soilwater_movement(): + with _nl.soilwater_movement_inparm as n: + n.soilwater_movement_method = 1 + n.upper_boundary_condition = 1 + if n.soilwater_movement_method == 1: + if not _nl.clm_inparm.use_bedrock and _in_opts["vichydro"] == 1: + n.lower_boundary_condition = 3 + else: + n.lower_boundary_condition = 2 + elif n.soilwater_movement_method == 0: + n.lower_boundary_condition = 4 + n.dtmin = 60.0 + n.verySmall = 1e-8 + n.xTolerUpper = 1e-1 + n.xTolerLower = 1e-2 + n.expensive = 42 + n.inexpensive = 1 + n.flux_calculation = 1 + +def setup_logic_rooting_profile(): + _nl.rooting_profile_inparm.rooting_profile_method_water = 1 + _nl.rooting_profile_inparm.rooting_profile_method_carbon = 1 + +def setup_logic_friction_vel(): + _nl.friction_velocity.zetamaxstable = 0.5 + +def setup_logic_century_soilbgcdecompcascade(): + with _nl.clm_inparm as n: + if n.use_century_decomp: + if (n.use_cn and not n.use_fates) or (not n.use_cn and n.use_fates): + _nl.century_soilbgcdecompcascade.initial_Cstocks = [200.0, 200.0, 200.0] + _nl.century_soilbgcdecompcascade.initial_Cstocks_depth = [1.50] + +def setup_logic_cngeneral(): + with _nl.clm_inparm as n: + if n.use_cn: + if n.use_crop: + _nl.cn_general.dribble_crophrv_xsmrpool_2atm = True if n.co2_type == "prognostic" else False + else: + if not _nl.cn_general.dribble_crophrv_xsmrpool_2atm is None: + error("When CROP is NOT on dribble_crophrv_xsmrpool_2atm can NOT be set") + else: + if (not _nl.cn_general.reseed_dead_plants is None or + not _nl.cn_general.dribble_crophrv_xsmrpool_2atm is None): + error("""When CN is not on none of the following can be set: , + dribble_crophrv_xsmrpool_2atm nor reseed_dead_plantsr + (eg. don't use these options with SP mode)""") + +def setup_logic_cnvegcarbonstate(): + if _nl.clm_inparm.use_cn: + if _nl.clm_nitrogen.MM_Nuptake_opt is None: + _nl.clm_nitrogen.MM_Nuptake_opt = False + _nl.cnvegcarbonstate.initial_vegC = 100.0 if _nl.clm_nitrogen.MM_Nuptake_opt else 1.0 + +def setup_logic_soil_resis(): + _nl.soil_resis_inparm.soil_resis_method = 1 + +def setup_logic_canopyfluxes(): + _nl.canopyfluxes_inparm.use_undercanopy_stability = False + +def setup_logic_canopyhydrology(): + _nl.clm_canopyhydrology_inparm.interception_fraction = 1.0 + _nl.clm_canopyhydrology_inparm.maximum_leaf_wetted_fraction = 0.05 + _nl.clm_canopyhydrology_inparm.use_clm5_fpi = True + +def setup_logic_canopy(): + _nl.clm_canopy_inparm.leaf_mr_vcm = 0.015 + +def setup_logic_hydrology_params(): + lbc = _nl.soilwater_movement_inparm.lower_boundary_condition + with _nl.soilhydrology_inparm as n: + if lbc == 1 or lbc == 2: + n.baseflow_scalar = 0.01 if lbc == 1 else 0.001 + if not n.baseflow_scalar is None and not (lbc == 1 or lbc == 2): + error("baseflow_scalar is only used for lower_boundary_condition of flux or zero-flux") + +def setup_logic_irrigation_parameters(): + with _nl.irrigation_inparm as n: + n.irrig_min_lai = 0.0 + n.irrig_start_time = 21600 + n.irrig_length = 14400 + n.irrig_target_smp = -3400.0 + n.irrig_depth = 0.6 + n.irrig_threshold_fraction = 1.0 + n.limit_irrigation_if_rof_enabled = False + if n.limit_irrigation_if_rof_enabled: + n.irrig_river_volume_threshold = 0.1 + elif not n.irrig_river_volume_threshold is None: + error("irrig_river_volume_threshold can only be set if limit_irrigation_if_rof_enabled is true") + +def setup_logic_hydrology_switches(): + origflag = _nl.clm_soilhydrology_inparm.origflag + h2osfcflag = _nl.clm_soilhydrology_inparm.h2osfcflag + if origflag == 1 and _nl.clm_inparm.subgridflag == 1: + error("if origflag is ON, subgridflag can NOT also be on!") + if h2osfcflag == 1 and _nl.clm_inparm.subgridflag != 1: + error("if h2osfcflag is ON, subgridflag can NOT be off!") + if (not origflag is None or + not h2osfcflag is None or + not _nl.clm_canopyhydrology_inparm.oldfflag is None): + error("ERROR:: origflag/h2osfcflag/oldfflag is deprecated and can only be used with CLM4.5") + + lower = _nl.soilwater_movement_inparm.lower_boundary_condition + use_vic = _nl.clm_inparm.use_vichydro + use_bed = _nl.clm_inparm.use_bedrock + soilmtd = _nl.soilwater_movement_inparm.soilwater_movement_method + + if(not soilmtd is None and not lower is None) and soilmtd == 0 and lower != 4: + error("If soil water movement method is zeng-decker -- lower_boundary_condition can only be aquifer") + + if(not soilmtd is None and not lower is None) and soilmtd == 1 and lower == 4: + error("If soil water movement method is adaptive -- lower_boundary_condition can NOT be aquifer") + + if(not use_bed is None and not lower is None) and use_bed and lower != 2: + error("If use_bedrock is on -- lower_boundary_condition can only be flux") + + if(not use_vic is None and not lower is None) and use_vic and lower != 3 and lower != 4: + error("If use_vichydro is on -- lower_boundary_condition can only be table or aquifer") + + if(not origflag is None and not use_vic is None) and use_vic and origflag == 1: + error("If use_vichydro is on -- origflag can NOT be equal to 1") + + if(not h2osfcflag is None and not lower is None) and h2osfcflag == 0 and lower != 4: + error("If h2osfcflag is 0 lower_boundary_condition can only be aquifer") + +def setup_logic_initinterp(): + if _nl.clm_inparm.use_init_interp: + _nl.clm_initinterp_inparm.init_interp_method = "general" + elif not _nl.clm_initinterp_inparm.init_interp_method is None: + error("init_interp_method can only be set if use_init_interp is true") + +def setup_cmdl_bgc(): + with _nl.clm_inparm as n: + if _in_opts["bgc_mode"] == "cn": + n.use_cn = True + n.use_fates = False + n.use_vertsoilc = False + n.use_century_decomp = False + n.use_lch4 = False + n.use_nitrif_denitrif = False + n.use_fun = False + elif _in_opts["bgc_mode"] == "bgc": + n.use_cn = True + n.use_fates = False + n.use_vertsoilc = True + n.use_century_decomp = True + n.use_lch4 = True + n.use_nitrif_denitrif = True + n.use_fun = True + elif _in_opts["bgc_mode"] == "fates": + n.use_cn = False + n.use_fates = True + n.use_vertsoilc = True + n.use_century_decomp = True + n.use_lch4 = False + n.use_nitrif_denitrif = False + n.use_fun = False + elif _in_opts["bgc_mode"] == "sp": + n.use_cn = False + n.use_fates = False + n.use_vertsoilc = False + n.use_century_decomp = False + n.use_lch4 = False + n.use_nitrif_denitrif = False + n.use_fun = False + else: + error("Unsupported bgc_mode = " + _in_opts["bgc_mode"]) + +def setup_cmdl_fire_light_res(): + if _in_opts["light_res"] == "default": + if not _nl.clm_inparm.use_cn or _nl.cnfire_inparm.fire_method == "nofire": + _in_opts["light_res"] = "none" + else: + _in_opts["light_res"] = "94x192" + else: + if _nl.cnfire_inparm.fire_method == "nofire": + error("light_res used with fire_method='nofire'. light_res can ONLY be used without the nofire option") + if not _nl.light_streams.stream_fldfilename_lightng is None: + error("light_res used while also explicitly setting stream_fldfilename_lightng filename which is a contradiction. Use one or the other not both.") + if not _nl.clm_inparm.use_cn: + error("light_res used CN is NOT on. light_res can only be used when CN is on (with bgc: cn or bgc)") + if not _nl.clm_inparm.use_cn and _in_opts["light_res"] is None: + error("light_res is set to none, but CN is on (with bgc: cn or bgc) which is a contradiction") + if _nl.clm_inparm.use_cn: + _nl.cnfire_inparm.fire_method = "li2016crufrc" + _env["cnfireson"] = True + elif _nl.cnfire_inparm.fire_method == "nofire": + _env["cnfireson"] = False + else: + _env["cnfireson"] = False + +def setup_cmdl_spinup(): + if _nl.clm_inparm.use_cn: + if _in_opts["clm_accelerated_spinup"] == "on": + _nl.clm_inparm.spinup_state = 2 + else: + _nl.clm_inparm.spinup_state = 0 + if _nl.clm_inparm.spinup_state != 0: + _env["bgc_spinup"] = "on" + if _in_opts["bgc_mode"] == "sp": + error("spinup_state is accelerated (=1 or 2) which is for a BGC mode of CN or BGC, but the BGC mode is Satellite Phenology, change one or the other") + if _in_opts["clm_accelerated_spinup"] == "off": + error("spinup_state is accelerated, but clm_accelerated_spinup is off, change one or the other") + else: + _env["bgc_spinup"] = "off" + + if _env["bgc_spinup"] == "on" and not _nl.clm_inparm.use_cn and not _nl.clm_inparm.use_fates: + error("clm_accelerated_spinup can not be on if neither CN nor ED is turned on") + if _nl.clm_inparm.spinup_state == 0 and _env["bgc_spinup"] == "on": + error("Namelist spinup_state contradicts the command line option bgc_spinup") + if _nl.clm_inparm.spinup_state == 1 and _env["bgc_spinup"] == "off": + error("Namelist spinup_state contradicts the command line option bgc_spinup") + +def setup_cmdl_crop(): + if _in_opts["crop"] == 1 and _in_opts["bgc_mode"] == "sp": + error("Cannot turn crop mode on mode bgc=sp") + _nl.clm_inparm.use_crop = (_in_opts["crop"] == 1) + +def setup_cmdl_dynamic_vegetation(): + if _in_opts["dynamic_vegetation"] == 1 and _in_opts["bgc_mode"] == "sp": + if _in_opts["bgc_mode"] == "sp": + error("Cannot turn dynamic_vegetation mode on with bgc=sp") + else: + _nl.clm_inparm.use_cndv = True + +def setup_cmdl_fates_mode(): + with _nl.clm_inparm as n: + if n.use_crop and _in_opts["bgc_mode"] == "fates": + error("Cannot turn fates mode on with crop") + elif n.use_fates: + n.use_vertsoilc = True + n.use_century_decomp = True + n.use_lch4 = False + else: + if (not n.use_fates_spitfire is None or not n.use_fates_planthydro is None or + not n.use_fates_ed_st3 is None or not n.use_fates_ed_prescribed_phys is None or + not n.use_fates_inventory_init is None or not n.fates_inventory_ctrl_filename is None or + not n.use_fates_logging is None or not n.fates_parteh_mode is None): + error("is being set, but can ONLY be set when -bgc fates option is used.") + +def setup_cmdl_run_type(): + first_yr = _in_opts["start_ymd"] / 10000 + if _in_opts["clm_start_type"] == "default": + if first_yr == 1850 or first_yr == 2000: + _in_opts["clm_start_type"] = "startup" + else: + _in_opts["clm_start_type"] = "arb_ic" + +if __name__ == "__main__": + """ + For testing purposes. To run gen_lnd_in.py, + directly, execute it via Python script mode: + + $ cd + $ python3 -m clm5nl.generators.gen_lnd_in + """ + + opts, nl, drv_flds = {}, {}, {} + opts["bgc_mode"] = "bgc" + opts["clm_accelerated_spinup"] = "off" + opts["clm_start_type"] = "arb_ic" + opts["co2_ppmv"] = 367.0 + opts["co2_type"] = "constant" + opts["crop"] = 1 + opts["drydep"] = False + opts["dtime"] = None + opts["dynamic_vegetation"] = 0 + opts["fire_emis"] = False + opts["GLC_TWO_WAY_COUPLING"] = False + opts["glc_nec"] = 10 + opts["ignore_ic_date"] = False + opts["ignore_ic_year"] = False + opts["l_ncpl"] = 48 + opts["light_res"] = "default" + opts["lnd_frac"] = "/p/scratch/nrw_test_case/domain.lnd.300x300_NRW_300x300_NRW.190619.nc" + opts["lnd_tuning_mode"] = "clm5_0_CRUv7" + opts["mask"] = None + opts["megan"] = True + opts["nrevsn"] = None + opts["override_nsrest"] = None + opts["res"] = "UNSET" + opts["sim_year"] = "2000" + opts["sim_year_range"] = "constant" + opts["ssp_rcp"] = "hist" + opts["start_ymd"] = 20170101 + opts["use_case"] = None + opts["use_dynroot"] = False + opts["use_init_interp"] = True + opts["vichydro"] = 0 + nl["finidat"] = "/p/scratch/nrw_test_case/FSpinup_300x300_NRW.clm2.r.2222-01-01-00000.nc" + nl["fsnowaging"] = "/p/scratch/nrw_test_case/snicar_drdt_bst_fit_60_c070416.nc" + nl["fsnowoptics"] = "/p/scratch/nrw_test_case/snicar_optics_5bnd_c090915.nc" + nl["fsurdat"] = "/p/scratch/nrw_test_case/surfdata_300x300_NRW_hist_78pfts_CMIP6_simyr2000_c190619.nc" + nl["paramfile"] = "/p/scratch/nrw_test_case/clm5_params.c171117.nc" + drv_flds["megan_factors_file"] = "/p/scratch/nrw_test_case/megan21_emis_factors_78pft_c20161108.nc" + build_lnd_in(opts, nl, drv_flds, "lnd_in_test") + print("Successfully generated lnd_in_test") + diff --git a/namelist_generator/clm5nl/structures/__init__.py b/namelist_generator/clm5nl/structures/__init__.py new file mode 100644 index 0000000000..17ada489e7 --- /dev/null +++ b/namelist_generator/clm5nl/structures/__init__.py @@ -0,0 +1,7 @@ +from .nl_lnd_in import lnd_in +from .nl_drv_in import drv_in +from .nl_datm_in import datm_in +from .nl_drv_flds_in import drv_flds_in +from .namelist import Namelist + +__all__ = ['lnd_in', 'drv_in', 'datm_in', 'drv_flds_in', 'Namelist'] \ No newline at end of file diff --git a/namelist_generator/clm5nl/structures/namelist.py b/namelist_generator/clm5nl/structures/namelist.py new file mode 100644 index 0000000000..b1f629a291 --- /dev/null +++ b/namelist_generator/clm5nl/structures/namelist.py @@ -0,0 +1,106 @@ +from collections import OrderedDict +from .utils import nl_to_str + +class Namelist(object): + def __init__(self, nl_obj: dict = None): + self._name = type(self).__name__ + if nl_obj is None: + self._nl = OrderedDict() + else: + self._nl = nl_obj + + def __iter__(self): + return self._nl.__iter__() + + def __len__(self): + acc = 0 + for v in self._nl.values(): + acc += len(v) + return acc + + def keys(self): + return self._nl.keys() + + def __str__(self): + return nl_to_str(self._nl) + + def write(self, nml_path): + with open(nml_path, "w") as f: + f.write(nl_to_str(self._nl)) + +class NamelistGroupMixin(object): + def __init__(self): + self._group_name = type(self).__name__ + self._parent: Namelist = None + + def _get_param(self, key): + if self._group_name in self._parent._nl: + return self._parent._nl[self._group_name].get(key, None) + else: + return None + + def _set_param(self, key, value): + if not self._group_name in self._parent._nl: self._parent._nl[self._group_name] = OrderedDict() + self._parent._nl[self._group_name][key] = value + + def _del_param(self, key): + if self._group_name in self._parent._nl: + del self._parent._nl[self._group_name][key] + + def __enter__(self): + return self + + def __exit__(self, type, value, tb): + pass + + def __iter__(self): + if self._group_name in self._parent._nl: + return self._parent._nl[self._group_name].__iter__() + else: + return {}.__iter__() + + def __contains__(self, item): + if self._group_name in self._parent._nl: + return (item in self._parent._nl[self._group_name]) + else: + return False + + def __len__(self): + if self._group_name in self._parent._nl: + return len(self._parent._nl[self._group_name]) + else: + return 0 + + def __str__(self): + return nl_to_str(self._parent._nl, self._group_name) + + def items(self): + if self._group_name in self._parent._nl: + return self._parent._nl[self._group_name].items() + else: + return {}.items() + +class namelist_group(): + def __init__(self, nl_grp): + self._group_type = type(nl_grp.__name__, (nl_grp, NamelistGroupMixin), {}) + self._group = None + #self._nl_grp = ng() + + def __get__(self, nl_obj, objtype): + if self._group is None: self._group = self._group_type() + self._group._parent = nl_obj + return self._group + +class namelist_item(object): + def __init__(self, func): + self._param_name = func.__name__.lower() + self.__doc__ = func.__doc__ + + def __get__(self, nl_grp, objtype): + return nl_grp._get_param(self._param_name) + + def __set__(self, nl_grp, value): + nl_grp._set_param(self._param_name, value) + + def __delete__(self, nl_grp): + nl_grp._del_param(self._param_name) \ No newline at end of file diff --git a/namelist_generator/clm5nl/structures/nl_datm_in.py b/namelist_generator/clm5nl/structures/nl_datm_in.py new file mode 100644 index 0000000000..f47f95dda1 --- /dev/null +++ b/namelist_generator/clm5nl/structures/nl_datm_in.py @@ -0,0 +1,325 @@ +""" +Datm namelist and stream files +""" +from typing import List +from .namelist import Namelist, namelist_group , namelist_item + +class datm_in(Namelist): + + @namelist_group + class datm_nml(): + + @namelist_item + def anomaly_forcing(self) -> str: + """ + If set, include anomaly forcing streams in namelist. + """ + pass + + @namelist_item + def bias_correct(self) -> str: + """ + If set, include bias correction streams in namelist. + """ + pass + + @namelist_item + def decomp(self) -> str: + """ + Set the decomposition option for the data model. valid options are + placing the global array on the root task or a simple stride-one + load balanced one-dimensional decomposition. other decompositions + may be added in the future. valid values are ['root','1d']. + 1d = Vector decomposition, root = run only on the master task + """ + pass + + @namelist_item + def factorfn(self) -> str: + """ + filename containing correction factors for use only with CORE2 modes (CORE2_IAF and CORE2_NYF). + """ + pass + + + @namelist_item + def force_prognostic_true(self) -> bool: + """ + If true, prognostic is forced to true. (default=false) + """ + pass + + @namelist_item + def iradsw(self) -> int: + """ + Frequency to update radiation in number of steps (or hours if negative) + irdasw is the radiation setting used to compute the next shortwave + Julian date. values greater than 1 set the next radiation to the + present time plus 2 timesteps every iradsw. values less than 0 turn + set the next radiation to the present time plus two timesteps every + -iradsw hours. if iradsw is zero, the next radiation time is the + present time plus 1 timestep. (default=0.) + """ + pass + + @namelist_item + def presaero(self) -> bool: + """ + If true, prescribed aerosols are sent from datm (must be true for running with CLM). + """ + pass + + @namelist_item + def restfilm(self) -> str: + """ + Model restart filename for the data atmosphere model data. This is + optional. If both restfils and restfilm are undefined, the restart + filename will be read from the DATM restart pointer file (or files for multiple instances). + """ + pass + + @namelist_item + def restfils(self) -> str: + """ + stream restart filename for the data atmosphere stream data. This is + optional. If both restfils and restfilm are undefined, the restart + filename will be read from the DATM restart pointer file (or files for multiple instances). + """ + pass + + @namelist_item + def wiso_datm(self) -> bool: + """ + flag which if true, says to turn on water isotopes + """ + pass + + @namelist_group + class shr_strdata_nml(): + + @namelist_item + def datamode(self) -> str: + """ + general method that operates on the data. this is generally + implemented in the data models but is set in the strdata method for + convenience. valid options are dependent on the data model and will + be described elsewhere. NULL is always a valid option and means no + data will be generated. default='NULL' + + datamode = "NULL" + turns off the data model as a provider of data to the coupler. + The atm_present flag will be set to false + and the coupler will assume no exchange of data to or from the data model. + + datamode = "COPYALL" + The default science mode of the data model is the COPYALL mode. + COPYALL mode will examine the fields found in all input data streams, + if any input field names match the field names used internally, they + are copied into the export array and passed directly to the coupler + without any special user code. Any required fields not found on an + input stream will be set to zero except for aerosol deposition fields + which will be set to a special value. There are several other + scientific modes supported by the model, they are listed below. The + mode is selected by a character string set in the strdata namelist + variable dataMode. + + datamode = "CORE2_NYF" + Coordinated Ocean-ice Reference Experiments (CORE) Version 2 Normal Year Forcing. + + datamode = "CORE2_IAF" + In conjunction with with CORE Version 2 atmospheric forcing data, + provides the atmosphere forcing favored by the Ocean Model Working + Group when coupling an active ocean model with observed atmospheric + forcing. This mode and associated data sets implement the CORE-IAF + Version 2 forcing data, as developed by Large and Yeager (2008) at + NCAR. See the documentation for CORE version 2 datasets at + http://data1.gfdl.noaa.gov/nomads/forms/mom4/COREv2.html Also see + W.G.Large, S.G.Yeager (2008), The global climatology of an + interannually varying air-sea flux data set. + Clm Dyn doi 10.1007/s00382-008-0441-3. + + datamode = "CORE_IAF_JRA*" + JRA55 intra-annual year forcing + + datamode = "CLMNCEP" + In conjunction with NCEP climatological atmosphere data, provides the + atmosphere forcing favored by the Land Model Working Group when + coupling an active land model with observed atmospheric forcing. This + mode replicates code previously found in CLM (circa 2005), before the + LMWG started using the CCSM flux coupler and data models to do + active-land-only simulations. + """ + pass + + @namelist_item + def domainfile(self) -> str: + """ + model spatial gridfile associated with the strdata. grid information will + be read from this file and that grid will serve as the target grid + for all input data for this strdata input. + """ + pass + + @namelist_item + def dtlimit(self) -> List[float]: + """ + array (up to 30 elements) of delta time ratio limits placed on the + time interpolation associated with the array of streams. this real + value causes the model to stop if the ratio of the running maximum + delta time divided by the minimum delta time is greater than the + dtlimit for that stream. for instance, with daily data, the delta + time should be exactly one day throughout the dataset and the computed + maximum divided by minimum delta time should always be 1.0. for + monthly data, the delta time should be between 28 and 31 days and the + maximum ratio should be about 1.1. the running value of the delta + time is computed as data is read and any wraparound or cycling is also + included. this input helps trap missing data or errors in cycling. + to turn off trapping, set the value to 1.0e30 or something similar. + """ + pass + + @namelist_item + def fillalgo(self) -> List[str]: + """ + array (up to 30 elements) of fill algorithms associated with the array + of streams. valid options are just copy (ie. no fill), special value, + nearest neighbor, nearest neighbor in "i" direction, or nearest + neighbor in "j" direction. + valid values: 'copy','spval','nn','nnoni','nnonj' + """ + pass + + @namelist_item + def fillmask(self) -> List[str]: + """ + plays no role is fill algorithm at the present time. + valid values: "nomask,srcmask,dstmask,bothmask" + """ + pass + + @namelist_item + def fillread(self) -> List[str]: + """ + array (up to 30 elements) of filenames associated with the array of + streams. specifies the weights file to read in instead of computing the + weights on the fly for the fill operation. if this is set, fillalgo + and fillmask are ignored. + """ + pass + + @namelist_item + def fillwrite(self) -> List[str]: + """ + array (up to 30 elements) of filenames associated with the array of + streams. specifies the weights file to generate after weights are + computed on the fly for the fill operation. this allows a user to + save and reuse a set of weights later. + """ + pass + + @namelist_item + def mapalgo(self) -> List[str]: + """ + array (up to 30 elements) of fill algorithms associated with the array + of streams. valid options are copy by index, set to special value, + nearest neighbor, nearest neighbor in "i" direction, nearest neighbor + in "j" direction, or bilinear. + valid values: copy,spval,nn,nnoni,nnonj,bilinear + """ + pass + + @namelist_item + def mapmask(self) -> List[str]: + """ + array (up to 30 elements) of masking algorithms for mapping input data + associated with the array of streams. valid options are map only from + valid src points, map only to valid destination points, ignore all + masks, map only from valid src points to valid destination points. + valid values: srcmask, dstmask, nomask,bothmask + """ + pass + + @namelist_item + def mapread(self) -> List[str]: + """ + array (up to 30 elements) of filenames associated with the array of + streams. specifies the weights file to read instead of computing + weights on the fly for the mapping (interpolation) operation. if this + is set, mapalgo and mapmask are ignored. + """ + pass + + @namelist_item + def mapwrite(self) -> List[str]: + """ + array (up to 30 elements) of filenames associated with the array of + streams. specifies the weights file to generate after weights are + computed on the fly for the mapping (interpolation) operation. this + allows a user to save and reuse a set of weights later. + """ + pass + + @namelist_item + def readmode(self) -> List[str]: + """ + array (up to 30 elements) of reading mode associated with the array of + streams. specifies the mode of reading temporal stream dataset. + valid options are "single" (read temporal dataset one at a time) or + "full_file" (read all entires of temporal dataset in a given netcdf file) + valid values: single,full_file + """ + pass + + @namelist_item + def streams(self) -> List[str]: + """ + character array (up to 30 elements) of stream input files. this + string is actually parsed by a stream method and so the format is + specified by the stream module. this string consists of a + "stream_input_filename year_align year_first year_last". the + stream_input_filename is a stream text input file and the format and + options are described elsewhere. year_align, year_first, and + year_last provide information about the time axis of the file and how + to relate the input time axis to the model time axis. + """ + pass + + @namelist_item + def taxmode(self) -> List[str]: + """ + array of time axis modes associated with the array of streams for + handling data outside the specified stream time axis. + valid options are to cycle the data based on the first, last, and + align settings associated with the stream dataset, to extend the first + and last valid value indefinitely, or to limit the interpolated data + to fall only between the least and greatest valid value of the time array. + valid values: cycle,extend,limit + """ + pass + + @namelist_item + def tintalgo(self) -> List[str]: + """ + array (up to 30 elements) of time interpolation options associated with the array of + streams. + valid values: lower,upper,nearest,linear,coszen + lower = Use lower time-value + upper = Use upper time-value + nearest = Use the nearest time-value + linear = Linearly interpolate between the two time-values + coszen = Scale according to the cosine of the solar zenith angle (for solar) + """ + pass + + @namelist_item + def vectors(self) -> List[str]: + """ + list of paired colon delimited field names that should be treated as + vectors when carrying out spatial interpolation. unlike other + character arrays in this namelist, this array is completely decoupled + from the list of streams. this is a list of vector pairs that span + all input streams where different fields of the vector pair could + appear in different streams. + for example, vectors = 'u:v','taux:tauy'. + """ + pass \ No newline at end of file diff --git a/namelist_generator/clm5nl/structures/nl_drv_flds_in.py b/namelist_generator/clm5nl/structures/nl_drv_flds_in.py new file mode 100644 index 0000000000..5dd2784029 --- /dev/null +++ b/namelist_generator/clm5nl/structures/nl_drv_flds_in.py @@ -0,0 +1,80 @@ +"""drv_flds_in namelist +""" +from typing import List +from .namelist import Namelist, namelist_group , namelist_item + +class drv_flds_in(Namelist): + + @namelist_group + class drydep_inparm(): + + @namelist_item + def drydep_list(self) -> List[str]: + """ + List of species that undergo dry deposition. + """ + pass + + @namelist_item + def drydep_method(self) -> str: + """ + Where dry deposition is calculated (from land, atmosphere, or from a table) + This specifies the method used to calculate dry + deposition velocities of gas-phase chemical species. The available methods + are: + 'table' - prescribed method in CAM + 'xactive_atm' - interactive method in CAM + 'xactive_lnd' - interactive method in CLM + """ + pass + + @namelist_group + class fire_emis_nl(): + + @namelist_item + def fire_emis_elevated(self) -> bool: + """ + If ture fire emissions are input into atmosphere as elevated forcings. + Otherwise they are treated as surface emissions. + Default: TRUE + """ + pass + + @namelist_item + def fire_emis_factors_file(self) -> str: + """ + File containing fire emissions factors. + Default: none + """ + pass + + @namelist_item + def fire_emis_specifier(self) -> List[str]: + """ + Fire emissions specifier. + Default: none + """ + pass + + @namelist_group + class megan_emis_nl(): + + @namelist_item + def megan_factors_file(self) -> str: + """ + File containing MEGAN emissions factors. Includes the list of MEGAN compounds that can be + used in the Comp_Name variable on the file. + """ + pass + + @namelist_item + def megan_specifier(self) -> List[str]: + """ + MEGAN specifier. This is in the form of: Chem-compound = megan_compound(s) + where megan_compound(s) can be the sum of megan compounds with a "+" between them. + In each equation, the item to the left of the equal sign is a CAM chemistry compound, the + items to the right are compounds known to the MEGAN model (single or combinations). + For example: megan_specifier = 'ISOP = isoprene', 'C10H16 = pinene_a + carene_3 + thujene_a' + """ + pass + \ No newline at end of file diff --git a/namelist_generator/clm5nl/structures/nl_drv_in.py b/namelist_generator/clm5nl/structures/nl_drv_in.py new file mode 100644 index 0000000000..0fa874312a --- /dev/null +++ b/namelist_generator/clm5nl/structures/nl_drv_in.py @@ -0,0 +1,2006 @@ +from typing import List +from .namelist import Namelist, namelist_group , namelist_item + +class drv_in(Namelist): + + @namelist_group + class cime_driver_inst(): + + @namelist_item + def ninst_driver(self) -> int: + """ + Number of CESM driver instances. Only used if MULTI_DRIVER is TRUE. + """ + pass + + @namelist_group + class cime_pes(): + + @namelist_item + def atm_layout(self) -> str: + """ + Layout of multi-instance atms (if there are more than 1) + """ + pass + + @namelist_item + def atm_ntasks(self) -> int: + """ + the number of mpi tasks assigned to the atm components. + set by NTASKS_ATM in env_configure.xml. + """ + pass + + @namelist_item + def atm_nthreads(self) -> int: + """ + the number of threads per mpi task for the atm component. + set by NTHRDS_ATM in env_configure.xml. + """ + pass + + @namelist_item + def atm_pestride(self) -> int: + """ + the mpi global processors stride associated with the mpi tasks for the atm component. + set by PSTRID_ATM in env_configure.xml. + """ + pass + + @namelist_item + def atm_rootpe(self) -> int: + """ + the global mpi task rank of the root processor assigned to the atm component. + set by ROOTPE_ATM in env_configure.xml. + """ + pass + + @namelist_item + def cpl_ntasks(self) -> int: + """ + the number of mpi tasks assigned to the cpl components. + set by NTASKS_CPL in env_configure.xml. + """ + pass + + @namelist_item + def cpl_nthreads(self) -> int: + """ + the number of threads per mpi task for the cpl component. + set by NTHRDS_CPL in env_configure.xml. + """ + pass + + @namelist_item + def cpl_pestride(self) -> int: + """ + the mpi global processors stride associated with the mpi tasks for the cpl component. + set by PSTRID_CPL in env_configure.xml. + """ + pass + + @namelist_item + def cpl_rootpe(self) -> int: + """ + the global mpi task rank of the root processor assigned to the cpl component. + set by ROOTPE_CPL in env_configure.xml. + """ + pass + + @namelist_item + def esp_layout(self) -> str: + """ + Layout of multi-instance external system processor (if there are more than 1) + """ + pass + + @namelist_item + def esp_ntasks(self) -> int: + """ + the number of mpi tasks assigned to the esp components. + set by NTASKS_ESP in env_configure.xml. + """ + pass + + @namelist_item + def esp_nthreads(self) -> int: + """ + the number of threads per mpi task for the esp component. + set by NTHRDS_ESP in env_configure.xml. + """ + pass + + @namelist_item + def esp_pestride(self) -> int: + """ + the mpi global processors stride associated with the mpi tasks for the esp component. + set by PSTRID_ESP in env_configure.xml. + """ + pass + + @namelist_item + def esp_rootpe(self) -> int: + """ + the global mpi task rank of the root processor assigned to the esp component. + set by ROOTPE_ESP in env_configure.xml. + """ + pass + + @namelist_item + def glc_layout(self) -> str: + """ + Layout of multi-instance glcs (if there are more than 1) + """ + pass + + @namelist_item + def glc_ntasks(self) -> int: + """ + the number of mpi tasks assigned to the glc components. + set by NTASKS_GLC in env_configure.xml. + """ + pass + + @namelist_item + def glc_nthreads(self) -> int: + """ + the number of threads per mpi task for the glc component. + set by NTHRDS_GLC in env_configure.xml. + """ + pass + + @namelist_item + def glc_pestride(self) -> int: + """ + the mpi global processors stride associated with the mpi tasks for the glc component. + set by PSTRID_GLC in env_configure.xml. + """ + pass + + @namelist_item + def glc_rootpe(self) -> int: + """ + the global mpi task rank of the root processor assigned to the glc component. + set by ROOTPE_GLC in env_configure.xml. + """ + pass + + @namelist_item + def ice_layout(self) -> str: + """ + Layout of multi-instance ices (if there are more than 1) + """ + pass + + @namelist_item + def ice_ntasks(self) -> int: + """ + the number of mpi tasks assigned to the ice components. + set by NTASKS_ICE in env_configure.xml. + """ + pass + + @namelist_item + def ice_nthreads(self) -> int: + """ + the number of threads per mpi task for the ice component. + set by NTHRDS_ICE in env_configure.xml. + """ + pass + + @namelist_item + def ice_pestride(self) -> int: + """ + the mpi global processors stride associated with the mpi tasks for the ice component. + set by PSTRID_ICE in env_configure.xml. + """ + pass + + @namelist_item + def ice_rootpe(self) -> int: + """ + the global mpi task rank of the root processor assigned to the ice component. + set by ROOTPE_ICE in env_configure.xml. + """ + pass + + @namelist_item + def lnd_layout(self) -> str: + """ + Layout of multi-instance lnds (if there are more than 1) + """ + pass + + @namelist_item + def lnd_ntasks(self) -> int: + """ + the number of mpi tasks assigned to the lnd components. + set by NTASKS_LND in env_configure.xml. + """ + pass + + @namelist_item + def lnd_nthreads(self) -> int: + """ + the number of threads per mpi task for the lnd component. + set by NTHRDS_LND in env_configure.xml. + """ + pass + + @namelist_item + def lnd_pestride(self) -> int: + """ + the mpi global processors stride associated with the mpi tasks for the lnd component. + set by PSTRID_LND in env_configure.xml. + """ + pass + + @namelist_item + def lnd_rootpe(self) -> int: + """ + the global mpi task rank of the root processor assigned to the lnd component. + set by ROOTPE_LND in env_configure.xml. + """ + pass + + @namelist_item + def ocn_layout(self) -> str: + """ + Layout of multi-instance ocns (if there are more than 1) + """ + pass + + @namelist_item + def ocn_ntasks(self) -> int: + """ + the number of mpi tasks assigned to the ocn components. + set by NTASKS_OCN in env_configure.xml. + """ + pass + + @namelist_item + def ocn_nthreads(self) -> int: + """ + the number of threads per mpi task for the ocn component. + set by NTHRDS_OCN in env_configure.xml. + """ + pass + + @namelist_item + def ocn_pestride(self) -> int: + """ + the mpi global processors stride associated with the mpi tasks for the ocn component. + set by PSTRID_OCN in env_configure.xml. default: 1 + """ + pass + + @namelist_item + def ocn_rootpe(self) -> int: + """ + the global mpi task rank of the root processor assigned to the ocn component. + set by ROOTPE_OCN in env_configure.xml. + """ + pass + + @namelist_group + class esmf_inparm(): + + @namelist_item + def esmf_logfile_kind(self) -> str: + """ + Specify type of ESMF logging: + ESMF_LOGKIND_SINGLE, ESMF_LOGKIND_MULTI, ESMF_LOGKIND_MULTI_ON_ERROR, ESMF_LOGKIND_NONE + """ + pass + + @namelist_group + class papi_inparm(): + """ + in perf_mod.F90 + """ + + @namelist_item + def papi_ctr1_str(self) -> str: + """ + See gptl_papi.c for the list of valid values + """ + pass + + @namelist_item + def papi_ctr2_str(self) -> str: + """ + See gptl_papi.c for the list of valid values + """ + pass + + @namelist_item + def papi_ctr3_str(self) -> str: + """ + See gptl_papi.c for the list of valid values + """ + pass + + @namelist_item + def papi_ctr4_str(self) -> str: + """ + See gptl_papi.c for the list of valid values + """ + pass + + @namelist_group + class pio_default_inparm(): + + @namelist_item + def pio_async_interface(self) -> bool: + """ + future asynchronous IO capability (not currently supported). + If pio_async_interface is .true. or {component}_PIO_* variable is not set or set to -99 + the component variable will be set using the pio_* value. + default: .false. + """ + pass + + + @namelist_item + def pio_blocksize(self) -> int: + """ + blocksize for pio box rearranger + """ + pass + + + @namelist_item + def pio_buffer_size_limit(self) -> int: + """ + pio buffer size limit + """ + pass + + @namelist_item + def pio_debug_level(self) -> int: + """ + pio debug level + valid values: 0,1,2,3,4,5,6 + """ + pass + + @namelist_item + def pio_rearr_comm_enable_hs_comp2io(self) -> bool: + """ + pio rearranger communication option: Enable handshake (comp2io) + """ + pass + + @namelist_item + def pio_rearr_comm_enable_hs_io2comp(self) -> bool: + """ + pio rearranger communication option: Enable handshake (io2comp) + """ + pass + + @namelist_item + def pio_rearr_comm_enable_isend_comp2io(self) -> bool: + """ + pio rearranger communication option: Enable isends (comp2io) + """ + pass + + @namelist_item + def pio_rearr_comm_enable_isend_io2comp(self) -> bool: + """ + pio rearranger communication option: Enable isends (io2comp) + default: .false. + """ + pass + + @namelist_item + def pio_rearr_comm_fcd(self) -> str: + """ + pio rearranger communication flow control direction. + """ + pass + + @namelist_item + def pio_rearr_comm_max_pend_req_comp2io(self) -> int: + """ + pio rearranger communication max pending req (comp2io) + """ + pass + + @namelist_item + def pio_rearr_comm_max_pend_req_io2comp(self) -> int: + """ + pio rearranger communication max pending req (io2comp) + """ + pass + + @namelist_item + def pio_rearr_comm_type(self) -> str: + """ + pio rearranger communication type. + valid values: p2p, coll, default + """ + pass + + @namelist_group + class prof_inparm(): + + @namelist_item + def profile_add_detail(self) -> bool: + """ + default: .false. + """ + pass + + @namelist_item + def profile_barrier(self) -> bool: + """ + + """ + pass + + @namelist_item + def profile_depth_limit(self) -> int: + """ + + """ + pass + + @namelist_item + def profile_detail_limit(self) -> int: + """ + + """ + pass + + @namelist_item + def profile_disable(self) -> bool: + """ + + """ + pass + + @namelist_item + def profile_global_stats(self) -> bool: + """ + + """ + pass + + @namelist_item + def profile_outpe_num(self) -> int: + """ + default: 1 + """ + pass + + @namelist_item + def profile_outpe_stride(self) -> int: + """ + + """ + pass + + @namelist_item + def profile_ovhd_measurement(self) -> bool: + """ + default: .false. + """ + pass + + @namelist_item + def profile_papi_enable(self) -> bool: + """ + default: .false. + """ + pass + + @namelist_item + def profile_single_file(self) -> bool: + """ + + """ + pass + + @namelist_item + def profile_timer(self) -> bool: + """ + + """ + pass + + @namelist_group + class seq_cplflds_inparm(): + + @namelist_item + def flds_bgc_oi(self) -> bool: + """ + If set to .true. BGC fields will be passed back and forth between the ocean and seaice + via the coupler. + """ + pass + + @namelist_item + def flds_co2_dmsa(self) -> bool: + """ + If CCSM_BGC is set to 'CO2_DMSA', then flds_co2_dmsa will be set to .true. by default. + """ + pass + + @namelist_item + def flds_co2a(self) -> bool: + """ + If set to .true., adds prognostic CO2 and diagnostic CO2 at the lowest + model level to be sent from the atmosphere to the land and ocean. + If CCSM_BGC is set to 'CO2A', then flds_co2a will be set to .true. by default + """ + pass + + @namelist_item + def flds_co2b(self) -> bool: + """ + If set to .true., adds prognostic CO2 and diagnostic CO2 at the lowest + model level to be sent from the atmosphere just to the land, and the + surface upward flux of CO2 to be sent from the land back to the + atmosphere. + If CCSM_BGC is set to 'CO2B', then flds_co2b will be set to .true. by default. + """ + pass + + @namelist_item + def flds_co2c(self) -> bool: + """ + If set to .true., adds prognostic CO2 and diagnostic CO2 at the lowest + model level to be sent from the atmosphere to the land and ocean, and the + surface upward flux of CO2 to be sent from the land and the open ocean + back to the atmosphere. + If CCSM_BGC is set to 'CO2C', then flds_co2c will be set to .true. by default. + """ + pass + + @namelist_item + def flds_wiso(self) -> bool: + """ + Pass water isotopes between components + """ + pass + + @namelist_item + def glc_nec(self) -> int: + """ + Number of cism elevation classes. Set by the xml variable GLC_NEC in env_run.xml + """ + pass + + @namelist_item + def ice_ncat(self) -> int: + """ + Number of sea ice thickness categories. Set by the xml variable ICE_NCAT in env_build.xml + """ + pass + + @namelist_item + def nan_check_component_fields(self) -> bool: + """ + .true. means that all fields passed to coupler are checked for NaN values + """ + pass + + @namelist_item + def seq_flds_i2o_per_cat(self) -> bool: + """ + .true. if select per ice thickness category fields are passed to the ocean. + Set by the xml variable CPL_I2O_PER_CAT in env_run.xml + """ + pass + + @namelist_group + class seq_cplflds_userspec(): + + @namelist_item + def cplflds_custom(self) -> str: + """ + New fields that are user specified can be added as namelist variables + by the user in the cpl namelist seq_flds_user using the namelist variable + array cplflds_customs. The user specified new fields must follow the + above naming convention. + As an example, say you want to add a new state 'foo' that is passed + from the land to the atm - you would do this as follows + &seq_flds_user + cplflds_custom = 'Sa_foo->a2x', 'Sa_foo->x2a' + / + This would add the field 'Sa_foo' to the character strings defining the + attribute vectors a2x and x2a. It is assumed that code would need to be + introduced in the atm and land components to deal with this new attribute + vector field. + Modify user_nl_cpl to edit this. + """ + pass + + @namelist_group + class seq_flux_mct_inparm(): + + @namelist_item + def seq_flux_atmocn_minwind(self) -> int: + """ + minimum wind speed for atmOcn flux calculations + """ + pass + + @namelist_item + def seq_flux_mct_albdif(self) -> int: + """ + Surface albedo for diffuse radiation + """ + pass + + @namelist_item + def seq_flux_mct_albdir(self) -> int: + """ + Surface albedo for direct radiation + """ + pass + + @namelist_group + class seq_infodata_inparm(): + + @namelist_item + def aoflux_grid(self) -> str: + """ + Grid for atm ocn flux calc (untested) + default: ocn + """ + pass + + @namelist_item + def aqua_planet(self) -> bool: + """ + true => turn on aquaplanet mode in cam + """ + pass + + @namelist_item + def aqua_planet_sst(self) -> int: + """ + 1 => default sst mode for aquaplanet in cam + """ + pass + + @namelist_item + def atm_gnam(self) -> str: + """ + ATM_GRID values passed into driver. + """ + pass + + @namelist_item + def bfbflag(self) -> bool: + """ + turns on bfb option in coupler which produce bfb results in the + coupler on different processor counts. (default: .false.) + """ + pass + + @namelist_item + def brnch_retain_casename(self) -> bool: + """ + Allow same branch casename as reference casename. If $CASE and $REFCASE are the same and the start_type is + not startup, then the value of brnch_retain_casename is set to .true. + """ + pass + + @namelist_item + def budget_ann(self) -> int: + """ + sets the diagnotics level of the annual budgets. [0,1,2,3], + written only if do_budgets variable is .true., + 0=none, + 1=+net summary budgets, + 2=+detailed lnd/ocn/ice component budgets, + 3=+detailed atm budgets + default: 1 + """ + pass + + @namelist_item + def budget_daily(self) -> int: + """ + sets the diagnotics level of the daily budgets. [0,1,2,3], + written only if do_budgets variable is .true., + 0=none, + 1=+net summary budgets, + 2=+detailed lnd/ocn/ice component budgets, + 3=+detailed atm budgets + default: 0 + """ + pass + + @namelist_item + def budget_inst(self) -> int: + """ + sets the diagnotics level of the instantaneous budgets. [0,1,2,3], + written only if BUDGETS variable is true + 0=none, + 1=+net summary budgets, + 2=+detailed lnd/ocn/ice component budgets, + 3=+detailed atm budgets + default: 0 + """ + pass + + @namelist_item + def budget_ltann(self) -> int: + """ + sets the diagnotics level of the longterm budgets written at the end + of the year. [0,1,2,3], + written only if do_budgets variable is .true., + 0=none, + 1=+net summary budgets, + 2=+detailed lnd/ocn/ice component budgets, + 3=+detailed atm budgets, + default: 1 + """ + pass + + @namelist_item + def budget_ltend(self) -> int: + """ + sets the diagnotics level of the longterm budgets written at the end + of each run. [0,1,2,3], + written only if do_budgets variable is .true., + 0=none, + 1=+net summary budgets, + 2=+detailed lnd/ocn/ice component budgets, + 3=+detailed atm budgets, + default: 0 + """ + pass + + @namelist_item + def budget_month(self) -> int: + """ + sets the diagnotics level of the monthy budgets. [0,1,2,3], + written only if do_budgets variable is .true., + 0=none, + 1=+net summary budgets, + 2=+detailed lnd/ocn/ice component budgets, + 3=+detailed atm budgets + default: 1 + """ + pass + + @namelist_item + def case_desc(self) -> str: + """ + case description. + """ + pass + + @namelist_item + def case_name(self) -> str: + """ + case name. + """ + pass + + @namelist_item + def cime_model(self) -> str: + """ + cime model - e3sm or cesm + """ + pass + + @namelist_item + def coldair_outbreak_mod(self) -> bool: + """ + if true use Mahrt and Sun 1995,MWR modification to surface flux calculation + """ + pass + + @namelist_item + def cpl_decomp(self) -> int: + """ + cpl decomp option (0=default, 1=comp decomp, 2=rearr comp decomp, 3=new single 1d seg + default: 0 + """ + pass + + @namelist_item + def cpl_seq_option(self) -> str: + """ + Set the coupler sequencing. + """ + pass + + @namelist_item + def do_budgets(self) -> bool: + """ + logical that turns on diagnostic budgets, false means budgets will never be written + """ + pass + + @namelist_item + def do_histinit(self) -> bool: + """ + logical to write an extra initial coupler history file + """ + pass + + @namelist_item + def drv_threading(self) -> bool: + """ + turn on run time control of threading per pe per component by the driver + default: false + """ + pass + + @namelist_item + def eps_aarea(self) -> float: + """ + Error tolerance for differences in atm/land areas in domain checking + default: 1.0e-07 + """ + pass + + @namelist_item + def eps_agrid(self) -> float: + """ + Error tolerance for differences in atm/land lat/lon in domain checking + default: 1.0e-12 + """ + pass + + @namelist_item + def eps_amask(self) -> float: + """ + Error tolerance for differences in atm/land masks in domain checking + default: 1.0e-13 + """ + pass + + @namelist_item + def eps_frac(self) -> float: + """ + Error tolerance for differences in fractions in domain checking + default: 1.0e-02 + """ + pass + + @namelist_item + def eps_oarea(self) -> float: + """ + Error tolerance for differences in ocean/ice lon/lat in domain checking + default: 1.0e-1 + """ + pass + + @namelist_item + def eps_ogrid(self) -> float: + """ + Error tolerance for differences in ocean/ice lon/lat in domain checking + default: 1.0e-2 + """ + pass + + @namelist_item + def eps_omask(self) -> float: + """ + Error tolerance for differences in ocean/ice masks in domain checking + default: 1.0e-06 + """ + pass + + @namelist_item + def flux_albav(self) -> bool: + """ + Only used for C,G compsets: if true, compute albedos to work with daily avg SW down + """ + pass + + @namelist_item + def flux_convergence(self) -> float: + """ + Iterate atmocn flux calculation to this % difference + Setting this to zero will always do flux_max_iteration + """ + pass + + @namelist_item + def flux_diurnal(self) -> bool: + """ + If true, turn on diurnal cycle in computing atm/ocn fluxes + default: false + """ + pass + + @namelist_item + def flux_epbal(self) -> str: + """ + Only used for C,G compsets: if ocn, ocn provides EP balance factor for precip + """ + pass + + @namelist_item + def flux_max_iteration(self) -> int: + """ + Iterate atmocn flux calculation a max of this value + """ + pass + + @namelist_item + def force_stop_at(self) -> str: + """ + Force stop at the next month, day, etc when wall_time_limit is hit + default: month + """ + pass + + @namelist_item + def glc_gnam(self) -> str: + """ + GLC_GRID values passed into driver. + """ + pass + + @namelist_item + def glc_renormalize_smb(self) -> str: + """ + Whether to renormalize the surface mass balance (smb) sent from lnd to glc so that the + global integral on the glc grid agrees with the global integral on the lnd grid. + + Unlike most fluxes, smb is remapped with bilinear rather than conservative mapping weights, + so this option is needed for conservation. However, conservation is not required in many + cases, since we often run glc as a diagnostic (one-way-coupled) component. + + Allowable values are: + 'on': always do this renormalization + 'off': never do this renormalization (see WARNING below) + 'on_if_glc_coupled_fluxes': Determine at runtime whether to do this renormalization. + Does the renormalization if we're running a two-way-coupled glc that sends fluxes + to other components (which is the case where we need conservation). + Does NOT do the renormalization if we're running a one-way-coupled glc, or if + we're running a glc-only compset (T compsets). + (In these cases, conservation is not important.) + + Only used if running with a prognostic GLC component. + + WARNING: Setting this to 'off' will break conservation when running with an + evolving, two-way-coupled glc. + """ + pass + + @namelist_item + def gust_fac(self) -> float: + """ + wind gustiness factor + """ + pass + + @namelist_item + def histaux_a2x(self) -> bool: + """ + turns on coupler history stream for instantaneous atm to coupler fields. + default: false + """ + pass + + @namelist_item + def histaux_a2x1hr(self) -> bool: + """ + turns on coupler history stream for 1-hour average atm to coupler fields. + default: false + """ + pass + + @namelist_item + def histaux_a2x1hri(self) -> bool: + """ + turns on coupler history stream for 1-hour instantaneous atm to coupler fields. + default: false + """ + pass + + @namelist_item + def histaux_a2x24hr(self) -> bool: + """ + turns on coupler history stream for daily average atm to coupler fields. + default: false + """ + pass + + @namelist_item + def histaux_a2x3hr(self) -> bool: + """ + turns on coupler history stream for 3-hour average atm to coupler fields. + default: false + """ + pass + + @namelist_item + def histaux_a2x3hrp(self) -> bool: + """ + turns on coupler history stream for 3-hour average atm to coupler precip fields. + default: false + """ + pass + + @namelist_item + def histaux_double_precision(self) -> bool: + """ + if true, use double-precision rather than single-precision for + coupler auxiliary history files + default: false + """ + pass + + @namelist_item + def histaux_l2x(self) -> bool: + """ + turns on coupler history stream for instantaneous land to coupler fields. + default: false + """ + pass + + @namelist_item + def histaux_l2x1yrg(self) -> bool: + """ + turns on coupler history stream for annual lnd to coupler glc forcing fields. + default: false + """ + pass + + @namelist_item + def histaux_r2x(self) -> bool: + """ + turns on coupler history stream for average* runoff to coupler fields + (*despite the lack of an averaging time span in the name). + Files are written at time-of-day = 00000, and at the end of the run interval, + even if that time is not 00000. + Run length less than 24 hours; averaging period is the run length, + Otherwise; averaging period is 24 hours for files before the last (partial) day, + averaging period is the last (partial) day for the last file. + default: false + """ + pass + + @namelist_item + def histavg_atm(self) -> bool: + """ + writes atm fields in coupler average history files. + default: true + """ + pass + + @namelist_item + def histavg_glc(self) -> bool: + """ + writes glc fields in coupler average history files. + default: true + """ + pass + + @namelist_item + def histavg_ice(self) -> bool: + """ + writes ice fields in coupler average history files. + default: true + """ + pass + + @namelist_item + def histavg_lnd(self) -> bool: + """ + writes lnd fields in coupler average history files. + default: true + """ + pass + + @namelist_item + def histavg_ocn(self) -> bool: + """ + writes ocn fields in coupler average history files. + default: true + """ + pass + + @namelist_item + def histavg_rof(self) -> bool: + """ + writes rof fields in coupler average history files. + default: true + """ + pass + + @namelist_item + def histavg_wav(self) -> bool: + """ + writes wav fields in coupler average history files. + default: true + """ + pass + + @namelist_item + def histavg_xao(self) -> bool: + """ + writes xao fields in coupler average history files. + default: true + """ + pass + + @namelist_item + def hostname(self) -> str: + """ + hostname information + """ + pass + + @namelist_item + def ice_gnam(self) -> str: + """ + ICE_GRID values passed into driver. + """ + pass + + @namelist_item + def info_debug(self) -> int: + """ + Level of debug output, 0=minimum, 1=normal, 2=more, 3=too much (default: 1) + """ + pass + + @namelist_item + def lnd_gnam(self) -> str: + """ + LND_GRID values passed into driver. + """ + pass + + @namelist_item + def logfilepostfix(self) -> str: + """ + Ending suffix "postfix" for output log files. + """ + pass + + @namelist_item + def max_cplstep_time(self) -> float: + """ + Abort model if coupler timestep wallclock time exceeds this value, ignored if 0, + if < 0 then use abs(max_cplstep_time)*cktime as the threshold. + """ + pass + + @namelist_item + def mct_usealltoall(self) -> bool: + """ + mct alltoall mapping flag + default: false + """ + pass + + @namelist_item + def mct_usevector(self) -> bool: + """ + mct vector flag + default: false + """ + pass + + @namelist_item + def model_doi_url(self) -> str: + """ + model doi url + """ + pass + + @namelist_item + def model_version(self) -> str: + """ + model version documentation + """ + pass + + @namelist_item + def ocn_gnam(self) -> str: + """ + OCN_GRID values passed into driver. + """ + pass + + @namelist_item + def orb_eccen(self) -> float: + """ + eccentricity of orbit, used when orb_mode is fixed_parameters. + default: SHR_ORB_UNDEF_REAL (1.e36) (Not currently used in build-namelist) + """ + pass + + @namelist_item + def orb_iyear(self) -> int: + """ + year of orbit, used when orb_mode is fixed_year or variable_year. (default: 1990) + """ + pass + + @namelist_item + def orb_iyear_align(self) -> int: + """ + model year associated with orb_iyear when orb_mode is variable_year. (default: 1990) + """ + pass + + @namelist_item + def orb_mode(self) -> str: + """ + orbital model setting. this sets how the orbital mode will be + configured. + "fixed_year" uses the orb_iyear and other orb inputs are ignored. In + this mode, the orbital parameters are constant and based on the year. + "variable_year" uses the orb_iyear and orb_iyear_align. In this mode, + the orbital parameters vary as the model year advances and the model + year orb_iyear_align has the equivalent orbital year of orb_iyear. + "fixed_parameters" uses the orb_eccen, orb_mvelp, and orb_obliq to set + the orbital parameters which then remain constant through the model + integration. [fixed_year, variable_year, fixed_parameters] (default: 'fixed_year'.) + """ + pass + + @namelist_item + def orb_mvelp(self) -> float: + """ + location of vernal equinox in longitude degrees, used when orb_mode is fixed_parameters. + default: SHR_ORB_UNDEF_REAL (1.e36)(Not currently used in build-namelist) + """ + pass + + @namelist_item + def orb_obliq(self) -> float: + """ + obliquity of orbit in degrees, used when orb_mode is fixed_parameters. + default: SHR_ORB_UNDEF_REAL (1.e36) (Not currently used in build-namelist) + """ + pass + + @namelist_item + def outpathroot(self) -> str: + """ + Root directory for driver output files + """ + pass + + @namelist_item + def reprosum_diffmax(self) -> float: + """ + Tolerance for relative error + default: -1.0e-8 + """ + pass + + @namelist_item + def reprosum_recompute(self) -> bool: + """ + Recompute with non-scalable algorithm if reprosum_diffmax is exceeded. + default: .false. + """ + pass + + @namelist_item + def reprosum_use_ddpdd(self) -> bool: + """ + Use faster method for reprosum, but one where reproducibility is not always guaranteed. + default: .false. + """ + pass + + @namelist_item + def restart_file(self) -> str: + """ + Driver restart filename. + (NOTE: Normally THIS IS NOT USED -- Set with RUN_REFCASE and RUN_REFDATE) + """ + pass + + @namelist_item + def rof_gnam(self) -> str: + """ + ROF_GRID values passed into driver. + """ + pass + + @namelist_item + def run_barriers(self) -> bool: + """ + default: .false. + """ + pass + + @namelist_item + def scmlat(self) -> int: + """ + grid point latitude associated with single column mode. + if set to -999, ignore this value + """ + pass + + @namelist_item + def scmlon(self) -> int: + """ + grid point longitude associated with single column mode. + set by PTS_LON in env_run.xml. + """ + pass + + @namelist_item + def shr_map_dopole(self) -> bool: + """ + invoke pole averaging corrections in shr_map_mod weights generation (default: true) + """ + pass + + @namelist_item + def single_column(self) -> bool: + """ + turns on single column mode. set by PTS_MODE in env_case.xml, default: false + """ + pass + + @namelist_item + def start_type(self) -> str: + """ + mode to start the run up, [startup,branch,continue], + automatically derived from RUN_TYPE in env_run.xml + """ + pass + + @namelist_item + def tchkpt_dir(self) -> str: + """ + location of timing checkpoint output + """ + pass + + @namelist_item + def tfreeze_option(self) -> str: + """ + Freezing point calculation for salt water. + """ + pass + + @namelist_item + def timing_dir(self) -> str: + """ + location of timing output + """ + pass + + @namelist_item + def username(self) -> str: + """ + username documentation + """ + pass + + @namelist_item + def vect_map(self) -> str: + """ + vect_map + turns on the vector mapping option for u and v vector mapping between + atm and ocean grids in the coupler. the options are none, npfix, + cart3d, cart3d_diag, cart3d_uvw, and cart3d_uvw_diag. the none option + results in scalar mapping independently for the u and v field which + tends to generate large errors near the poles. npfix is the + traditional option where the vectors are corrected on the ocean grid + north of the last latitude line of the atmosphere grid. the cart3d + options convert the east (u) and north (v) vectors to 3d (x,y,z) + triplets, and maps those fields before converting back to the east (u) + and north (v) directions. the cart3d ignores the resuling "w" + velocity. the cart3d_uvw calculates the resulting u and v vectors by + preserving the total "u,v,w" speed and the angle of the (u,v) vector. + the _diag options just add diagnotics to the log file about the vector + mapping. + """ + pass + + @namelist_item + def wall_time_limit(self) -> float: + """ + Wall time limit for run + default: -1.0 + """ + pass + + @namelist_item + def wav_gnam(self) -> float: + """ + WAV_GRID values passed into driver. + """ + pass + + @namelist_item + def wv_sat_scheme(self) -> str: + """ + Type of water vapor saturation vapor pressure scheme employed. 'GoffGratch' for + Goff and Gratch (1946); 'MurphyKoop' for Murphy and Koop (2005); 'Bolton' for + Bolton (1980); 'Flatau' for Flatau, Walko, and Cotton (1992). + Default: GoffGratch + """ + pass + + @namelist_item + def wv_sat_table_spacing(self) -> float: + """ + Temperature resolution of saturation vapor pressure lookup tables in Kelvin. + (This is only used if wv_sat_use_tables is .true.) + Default: 1.0 + """ + pass + + @namelist_item + def wv_sat_transition_start(self) -> float: + """ + Width of the liquid-ice transition range in mixed-phase water saturation vapor + pressure calculations. The range always ends at 0 degrees Celsius, so this + variable only affects the start of the transition. + Default: 20K + WARNING: CAM is tuned to the default value of this variable. Because it affects + so many different parameterizations, changes to this variable may require a + significant retuning of CAM's cloud physics to give reasonable results. + """ + pass + + @namelist_item + def wv_sat_use_tables(self) -> bool: + """ + Whether or not to produce lookup tables at init time to use as a cache for + saturation vapor pressure. + Default: .false. + """ + pass + + @namelist_group + class seq_timemgr_inparm(): + + @namelist_item + def atm_cpl_dt(self) -> int: + """ + atm coupling interval in seconds + set via ATM_NCPL in env_run.xml. + ATM_NCPL is the number of times the atm is coupled per NCPL_BASE_PERIOD + NCPL_BASE_PERIOD is also set in env_run.xml and is the base period + associated with NCPL coupling frequency, and has valid values: hour,day,year,decade + """ + pass + + @namelist_item + def atm_cpl_offset(self) -> int: + """ + atm coupling interval offset in seconds default: 0 + """ + pass + + @namelist_item + def barrier_n(self) -> int: + """ + Sets model barriers with barrier_option and barrier_ymd (same options as stop_n) + default: 1 + """ + pass + + @namelist_item + def barrier_option(self) -> str: + """ + sets the driver barrier frequency to sync models across all tasks with barrier_n and barrier_ymd + barrier_option alarms are like restart_option + default: never + """ + pass + + @namelist_item + def barrier_ymd(self) -> int: + """ + Date in yyyymmdd format, sets model barriers date with barrier_option and barrier_n + """ + pass + + @namelist_item + def calendar(self) -> str: + """ + calendar in use. [NO_LEAP, GREOGORIAN]. + set by CALENDAR in env_build.xml + """ + pass + + @namelist_item + def data_assimilation_atm(self) -> bool: + """ + Whether Data Assimilation is on for component atm + """ + pass + + @namelist_item + def data_assimilation_cpl(self) -> bool: + """ + Whether Data Assimilation is on for component CPL + """ + pass + + @namelist_item + def data_assimilation_glc(self) -> bool: + """ + Whether Data Assimilation is on for component glc + """ + pass + + @namelist_item + def data_assimilation_ice(self) -> bool: + """ + Whether Data Assimilation is on for component ice + """ + pass + + @namelist_item + def data_assimilation_lnd(self) -> bool: + """ + Whether Data Assimilation is on for component lnd + """ + pass + + @namelist_item + def data_assimilation_ocn(self) -> bool: + """ + Whether Data Assimilation is on for component ocn + """ + pass + + @namelist_item + def data_assimilation_rof(self) -> bool: + """ + Whether Data Assimilation is on for component rof + """ + pass + + @namelist_item + def data_assimilation_wav(self) -> bool: + """ + Whether Data Assimilation is on for component wav + """ + pass + + @namelist_item + def end_restart(self) -> bool: + """ + true => write restarts at end of run + forces a restart write at the end of the run in addition to any + setting associated with rest_option. default=true. this setting + will be set to false if restart_option is none or never. + default: false + """ + pass + + @namelist_item + def esp_cpl_dt(self) -> int: + """ + esp run interval in seconds + esp_cpl_dt is the number of times the esp is run per NCPL_BASE_PERIOD + NCPL_BASE_PERIOD is set in env_run.xml and is the base period + associated with NCPL coupling frequency, nad has valid values: hour,day,year,decade + default value set by buildnml to be the pause interval if pause is active + otherwise, it is set to the shortest component coupling time + """ + pass + + @namelist_item + def esp_cpl_offset(self) -> int: + """ + esp coupling interval offset in seconds default: 0 + """ + pass + + @namelist_item + def esp_run_on_pause(self) -> bool: + """ + true => ESP component runs after driver 'pause cycle' If any + component 'pauses' (see PAUSE_OPTION, + PAUSE_N and DATA_ASSIMILATION_XXX XML + variables), the ESP component (if present) will be run to + process the component 'pause' (restart) files and set any + required 'resume' signals. If true, esp_cpl_dt and + esp_cpl_offset settings are ignored. default: true + """ + pass + + @namelist_item + def glc_avg_period(self) -> str: + """ + Period at which coupler averages fields sent to GLC. + This supports doing the averaging to GLC less frequently than GLC is called + (i.e., separating the averaging frequency from the calling frequency). + This is useful because there are benefits to only averaging the GLC inputs + as frequently as they are really needed (yearly for CISM), but GLC needs to + still be called more frequently than that in order to support mid-year restarts. + + Setting glc_avg_period to 'glc_coupling_period' means that the averaging is + done exactly when the GLC is called (governed by GLC_NCPL). + """ + pass + + @namelist_item + def glc_cpl_dt(self) -> int: + """ + glc coupling interval in seconds + set via GLC_NCPL in env_run.xml. + GLC_NCPL is the number of times the glc is coupled per NCPL_BASE_PERIOD + NCPL_BASE_PERIOD is also set in env_run.xml and is the base period + associated with NCPL coupling frequency, nad has valid values: hour,day,year,decade + """ + pass + + @namelist_item + def glc_cpl_offset(self) -> int: + """ + glc coupling interval offset in seconds default: 0 + """ + pass + + @namelist_item + def histavg_n(self) -> int: + """ + Sets coupler time-average history file frequency (like restart_option) + set by AVGHIST_N in env_run.xml. + """ + pass + + @namelist_item + def histavg_option(self) -> str: + """ + coupler time average history option (used with histavg_n and histavg_ymd) + set by AVGHIST_OPTION in env_run.xml. + histavg_option alarms are: + [none/never], turns option off + [nstep/s] , history snapshot every histavg_n nsteps , relative to current run start time + [nsecond/s] , history snapshot every histavg_n nseconds, relative to current run start time + [nminute/s] , history snapshot every histavg_n nminutes, relative to current run start time + [nhour/s] , history snapshot every histavg_n nhours , relative to current run start time + [nday/s] , history snapshot every histavg_n ndays , relative to current run start time + [monthly/s] , history snapshot every month , relative to current run start time + [nmonth/s] , history snapshot every histavg_n nmonths , relative to current run start time + [nyear/s] , history snapshot every histavg_n nyears , relative to current run start time + [date] , history snapshot at histavg_ymd value + [ifdays0] , history snapshot at histavg_n calendar day value and seconds equal 0 + [end] , history snapshot at end + """ + pass + + @namelist_item + def histavg_ymd(self) -> int: + """ + date associated with histavg_option date. yyyymmdd format. + set by AVGHIST_DATE in env_run.xml. + """ + pass + + @namelist_item + def history_n(self) -> int: + """ + sets coupler snapshot history file frequency (like restart_n) + set by HIST_N in env_run.xml. + """ + pass + + @namelist_item + def history_option(self) -> str: + """ + coupler history snapshot option (used with history_n and history_ymd) + set by HIST_OPTION in env_run.xml. + history_option alarms are: + [none/never], turns option off + [nstep/s] , history snapshot every history_n nsteps , relative to current run start time + [nsecond/s] , history snapshot every history_n nseconds, relative to current run start time + [nminute/s] , history snapshot every history_n nminutes, relative to current run start time + [nhour/s] , history snapshot every history_n nhours , relative to current run start time + [nday/s] , history snapshot every history_n ndays , relative to current run start time + [monthly/s] , history snapshot every month , relative to current run start time + [nmonth/s] , history snapshot every history_n nmonths , relative to current run start time + [nyear/s] , history snapshot every history_n nyears , relative to current run start time + [date] , history snapshot at history_ymd value + [ifdays0] , history snapshot at history_n calendar day value and seconds equal 0 + [end] , history snapshot at end + """ + pass + + @namelist_item + def history_ymd(self) -> int: + """ + date associated with history_option date. yyyymmdd format. + set by HIST_DATE in env_run.xml. + """ + pass + + @namelist_item + def ice_cpl_dt(self) -> int: + """ + ice coupling interval in seconds + set via ICE_NCPL in env_run.xml. + ICE_NCPL is the number of times the ice is coupled per NCPL_BASE_PERIOD + NCPL_BASE_PERIOD is also set in env_run.xml and is the base period + associated with NCPL coupling frequency, nad has valid values: hour,day,year,decade + """ + pass + + @namelist_item + def ice_cpl_offset(self) -> int: + """ + ice coupling interval offset in seconds default: 0 + """ + pass + + @namelist_item + def lnd_cpl_dt(self) -> int: + """ + lnd coupling interval in seconds + set via LND_NCPL in env_run.xml. + LND_NCPL is the number of times the lnd is coupled per NCPL_BASE_PERIOD + NCPL_BASE_PERIOD is also set in env_run.xml and is the base period + associated with NCPL coupling frequency, nad has valid values: hour,day,year,decade + """ + pass + + @namelist_item + def lnd_cpl_offset(self) -> int: + """ + lnd coupling interval offset in seconds default: 0 + """ + pass + + @namelist_item + def ocn_cpl_dt(self) -> int: + """ + ocn coupling interval in seconds + set via OCN_NCPL in env_run.xml. + OCN_NCPL is the number of times the ocn is coupled per NCPL_BASE_PERIOD + NCPL_BASE_PERIOD is also set in env_run.xml and is the base period + associated with NCPL coupling frequency, nad has valid values: hour,day,year,decade + """ + pass + + @namelist_item + def ocn_cpl_offset(self) -> int: + """ + ocn coupling interval offset in seconds default: 0 + """ + pass + + @namelist_item + def pause_active_atm(self) -> bool: + """ + Whether Pause signals are active for component atm + """ + pass + + @namelist_item + def pause_active_cpl(self) -> bool: + """ + Whether Pause signals are active for component CPL + """ + pass + + @namelist_item + def pause_active_glc(self) -> bool: + """ + Whether Pause signals are active for component ocn + """ + pass + + @namelist_item + def pause_active_ice(self) -> bool: + """ + Whether Pause signals are active for component ice + """ + pass + + @namelist_item + def pause_active_lnd(self) -> bool: + """ + Whether Pause signals are active for component lnd + """ + pass + + @namelist_item + def pause_active_ocn(self) -> bool: + """ + Whether Pause signals are active for component ocn + """ + pass + + @namelist_item + def pause_active_rof(self) -> bool: + """ + Whether Pause signals are active for component rof + """ + pass + + @namelist_item + def pause_active_wav(self) -> bool: + """ + Whether Pause signals are active for component wav + """ + pass + + @namelist_item + def pause_n(self) -> int: + """ + Sets the pause frequency with pause_option + """ + pass + + @namelist_item + def pause_option(self) -> str: + """ + sets the pause frequency with pause_n + pause_option alarms are: + [none/never], turns option off + [nstep/s] , pauses every pause_n nsteps , relative to start or last pause time + [nsecond/s] , pauses every pause_n nseconds, relative to start or last pause time + [nminute/s] , pauses every pause_n nminutes, relative to start or last pause time + [nhour/s] , pauses every pause_n nhours , relative to start or last pause time + [nday/s] , pauses every pause_n ndays , relative to start or last pause time + [nmonth/s] , pauses every pause_n nmonths , relative to start or last pause time + [monthly/s] , pauses every month , relative to start or last pause time + [nyear/s] , pauses every pause_n nyears , relative to start or last pause time + """ + pass + + @namelist_item + def restart_file(self) -> str: + """ + Driver restart filename. + (NOTE: Normally THIS IS NOT USED -- Set with RUN_REFCASE and RUN_REFDATE) + """ + pass + + @namelist_item + def restart_n(self) -> int: + """ + Sets model restart writes with restart_option and restart_ymd (same options as stop_n) + """ + pass + + @namelist_item + def restart_option(self) -> str: + """ + sets the restart frequency with restart_n and restart_ymd + restart_option alarms are: + [none/never], turns option off + [nstep/s] , restarts every restart_n nsteps , relative to current run start time + [nsecond/s] , restarts every restart_n nseconds, relative to current run start time + [nminute/s] , restarts every restart_n nminutes, relative to current run start time + [nhour/s] , restarts every restart_n nhours , relative to current run start time + [nday/s] , restarts every restart_n ndays , relative to current run start time + [monthly/s] , restarts every month , relative to current run start time + [nmonth/s] , restarts every restart_n nmonths , relative to current run start time + [nyear/s] , restarts every restart_n nyears , relative to current run start time + [date] , restarts at restart_ymd value + [ifdays0] , restarts at restart_n calendar day value and seconds equal 0 + [end] , restarts at end + """ + pass + + @namelist_item + def restart_ymd(self) -> int: + """ + Date in yyyymmdd format, sets model restart write date with rest_option and restart_n + default: STOP_N + """ + pass + + @namelist_item + def rof_cpl_dt(self) -> int: + """ + river runoff coupling interval in seconds + currently set by default to 10800 seconds. + default: 10800 + """ + pass + + @namelist_item + def start_tod(self) -> int: + """ + Start time-of-day in universal time (seconds), should be between zero and 86400 + default: 0 + """ + pass + + @namelist_item + def start_ymd(self) -> int: + """ + Run start date in yyyymmdd format, only used for startup and hybrid runs. + default: 00010101 + """ + pass + + @namelist_item + def stop_n(self) -> int: + """ + Sets the run length with stop_option and stop_ymd + """ + pass + + @namelist_item + def stop_option(self) -> str: + """ + sets the run length with stop_n and stop_ymd + stop_option alarms are: + [none/never], turns option off + [nstep/s] , stops every stop_n nsteps , relative to current run start time + [nsecond/s] , stops every stop_n nseconds, relative to current run start time + [nminute/s] , stops every stop_n nminutes, relative to current run start time + [nhour/s] , stops every stop_n nhours , relative to current run start time + [nday/s] , stops every stop_n ndays , relative to current run start time + [nmonth/s] , stops every stop_n nmonths , relative to current run start time + [monthly/s] , stops every month , relative to current run start time + [nyear/s] , stops every stop_n nyears , relative to current run start time + [date] , stops at stop_ymd value + [ifdays0] , stops at stop_n calendar day value and seconds equal 0 + [end] , stops at end + """ + pass + + @namelist_item + def stop_ymd(self) -> int: + """ + date in yyyymmdd format, sets the run length with stop_option and stop_n, + can be in addition to stop_option and stop_n, negative value implies off + """ + pass + + @namelist_item + def tprof_n(self) -> int: + """ + Sets timing output file frequency (like restart_n) + """ + pass + + @namelist_item + def tprof_option(self) -> str: + """ + Sets timing output file frequency (like rest_option but relative to run start date) + tprof_option alarms are: + [none/never], turns option off + [nstep/s] , every tprof_n nsteps , relative to current run start time + [nsecond/s] , every tprof_n nseconds, relative to current run start time + [nminute/s] , every tprof_n nminutes, relative to current run start time + [nhour/s] , every tprof_n nhours , relative to current run start time + [nday/s] , every tprof_n ndays , relative to current run start time + [monthly/s] , every month , relative to current run start time + [nmonth/s] , every tprof_n nmonths , relative to current run start time + [nyear/s] , every tprof_n nyears , relative to current run start time + [date] , at tprof_ymd value + [ifdays0] , at tprof_n calendar day value and seconds equal 0 + [end] , at end + """ + pass + + @namelist_item + def tprof_ymd(self) -> int: + """ + yyyymmdd format, sets timing output file date (like restart_date) + """ + pass + + @namelist_item + def wav_cpl_dt(self) -> int: + """ + wav coupling interval in seconds + set via WAV_NCPL in env_run.xml. + WAV_NCPL is the number of times the wav is coupled per NCPL_BASE_PERIOD + NCPL_BASE_PERIOD is also set in env_run.xml and is the base period + associated with NCPL coupling frequency, nad has valid values: hour,day,year,decade + """ + pass + + @namelist_item + def wav_cpl_offset(self) -> int: + """ + wav coupling interval offset in seconds default: 0 + """ + pass \ No newline at end of file diff --git a/namelist_generator/clm5nl/structures/nl_lnd_in.py b/namelist_generator/clm5nl/structures/nl_lnd_in.py new file mode 100644 index 0000000000..54b8c7ba60 --- /dev/null +++ b/namelist_generator/clm5nl/structures/nl_lnd_in.py @@ -0,0 +1,2113 @@ +""" +Lnd stdin namelist +""" +from typing import List +from .namelist import Namelist, namelist_group , namelist_item + +class lnd_in(Namelist): + + @namelist_group + class aerosol(): + + @namelist_item + def fresh_snw_rds_max(self) -> float: + """ + maximum warm (at freezing) fresh snow effective radius [microns] + """ + pass + + @namelist_group + class atm2lnd_inparm(): + + @namelist_item + def glcmec_downscale_longwave(self) -> bool: + """ + If TRUE, downscale longwave radiation over glc_mec landunits. + This downscaling is conservative. + """ + pass + + @namelist_item + def lapse_rate(self) -> float: + """ + Surface temperature lapse rate (K m-1) + A positive value means a decrease in temperature with increasing height + """ + pass + + @namelist_item + def lapse_rate_longwave(self) -> float: + """ + Longwave radiation lapse rate (W m-2 m-1) + A positive value means a decrease in LW radiation with increasing height + Only relevant if glcmec_downscale_longwave is .true. + """ + pass + + @namelist_item + def longwave_downscaling_limit(self) -> float: + """ + Relative limit for how much longwave downscaling can be done (unitless) + The pre-normalized, downscaled longwave is restricted to be in the range + [lwrad*(1-longwave_downscaling_limit), lwrad*(1+longwave_downscaling_limit)] + This parameter must be in the range [0,1] + Only relevant if glcmec_downscale_longwave is .true. + """ + pass + + @namelist_item + def precip_repartition_glc_all_rain_t(self) -> float: + """ + Temperature above which all precipitation falls as rain, for glacier columns (deg C) + Only relevant if repartition_rain_snow is .true. + """ + pass + + @namelist_item + def precip_repartition_glc_all_snow_t(self) -> float: + """ + Temperature below which all precipitation falls as snow, for glacier columns (deg C) + Only relevant if repartition_rain_snow is .true. + """ + pass + + @namelist_item + def precip_repartition_nonglc_all_rain_t(self) -> float: + """ + Temperature above which all precipitation falls as rain, for non-glacier columns (deg C) + Only relevant if repartition_rain_snow is .true. + """ + pass + + @namelist_item + def precip_repartition_nonglc_all_snow_t(self) -> float: + """ + Temperature below which all precipitation falls as snow, for non-glacier columns (deg C) + Only relevant if repartition_rain_snow is .true. + """ + pass + + @namelist_item + def repartition_rain_snow(self) -> bool: + """ + If TRUE, repartition rain/snow from atmosphere based on temperature. + """ + pass + + @namelist_group + class bgc_shared(): + + @namelist_item + def constrain_stress_deciduous_onset(self) -> bool: + """ + If TRUE use additional stress deciduous onset trigger + """ + pass + + @namelist_item + def decomp_depth_efolding(self) -> float: + """ + E-folding depth over which decomposition is slowed with depth in all soils. + """ + pass + + @namelist_group + class canopyfluxes_inparm(): + + @namelist_item + def use_undercanopy_stability(self) -> bool: + """ + If TRUE use the undercanopy stability term used with CLM4.5 (Sakaguchi & Zeng, 2008) + """ + pass + + @namelist_group + class century_soilbgcdecompcascade(): + + @namelist_item + def initial_Cstocks(self) -> List[float]: + """ + Initial stocks of Carbon to use in soil organic matter pools for CENTURY decomposition + """ + pass + + @namelist_item + def initial_Cstocks_depth(self) -> List[float]: + """ + Soil depth to place initial stocks of Carbon in soil organic matter pools for CENTURY decomposition + """ + pass + + @namelist_group + class ch4par_in(): + + @namelist_item + def allowlakeprod(self) -> bool: + """ + If TRUE, turn on methane biogeochemistry model for lake columns, + using a simplified version of the CH4 submodel. (EXPERIMENTAL) + """ + pass + + @namelist_item + def finundation_method(self) -> str: + """ + Inundated fraction method type to use for the CH4 submodel (possibly affecting soil + heterotrophic respiration and denitrification depending on the configuration), + + h2osfc ----------- Use prognostic saturated fraction h2osfc value calculated in Soil Hydrology + ZWT_inversion ---- Use inversion of Prigent Satellite data to model ZWT + TWS_inversion ---- Use inversion of Prigent Satellite data to model TWS + + Inversion options require additional data on fsurdat or use of stream_fldfilename_ch4finundated files. + (h2osfc option is EXPERIMENTAL and NOT tested) + """ + pass + + @namelist_item + def use_aereoxid_prog(self) -> bool: + """ + Allows user to tune the value of aereoxid. If set to FALSE, then use the value of aereoxid from + the parameter file (set to 0.0, but may be tuned with values in the range {0.0,1.0}. If set to TRUE, + then don't fix aere (see ch4Mod.F90). + """ + pass + + @namelist_group + class ch4finundated(): + + @namelist_item + def stream_fldfilename_ch4finundated(self) -> str: + """ + Filename of input stream data for finundated inversion of observed (from Prigent dataset) + to hydrologic variables (either TWS or ZWT) + """ + pass + + @namelist_group + class clm_canopy_inparm(): + + @namelist_item + def leaf_mr_vcm(self) -> float: + """ + Scalar of leaf respiration to vcmax + """ + pass + + @namelist_group + class clm_canopyhydrology_inparm(): + + @namelist_item + def interception_fraction(self) -> float: + """ + Fraction of intercepted precipitation + """ + pass + + @namelist_item + def maximum_leaf_wetted_fraction(self) -> float: + """ + Maximum fraction of leaf that may be wet prior to drip occuring + """ + pass + + @namelist_item + def oldfflag(self) -> int: + """ + Use old snow cover fraction from Niu et al. 2007 + (deprecated -- will be removed) + """ + pass + + @namelist_item + def snowveg_flag(self) -> str: + """ + Turn vegetation snow canopy ON, OFF, or ON with albedo influence (ON_RAD) + """ + pass + + @namelist_item + def use_clm5_fpi(self) -> str: + """ + If TRUE use clm5 equation for fraction of intercepted precipitation + """ + pass + + @namelist_group + class clm_glacier_behavior(): + + @namelist_item + def glacier_region_behavior(self) -> List[str]: + """ + Behavior of each glacier region (GLACIER_REGION in surface dataset). + First item corresponds to GLACIER_REGION with ID 0 in the surface dataset, + second to GLACIER_REGION with ID 1, etc. + Allowed values are: + 'multiple': grid cells can potentially have multiple glacier elevation defes, + but no virtual columns + 'virtual': grid cells have virtual columns: values are computed for every glacier + elevation def, even those with 0 area (in order to provide surface mass + balance for every glacier elevation def). + 'single_at_atm_topo': glacier landunits in these grid cells have a single column, + whose elevation matches the atmosphere's topographic height (so that there is no + adjustment due to downscaling) + Behavior of 'virtual' is required in the region where we have an ice sheet model + """ + pass + + @namelist_item + def glacier_region_ice_runoff_behavior(self) -> List[str]: + """ + Treatment of ice runoff for each glacier region (GLACIER_REGION in surface dataset). + First item corresponds to GLACIER_REGION with ID 0 in the surface dataset, + second to GLACIER_REGION with ID 1, etc. + Allowed values are: + 'remains_ice': ice runoff is sent to the river model as ice; this is a crude parameterization + of iceberg calving, and so is appropriate in regions where there is substantial + iceberg calving in reality + 'melted': ice runoff generated by the CLM physics (primarily due to snow capping) is melted + (generating a negative sensible heat flux) and runs off as liquid; this is appropriate in + regions that have little iceberg calving in reality. This can be important to avoid unrealistic + cooling of the ocean and consequent runaway sea ice growth. + Only applies when melt_non_icesheet_ice_runoff is .true. + """ + pass + + @namelist_item + def glacier_region_melt_behavior(self) -> List[str]: + """ + Treatment of ice melt for each glacier region (GLACIER_REGION in surface dataset). + First item corresponds to GLACIER_REGION with ID 0 in the surface dataset, + second to GLACIER_REGION with ID 1, etc. + Allowed values are: + 'replaced_by_ice': any melted ice runs off and is immediately replaced by solid ice; + this results in positive liquid runoff and negative ice runoff + 'remains_in_place': any melted ice remains in place as liquid until it refreezes; + thus, ice melt does not result in any runoff + IMPORTANT NOTE: Regions with the 'remains_in_place' behavior also do not + compute SMB (because negative SMB would be pretty much meaningless in + those regions). Thus, you cannot use this behavior where GLC is + operating. + Regions with the 'replaced_by_ice' behavior also compute SMB for the + vegetated column. + """ + pass + + @namelist_item + def glacier_region_rain_to_snow_behavior(self) -> List[str]: + """ + When rain-snow repartitioning / downscaling results in rain being converted to + snow, the behavior of the resulting additional snow. + First item corresponds to GLACIER_REGION with ID 0 in the surface dataset, + second to GLACIER_REGION with ID 1, etc. + Allowed values are: + 'converted_to_snow': rain is converted to snow, with a corresponding sensible + heat flux correction + 'runs_off': rather than being converted to snow, the excess rain runs off immediately + + IMPORTANT NOTE: Unlike other glacier_region*behavior namelist options, this + option applies to all landunit types in the given regions. + Only applies when repartition_rain_snow is .true. + """ + pass + + @namelist_group + class clm_humanindex_inparm(): + + @namelist_item + def calc_human_stress_indices(self) -> str: + """ + Human heat stress indices: + ALL = All indices will be calculated + FAST = A subset of indices will be calculated (will not include the computationally + expensive wet bulb calculation and associated indices) + NONE = No indices will be calculated + """ + pass + + @namelist_group + class clm_initinterp_inparm(): + + @namelist_item + def init_interp_method(self) -> str: + """ + Method to use for init_interp. Only applies when use_init_interp = .true. + + 'general': The general-purpose method that can be used when changing + grids, configurations, etc. This starts off with subgrid areas taken + from the surface dataset. + + 'use_finidat_areas': This starts off with subgrid areas taken from the + input finidat file. This is needed to achieve bit-for-bit results in a + coupled case (where areas in initialization impact initial fields sent + to the atmosphere) (but using the 'general' method will typically have + only a very minor impact on results in this case). For this method to + work, the input finidat file needs to be at the same resolution as the + current configuration. So this is a less general form of + init_interp. However, it can be used in cases where the only difference + is in internal memory allocation. In order to catch possible problems, + this uses a different algorithm for finding the input point for each + output point, which ensures that each active output point is associated + with exactly one input point with the same latitude, longitude and + type. This method requires (a) the same grid for input and output, + within roundoff; (b) any non-zero-weight point in the input must have + memory allocated for it in this grid cell in the output (this will be + satisfied if the point is non-zero-weight on the surface dataset or if + it's a point for which we allocate memory even for zero-weight points); + (c) any active point in the output (based on the surface dataset and + rules for determining active points) must have a matching point in this + grid cell in the input. (Note that this generally can NOT be used when + transitioning from a spinup run to a transient run, because spinup runs + typically have irrigation off and transient runs have irrigation on, and + the presence/absence of irrigation affects the subgrid structure; if it + weren't for that difference, then this option would be useful for this + use case.) + """ + pass + + @namelist_group + class clm_inparm(): + + @namelist_item + def albice(self) -> List[float]: + """ + Visible and Near-infrared albedo's for glacier ice + """ + pass + + @namelist_item + def anoxia(self) -> bool: + """ + If TRUE, reduce heterotrophic respiration according to available oxygen predicted by CH4 submodel. + """ + pass + + @namelist_item + def anoxia_wtsat(self) -> bool: + """ + If TRUE, weight calculation of oxygen limitation by the inundated fraction and diagnostic saturated column gas + concentration profile calculated in the CH4 submodel. Only applies if anoxia = TRUE. + (EXPERIMENTAL AND NOT FUNCTIONAL!) + (deprecated -- will be removed) + """ + pass + + @namelist_item + def atm_c13_filename(self) -> str: + """ + Filename with time series of atmospheric Delta C13 data, which use CMIP6 format. + variables in file are "time" and "delta13co2_in_air". time variable is in format: years since 1850-01-01 0:0:0.0. units are permil. + """ + pass + + @namelist_item + def atm_c14_filename(self) -> str: + """ + Filename with time series of atmospheric Delta C14 data. variables in file are "time" and + "Delta14co2_in_air". time variable is in format: years since 1850-01-01 0:0:0.0 units are permil. + """ + pass + + @namelist_item + def co2_ppmv(self) -> float: + """ + Atmospheric CO2 molar ratio (by volume) only used when co2_type==constant (umol/mol) + (Set by CCSM_CO2_PPMV) + """ + pass + + @namelist_item + def co2_type(self) -> str: + """ + Type of CO2 feedback. + constant = use the input co2_ppmv value + prognostic = use the prognostic value sent from the atmosphere + diagnostic = use the diagnostic value sent from the atmosphere + """ + pass + + @namelist_item + def create_crop_landunit(self) -> bool: + """ + If TRUE, separate the vegetated landunit into a crop landunit and a natural vegetation landunit + """ + pass + + @namelist_item + def dtime(self) -> int: + """ + Time step (seconds) + """ + pass + + @namelist_item + def fates_inventory_ctrl_filename(self) -> str: + """ + Full pathname to the inventory initialization control file. + (Required, if use_fates_inventory_init=T) + """ + pass + + @namelist_item + def fates_paramfile(self) -> str: + """ + Full pathname datafile with fates parameters + """ + pass + + @namelist_item + def fates_parteh_mode(self) -> int: + """ + Switch deciding which nutrient model to use in FATES. + """ + pass + + @namelist_item + def fatmlndfrc(self) -> str: + """ + Full pathname of land fraction data file. + """ + pass + + @namelist_item + def finidat(self) -> str: + """ + Full pathname of initial conditions file. If blank CLM will startup from arbitrary initial conditions. + """ + pass + + @namelist_item + def fsnowaging(self) -> str: + """ + SNICAR (SNow, ICe, and Aerosol Radiative model) snow aging data file name + """ + pass + + @namelist_item + def fsnowoptics(self) -> str: + """ + SNICAR (SNow, ICe, and Aerosol Radiative model) optical data file name + """ + pass + + @namelist_item + def fsurdat(self) -> str: + """ + Full pathname of surface data file. + """ + pass + + @namelist_item + def glc_do_dynglacier(self) -> bool: + """ + If TRUE, dynamically change areas and topographic heights over glacier points. + Only works when running with a non-stub glacier model. + """ + pass + + @namelist_item + def glc_snow_persistence_max_days(self) -> int: + """ + Number of days before one considers the perennially snow-covered point 'land ice' + (and thus capable of generating a positive surface mass balance for the glacier model). + This is meant to compensate for the fact that, with small values of h2osno_max, + the onset of a snow-capped state (and thus conversion to land ice) can occur in an + unrealistically short amount of time. + Thus, in general, large values of h2osno_max should have glc_snow_persistence_max_days = 0; + small values of h2osno_max should have glc_snow_persistence_max_days > 0. + """ + pass + + @namelist_item + def h2osno_max(self) -> float: + """ + Maximum snow depth in mm H2O equivalent. Additional mass gains will be capped when this depth + is exceeded. + Changes in this value should possibly be accompanied by changes in: + - nlevsno: larger values of h2osno_max should be accompanied by increases in nlevsno + - glc_snow_persistence_max_days: large values of h2osno_max should generally have + glc_snow_persistence_max_days = 0; small values of h2osno_max should generally have + glc_snow_persistence_max_days > 0. + """ + pass + + @namelist_item + def hist_empty_htapes(self) -> bool: + """ + If TRUE, indicates do NOT output any default history fields (requires you to use + hist_fincl* to set the exact output fields to use) + """ + pass + + @namelist_item + def hist_fincl1(self) -> List[str]: + """ + Fields to add to history tape series 1 + """ + pass + + @namelist_item + def hist_mfilt(self) -> int: + """ + Per tape series maximum number of time samples. + """ + pass + + @namelist_item + def hist_nhtfrq(self) -> int: + """ + Per tape series history write frequency. + positive means in time steps + 0=monthly + negative means hours + (i.e. 5 means every 24 time-steps and -24 means every day + """ + pass + + @namelist_item + def int_snow_max(self) -> int: + """ + Limit applied to integrated snowfall when determining changes in snow-covered + fraction during melt (mm H2O) + """ + pass + + @namelist_item + def irrigate(self) -> bool: + """ + If TRUE, irrigation will be active. + """ + pass + + @namelist_item + def maxpatch_glcmec(self) -> int: + """ + Number of multiple elevation defes over glacier points. + """ + pass + + @namelist_item + def maxpatch_pft(self) -> int: + """ + Max number of plant functional types in naturally vegetated landunit. + """ + pass + + @namelist_item + def n_melt_glcmec(self) -> float: + """ + SCA shape parameter for glc_mec (glacier multiple elevation def) columns + For most columns, n_melt is based on the standard deviation of 1km topography in the grid cell; + but glc_mec columns already account for subgrid topographic variability through their use of + multiple elevation defes; thus, to avoid double-accounting for topographic variability + in these columns, we use a fixed value of n_melt. + """ + pass + + @namelist_item + def nlevsno(self) -> int: + """ + Number of snow layers. + Values less than 5 are mainly useful for testing, and should not be used for science. + valid_values="3,4,5,6,7,8,9,10,11,12" + """ + pass + + @namelist_item + def nrevsn(self) -> str: + """ + Full pathname of master restart file for a branch run. (only used if RUN_TYPE=branch) + (Set with RUN_REFCASE and RUN_REFDATE) + """ + pass + + @namelist_item + def nsegspc(self) -> int: + """ + Number of segments per clump for decomposition + """ + pass + + @namelist_item + def override_bgc_restart_mismatch_dump(self) -> bool: + """ + Flag for overriding the crash that should occur if user tries to start the model from a restart file + made with a different version of the soil decomposition structure than is currently being used. + """ + pass + + @namelist_item + def override_nsrest(self) -> int: + """ + Override the start type from the driver: it can only be set to 3 meaning branch. + """ + pass + + @namelist_item + def paramfile(self) -> str: + """ + Full pathname datafile with plant function type (PFT) constants combined with + constants for biogeochem modules + """ + pass + + @namelist_item + def run_zero_weight_urban(self) -> bool: + """ + If TRUE, run all urban landunits everywhere where we have valid urban data. + This forces memory to be allocated and calculations to be run even for 0-weight urban points. + This has a substantial impact on memory use and performance, and should only be used + if you're interested in potential urban behavior globally. + """ + pass + + @namelist_item + def soil_layerstruct(self) -> str: + """ + 10SL_3.5m = standard CLM4 and CLM4.5 version + 23SL_3.5m = more vertical layers for permafrost simulations + 49SL_10m = 49 layer soil column, 10m of soil, 5 bedrock layers + 20SL_8.5m = 20 layer soil column, 8m of soil, 5 bedrock layers + """ + pass + + @namelist_item + def spinup_state(self) -> int: + """ + Flag for setting the state of the Accelerated decomposition spinup state for the BGC model. + 0 = normal model behavior; + 1 = AD spinup (standard) + 2 = AD spinup (accelerated spinup from Ricciuto, doesn't work for CNDV and not implemented for CN soil decomposition) + Entering and exiting spinup mode occurs automatically by comparing the namelist and restart file values for this variable. + NOTE: THIS CAN ONLY BE SET TO NON-ZERO WHEN BGC_MODE IS NOT SATELITE PHENOLOGY! + """ + pass + + @namelist_item + def subgridflag(self) -> int: + """ + Subgrid fluxes for snow + """ + pass + + @namelist_item + def suplnitro(self) -> str: + """ + Supplemental Nitrogen mode and for what type of vegetation it's turned on for. + In this mode Nitrogen is unlimited rather than prognosed and in general vegetation is + over-productive. + NONE = No vegetation types get supplemental Nitrogen + ALL = Supplemental Nitrogen is active for all vegetation types + """ + pass + + @namelist_item + def use_bedrock(self) -> bool: + """ + If TRUE, use variable soil depth. + If present on surface dataset, use depth to bedrock information to + specify spatially variable soil thickness. If not present, use bottom + of soil column (nlevsoi). + """ + pass + + @namelist_item + def use_c13(self) -> bool: + """ + Enable C13 model + """ + pass + + @namelist_item + def use_c13_timeseries(self) -> bool: + """ + Flag to use the atmospheric time series of C13 concentrations from natural abundance + and the Seuss Effect, rather than static values. + """ + pass + + @namelist_item + def use_c14(self) -> bool: + """ + Enable C14 model + """ + pass + + @namelist_item + def use_c14_bombspike(self) -> bool: + """ + Flag to use the atmospheric time series of C14 concentrations from bomb fallout and Seuss effect, + rather than natural abundance C14 (nominally set as 10^-12 mol C14 / mol C) + """ + pass + + @namelist_item + def use_century_decomp(self) -> bool: + """ + Use parameters for decomposition from the CENTURY Carbon model + Requires the CN or FATES model to work (either CN or CNDV). + """ + pass + + @namelist_item + def use_cn(self) -> bool: + """ + CLM Biogeochemistry mode : Carbon Nitrogen model (CN) + (or CLM45BGC if phys=clm4_5, vsoilc_centbgc='on', and clm4me='on') + """ + pass + + @namelist_item + def use_cndv(self) -> bool: + """ + CLM Biogeochemistry mode : Carbon Nitrogen with Dynamic Global Vegetation Model (CNDV) + (or CLM45BGCDV if phys=clm4_5, vsoilc_centbgc='on', and clm4me='on') + """ + pass + + @namelist_item + def use_crop(self) -> bool: + """ + Toggle to turn on the prognostic crop model + """ + pass + + @namelist_item + def use_dynroot(self) -> bool: + """ + Toggle to turn on the dynamic root model + """ + pass + + @namelist_item + def use_fates(self) -> bool: + """ + Toggle to turn on the FATES model (use_fates= '.true.' is EXPERIMENTAL NOT SUPPORTED!) + """ + pass + + @namelist_item + def use_fates_ed_prescribed_phys(self) -> bool: + """ + Toggle to turn on prescribed physiology (only relevant if FATES is being used). + """ + pass + + @namelist_item + def use_fates_ed_st3(self) -> bool: + """ + Toggle to turn on Static Stand Structure Mode (only relevant if FATES is being used). + (use_fates_ed_st3=".true." is EXPERIMENTAL NOT SUPPORTED! Nor is it Tested!) + """ + pass + + @namelist_item + def use_fates_inventory_init(self) -> bool: + """ + Toggle to turn on inventory initialization to startup FATES (only relevant if FATES is being used). + (use_fates_inventory_init=".true." is EXPERIMENTAL NOT SUPPORTED! Nor is it Tested!) + """ + pass + + @namelist_item + def use_fates_logging(self) -> bool: + """ + Toggle to turn on the logging module (only relevant if FATES is being used). + """ + pass + + @namelist_item + def use_fates_planthydro(self) -> bool: + """ + Toggle to turn on plant hydraulics (only relevant if FATES is on). + (use_fates_planthydro=".true." is EXPERIMENTAL NOT SUPPORTED! Nor is it Tested!) + """ + pass + + @namelist_item + def use_fates_spitfire(self) -> bool: + """ + Toggle to turn on spitfire module for modeling fire (only relevant if FATES is being used). + """ + pass + + @namelist_item + def use_fertilizer(self) -> bool: + """ + Toggle to turn on the prognostic fertilizer for crop model + """ + pass + + @namelist_item + def use_flexibleCN(self) -> bool: + """ + Allow the CN ratio to flexibly change with the simulation, rather than being fixed + """ + pass + + @namelist_item + def use_fun(self) -> bool: + """ + Turn the Fixation and Uptate of Nitrogen model version 2 (FUN2.0) + Requires the CN model to work (either CN or CNDV). + """ + pass + + @namelist_item + def use_grainproduct(self) -> bool: + """ + Toggle to turn on the 1-year grain product pool in the crop model + """ + pass + + @namelist_item + def use_hydrstress(self) -> bool: + """ + Toggle to turn on the plant hydraulic stress model + """ + pass + + @namelist_item + def use_init_interp(self) -> bool: + """ + If set to .true., interpinic will be called to interpolate the file given by finidat, + creating the output file specified by finidat_interp_dest. + This requires that finidat be non-blank. + """ + pass + + @namelist_item + def use_lai_streams(self) -> bool: + """ + Toggle to turn on use of LAI streams in place of the LAI on the surface dataset when using Satellite Phenology mode. + (EXPERIMENTAL and NOT tested) + """ + pass + + @namelist_item + def use_lch4(self) -> bool: + """ + Turn on methane model. Standard part of CLM45BGC model. + """ + pass + + @namelist_item + def use_luna(self) -> bool: + """ + Toggle to turn on the LUNA model, to effect Photosynthesis by leaf Nitrogen + LUNA operates on C3 and non-crop vegetation (see vcmax_opt for how other veg is handled) + LUNA: Leaf Utilization of Nitrogen for Assimilation + """ + pass + + @namelist_item + def use_mexicocity(self) -> bool: + """ + Toggle for mexico city specific logic. + """ + pass + + @namelist_item + def use_nguardrail(self) -> bool: + """ + Apply the guardrail for leaf-Nitrogen that ensures it doesn't go negative or too small + """ + pass + + @namelist_item + def use_nitrif_denitrif(self) -> bool: + """ + Nitrification/denitrification splits the prognostic mineral N pool into two + mineral N pools: NO3 and NH4, and includes the transformations between them. + Requires the CN model to work (either CN or CNDV). + """ + pass + + @namelist_item + def use_soil_moisture_streams(self) -> bool: + """ + Toggle to turn on use of input prescribed soil moisture streams rather than have CLM prognose it (EXPERIMENTAL) + """ + pass + + @namelist_item + def use_vancouver(self) -> bool: + """ + Toggle for vancouver specific logic. + """ + pass + + @namelist_item + def use_vertsoilc(self) -> bool: + """ + Turn on vertical soil carbon. + Requires the CN or FATES model to work (either CN or CNDV). + """ + pass + + @namelist_item + def use_vichydro(self) -> bool: + """ + Toggle to turn on the VIC hydrologic parameterizations + (vichydro=".true." is EXPERIMENTAL NOT SUPPORTED!) + """ + pass + + @namelist_group + class clm_nitrogen(): + + @namelist_item + def carbon_resp_opt(self) -> int: + """ + Carbon respiration option to burn off carbon when CN ratio is too high; do NOT use when FUN is on (EXPERIMENTAL and NOT tested) + """ + pass + + @namelist_item + def CN_evergreen_phenology_opt(self) -> int: + """ + Evergreen phenology option for CNPhenology (EXPERIMENTAL and NOT tested) + """ + pass + + @namelist_item + def CN_partition_opt(self) -> int: + """ + Partition option for flexible-CN (EXPERIMENTAL and NOT tested) + CN_partition_opt = 1 + """ + pass + + @namelist_item + def CN_residual_opt(self) -> int: + """ + Residual option for flexible-CN (EXPERIMENTAL and NOT tested) + """ + pass + + @namelist_item + def CNratio_floating(self) -> bool: + """ + Flexible CN ratio used for Phenology (EXPERIMENTAL and NOT tested) + """ + pass + + @namelist_item + def downreg_opt(self) -> bool: + """ + GPP downregulation for use_flexibleCN option (EXPERIMENTAL and NOT tested) + """ + pass + + @namelist_item + def lnc_opt(self) -> bool: + """ + How LUNA and Photosynthesis (if needed) will get Leaf nitrogen content + lnc_opt = true get from leaf N from CN model + lnc_opt = false get based on LAI and fixed CN ratio from parameter file + """ + pass + + @namelist_item + def MM_Nuptake_opt(self) -> bool: + """ + Michaelis Menten nitrogen uptake kinetics + """ + pass + + @namelist_item + def nscalar_opt(self) -> bool: + """ + Michaelis Menten nitrogen limitation for use_flexibleCN option (EXPERIMENTAL and NOT tested) + """ + pass + + @namelist_item + def plant_ndemand_opt(self) -> int: + """ + Plant nitrogen demand for use_flexibleCN option (EXPERIMENTAL and NOT tested) + valid_values="0,1,2,3" + """ + pass + + @namelist_item + def reduce_dayl_factor(self) -> bool: + """ + Reduce day length factor (NOT implemented) + """ + pass + + @namelist_item + def substrate_term_opt(self) -> bool: + """ + Michaelis Menten substrate limitation for use_flexibleCN option (EXPERIMENTAL and NOT tested) + """ + pass + + @namelist_item + def temp_scalar_opt(self) -> bool: + """ + Michaelis Menten substrate limitation for use_flexibleCN option (EXPERIMENTAL and NOT tested) + """ + pass + + @namelist_item + def vcmax_opt(self) -> int: + """ + Vcmax calculation for Photosynthesis + vcmax_opt = 4 As for vcmax_opt=0, but using leafN, and exponential if tree (EXPERIMENTAL NOT TESTED!) + vcmax_opt = 3 Based on leafN and VCAD (used with Luna for crop and C4 vegetation) + vcmax_opt = 0 Based on canopy top and foilage Nitrogen limitation factor from params file (clm4.5) + """ + pass + + @namelist_group + class clm_snowhydrology_inparm(): + + @namelist_item + def lotmp_snowdensity_method(self) -> str: + """ + Snow density method to use for low temperatures (below -15C) + TruncatedAnderson1976 -- Truncate the Anderson-1976 equation at the value for -15C + Slater2017 ------------- Use equation from Slater that increases snow density for very cold temperatures (Arctic, Antarctic) + """ + pass + + @namelist_item + def overburden_compress_Tfactor(self) -> float: + """ + Snow compaction overburden exponential factor (1/K) + Not used for snow_overburden_compaction_method=Vionnet2012 + """ + pass + + @namelist_item + def reset_snow(self) -> bool: + """ + If set to .true., then reset the snow pack over non-glacier columns to a small value. + This is useful when transitioning from a spinup under one set of atmospheric forcings + to a run under a different set of atmospheric forcings: By resetting too-large snow packs, + we make it more likely that points will remain only seasonally snow-covered under the new + atmospheric forcings. (This is particularly true in a coupled run, where starting with a + too-large snow pack can cool the atmosphere, thus maintaining the too-large snow pack.) + + WARNING: Setting this to .true. will break water conservation for approximately the first + day of the new run. This is by design: The excess snow is completely removed from the system. + """ + pass + + @namelist_item + def reset_snow_glc(self) -> bool: + """ + If set to .true., then reset the snow pack over glacier columns to a small value. + This is useful when transitioning from a spinup under one set of atmospheric forcings + to a run under a different set of atmospheric forcings: By resetting too-large snow packs, + we make it more likely that points will remain only seasonally snow-covered under the new + atmospheric forcings. (This is particularly true in a coupled run, where starting with a + too-large snow pack can cool the atmosphere, thus maintaining the too-large snow pack.) + + See also reset_snow_glc_ela, which controls the elevation below which + glacier columns are reset. + + WARNING: Setting this to .true. will break water conservation for approximately the first + day of the new run. This is by design: The excess snow is completely removed from the system. + + WARNING: This variable is intended for short test runs, and generally + should not be used for scientific production runs. By resetting snow + below a given elevation, you risk forcing the system to evolve + differently in areas below and above reset_snow_glc_ela. + """ + pass + + @namelist_item + def reset_snow_glc_ela(self) -> float: + """ + Only relevant if reset_snow_glc is .true. + + When resetting snow pack over glacier columns, one can choose to do this over all glacier + columns, or only those below a certain elevation. A typical use case is to reset only those + columns that have a seasonal snow pack in the real world, i.e. SMB less than 0, also known as + the equilibrium line altitude (ELA). This parameter sets a single global ELA value. By + setting this parameter to a large value (i.e. 10000 m), all glacier columns will be reset. + + WARNING: This variable is intended for short test runs, and generally + should not be used for scientific production runs. By resetting snow + below a given elevation, you risk forcing the system to evolve + differently in areas below and above reset_snow_glc_ela. + """ + pass + + @namelist_item + def snow_overburden_compaction_method(self) -> str: + """ + Method used to compute snow overburden compaction + Anderson1976 -- older method, default in CLM45 + Vionnet2012 --- newer method, default in CLM50 + """ + pass + + @namelist_item + def upplim_destruct_metamorph(self) -> float: + """ + Upper Limit on Destructive Metamorphism Compaction [kg/m3] + """ + pass + + @namelist_item + def wind_dependent_snow_density(self) -> float: + """ + If TRUE, the density of new snow depends on wind speed, and there is also + wind-dependent snow compaction. + """ + pass + + @namelist_group + class clm_soilhydrology_inparm(): + + @namelist_item + def h2osfcflag(self) -> int: + """ + If surface water is active or not + (deprecated -- will be removed) + """ + pass + + @namelist_item + def origflag(self) -> int: + """ + Use original CLM4 soil hydraulic properties + (deprecated -- will be removed) + """ + pass + + @namelist_group + class clm_soilstate_inparm(): + + @namelist_item + def organic_frac_squared(self) -> bool: + """ + If TRUE, square the organic fraction when it's used (as was done in CLM4.5) + Otherwise use the fraction straight up (the default for CLM5.0) + """ + pass + + @namelist_group + class clmu_inparm(): + + @namelist_item + def building_temp_method(self) -> int: + """ + 0 = simpler method (clm4_5) + 1 = prognostic calculation of interior building temp (clm5_0) + """ + pass + + @namelist_item + def urban_hac(self) -> str: + """ + Turn urban air conditioning/heating ON or OFF and add wasteheat: + OFF = Air conditioning/heating is OFF in buildings, internal temperature allowed to float freely + ON = Air conditioning/heating is ON in buildings, internal temperature constrained + ON_WASTEHEAT = Air conditioning/heating is ON and waste-heat sent to urban canyon + """ + pass + + @namelist_item + def urban_traffic(self) -> bool: + """ + If TRUE, urban traffic flux will be activated (Currently NOT implemented). + """ + pass + + @namelist_group + class cnmresp_inparm(): + + @namelist_item + def br_root(self) -> float: + """ + CN Maintenence Respiration base rate for roots + (if NOT set, use the value for br_mr on the params file) + """ + pass + + @namelist_group + class cn_general(): + + @namelist_item + def dribble_crophrv_xsmrpool_2atm(self) -> bool: + """ + Harvest the XSMR pool at crop harvest time to the atmosphere slowly at an exponential rate + """ + pass + + @namelist_item + def reseed_dead_plants(self) -> bool: + """ + Flag to reseed any dead plants on startup from reading the initial conditions file + """ + pass + + @namelist_group + class cnfire_inparm(): + + @namelist_item + def fire_method(self) -> str: + """ + The method type to use for CNFire + + nofire: Turn fire effects off + li2014qianfrc: Reference paper Li, et. al.(2014) tuned with QIAN atmospheric forcing + li2016crufrc: Reference paper Li, et. al.(2016) tuned with CRU-NCEP atmospheric forcing + """ + pass + + @namelist_group + class cnphenology(): + + @namelist_item + def initial_seed_at_planting(self) -> float: + """ + Initial seed Carbon to use at planting + (only used when CN is on as well as crop) + """ + pass + + @namelist_group + class cnprecision_inparm(): + + @namelist_item + def ccrit(self) -> float: + """ + Critical threshold for truncation of Carbon (truncate Carbon states + to zero below this value) + """ + pass + + @namelist_item + def cnegcrit(self) -> float: + """ + Critical threshold of negative Carbon to die + (abort when Carbon states are below this value) + """ + pass + + @namelist_item + def ncrit(self) -> float: + """ + Critical threshold for truncation of Nitrogen + (truncate Nitrogen states to zero below this value) + """ + pass + + @namelist_item + def nnegcrit(self) -> float: + """ + Critical threshold of negative Nitrogen to die + (abort when Nitrogen states are below this value) + """ + pass + + @namelist_group + class cnvegcarbonstate(): + + @namelist_item + def initial_vegC(self) -> float: + """ + How much Carbon to initialize vegetation pools (leafc/frootc and storage) + to when -- Michaelis Menten nitrogen uptake kinetics is on + """ + pass + + @namelist_group + class crop(): + + @namelist_item + def baset_latvary_intercept(self) -> float: + """ + Only used when baset_mapping == varytropicsbylat + Intercept at zero latitude to add to baset from the PFT parameter file + """ + pass + + @namelist_item + def baset_latvary_slope(self) -> float: + """ + Only used when baset_mapping == varytropicsbylat + Slope with latitude in degrees to vary tropical baset by + """ + pass + + @namelist_item + def baset_mapping(self) -> str: + """ + Type of mapping to use for base temperature for prognostic crop model + constant = Just use baset from the PFT parameter file + varytropicsbylat = Vary the tropics by latitude + """ + pass + + @namelist_group + class dynamic_subgrid(): + + @namelist_item + def do_harvest(self) -> bool: + """ + If TRUE, apply harvest from flanduse_timeseries file. + (Only valid for transient runs, where there is a flanduse_timeseries file.) + (Also, only valid for use_cn = true.) + """ + pass + + @namelist_item + def do_transient_crops(self) -> bool: + """ + If TRUE, apply transient crops from flanduse_timeseries file. + (Only valid for transient runs, where there is a flanduse_timeseries file.) + """ + pass + + @namelist_item + def do_transient_pfts(self) -> bool: + """ + If TRUE, apply transient natural PFTs from flanduse_timeseries file. + (Only valid for transient runs, where there is a flanduse_timeseries file.) + """ + pass + + @namelist_item + def flanduse_timeseries(self) -> str: + """ + Full pathname of time varying landuse data file. This causes the land-use types of + the initial surface dataset to vary over time. + """ + pass + + @namelist_group + class friction_velocity(): + + @namelist_item + def zetamaxstable(self) -> float: + """ + The maximum value to use for zeta under stable conditions + """ + pass + + @namelist_group + class irrigation_inparm(): + + @namelist_item + def irrig_depth(self) -> float: + """ + Soil depth to which we measure for irrigation (m) + """ + pass + + @namelist_item + def irrig_length(self) -> int: + """ + Desired amount of time to irrigate per day (sec). + Actual time may differ if this is not a multiple of dtime. + """ + pass + + @namelist_item + def irrig_min_lai(self) -> float: + """ + Minimum leaf area index for irrigation to occur + """ + pass + + @namelist_item + def irrig_river_volume_threshold(self) -> float: + """ + Threshold for river water volume below which irrigation is shut off (as a fraction of available river water), if limit_irrigation_if_rof_enabled is .true. + A threshold of 0 means allow all river water to be used; + a threshold of 0.1 means allow 90% of the river volume to be used; etc. + """ + pass + + @namelist_item + def irrig_start_time(self) -> int: + """ + Time of day to check whether we need irrigation, seconds (0 = midnight). + We start applying the irrigation in the time step FOLLOWING this time. + """ + pass + + @namelist_item + def irrig_target_smp(self) -> float: + """ + Target soil matric potential for irrigation (mm). + When we irrigate, we aim to bring the total soil moisture in the top (irrig_depth) m of soil up to this level. + """ + pass + + @namelist_item + def irrig_threshold_fraction(self) -> float: + """ + Determines soil moisture threshold at which we irrigate. + If h2osoi_liq_wilting_point is the soil moisture level at wilting point and + h2osoi_liq_target is the soil moisture level at the target irrigation level + (given by irrig_target_smp), then the threshold at which we irrigate is + h2osoi_liq_wilting_point + + irrig_threshold_fraction*(h2osoi_liq_target - h2osoi_liq_wilting_point) + A value of 1 means that we irrigate whenever soil moisture falls below the target. + A value of 0 means that we only irrigate when soil moisture falls below the wilting point. + """ + pass + + @namelist_item + def limit_irrigation_if_rof_enabled(self) -> bool: + """ + If TRUE, limit irrigation when river storage drops below a threshold. + Only applies if using an active runoff (ROF) model; otherwise, river storage-based limitation + is turned off regardless of the setting of this namelist variable. + """ + pass + + @namelist_group + class lai_streams(): + + @namelist_item + def lai_mapalgo(self) -> str: + """ + Mapping method from LAI input file to the model resolution + bilinear = bilinear interpolation + nn = nearest neighbor + nnoni = nearest neighbor on the "i" (longitude) axis + nnonj = nearest neighbor on the "j" (latitude) axis + spval = set to special value + copy = copy using the same indices + """ + pass + + @namelist_item + def lai_tintalgo(self) -> str: + """ + Time interpolation method to use with LAI streams + """ + pass + + @namelist_item + def model_year_align_lai(self) -> int: + """ + Simulation year that aligns with stream_year_first_lai value + """ + pass + + @namelist_item + def stream_fldfilename_lai(self) -> str: + """ + Filename of input stream data for LAI + """ + pass + + @namelist_item + def stream_year_first_lai(self) -> int: + """ + First year to loop over for LAI data + """ + pass + + @namelist_item + def stream_year_last_lai(self) -> int: + """ + Last year to loop over for LAI data + """ + pass + + @namelist_group + class lifire_inparm(): + + @namelist_item + def boreal_peatfire_c(self) -> float: + """ + boreal peat fires (/hr) + """ + pass + + @namelist_item + def bt_max(self) -> float: + """ + Saturation BTRAN for ignition (0-1) + """ + pass + + @namelist_item + def bt_min(self) -> float: + """ + Critical BTRAN for ignition (0-1) + """ + pass + + @namelist_item + def cli_scale(self) -> float: + """ + Global constant for deforestation fires (/day) + """ + pass + + @namelist_item + def cmb_cmplt_fact(self) -> List[float]: + """ + Combustion completeness factor (for litter and CWD[Course Woody Debris]) (unitless) + """ + pass + + @namelist_item + def cropfire_a1(self) -> float: + """ + Scalar for cropfire (/hr) + """ + pass + + @namelist_item + def lfuel(self) -> float: + """ + Lower threshold for fuel mass needed for ignition + """ + pass + + @namelist_item + def non_boreal_peatfire_c(self) -> float: + """ + non-boreal peat fires (/hr) + """ + pass + + @namelist_item + def occur_hi_gdp_tree(self) -> float: + """ + Fire occurance for high GDP areas that are tree dominated (fraction) + """ + pass + + @namelist_item + def pot_hmn_ign_counts_alpha(self) -> float: + """ + Potential human ignition counts (/person/month) + """ + pass + + @namelist_item + def rh_hgh(self) -> float: + """ + Saturation RH for ignition (0-100) + """ + pass + + @namelist_item + def rh_low(self) -> float: + """ + Critical RH for ignition (0-100) + """ + pass + + @namelist_item + def ufuel(self) -> float: + """ + Upper threshold for fuel mass needed for ignition + """ + pass + + @namelist_group + class light_streams(): + + @namelist_item + def lightng_tintalgo(self) -> str: + """ + Time interpolation method to use with Lightning streams + """ + pass + + @namelist_item + def lightngmapalgo(self) -> str: + """ + Mapping method from Lightning input file to the model resolution + bilinear = bilinear interpolation + nn = nearest neighbor + nnoni = nearest neighbor on the "i" (longitude) axis + nnonj = nearest neighbor on the "j" (latitude) axis + spval = set to special value + copy = copy using the same indices + """ + pass + + @namelist_item + def model_year_align_lightng(self) -> int: + """ + Simulation year that aligns with stream_year_first_lightng value + """ + pass + + @namelist_item + def stream_fldfilename_lightng(self) -> str: + """ + Filename of input stream data for Lightning + """ + pass + + @namelist_item + def stream_year_first_lightng(self) -> int: + """ + First year to loop over for Lightning data + """ + pass + + @namelist_item + def stream_year_last_lightng(self) -> int: + """ + Last year to loop over for Lightning data + """ + pass + + @namelist_group + class lnd2atm_inparm(): + + @namelist_item + def melt_non_icesheet_ice_runoff(self) -> bool: + """ + If TRUE, ice runoff generated from non-glacier columns and glacier columns outside icesheet regions + is converted to liquid, with an appropriate sensible heat flux. + That is, the atmosphere (rather than the ocean) melts the ice. + (Exception: ice runoff generated to ensure conservation with dynamic landunits remains as ice.) + """ + pass + + @namelist_group + class luna(): + + @namelist_item + def jmaxb1(self) -> float: + """ + ??? + """ + pass + + @namelist_group + class ndepdyn_nml(): + + @namelist_item + def model_year_align_ndep(self) -> int: + """ + Simulation year that aligns with stream_year_first_ndep value + """ + pass + + @namelist_item + def ndep_taxmode(self) -> str: + """ + Time interpolation mode to determine how to handle data before and after the times in the file + cycle = Always cycle over the data + extend = Use the first time before the available data, and use the last time after the available data + limit = Only use the data within the times available -- abort if the model tries to go outside it + """ + pass + + @namelist_item + def ndep_varlist(self) -> str: + """ + Colon delimited list of variables to read from the streams file for nitrogen deposition + (Normally just read the single variable NDEP_year or NDEP_month) + """ + pass + + @namelist_item + def ndepmapalgo(self) -> str: + """ + Mapping method from Nitrogen deposition input file to the model resolution + bilinear = bilinear interpolation + nn = nearest neighbor + nnoni = nearest neighbor on the "i" (longitude) axis + nnonj = nearest neighbor on the "j" (latitude) axis + spval = set to special value + copy = copy using the same indices + """ + pass + + @namelist_item + def stream_fldfilename_ndep(self) -> str: + """ + Filename of input stream data for Nitrogen Deposition + """ + pass + + @namelist_item + def stream_year_first_ndep(self) -> int: + """ + First year to loop over for Nitrogen Deposition data + """ + pass + + @namelist_item + def stream_year_last_ndep(self) -> int: + """ + Last year to loop over for Nitrogen Deposition data + """ + pass + + @namelist_group + class nitrif_inparm(): + + @namelist_item + def denitrif_nitrateconc_coefficient(self) -> float: + """ + Multiplier for nitrate concentration for max denitrification rates + (ONLY used if use_nitrif_denitrif is enabled) + """ + pass + + @namelist_item + def denitrif_nitrateconc_exponent(self) -> float: + """ + Exponent power for nitrate concentrationfor max denitrification rates + (ONLY used if use_nitrif_denitrif is enabled) + """ + pass + + @namelist_item + def denitrif_respiration_coefficient(self) -> float: + """ + Multiplier for heterotrophic respiration for max denitrification rates + (ONLY used if use_nitrif_denitrif is enabled) + """ + pass + + @namelist_item + def denitrif_respiration_exponent(self) -> float: + """ + Exponent power for heterotrophic respiration for max denitrification rates + (ONLY used if use_nitrif_denitrif is enabled) + """ + pass + + @namelist_item + def k_nitr_max(self) -> float: + """ + Maximum nitrification rate constant (1/s) + (ONLY used if use_nitrif_denitrif is enabled) + """ + pass + + @namelist_group + class photosyns_inparm(): + + @namelist_item + def leafresp_method(self) -> int: + """ + Leaf maintencence respiration for canopy top at 25C method to use + + 0 Scaled by vcmax25top + 1 Ryan 1991 + 2 Atkin 2015 + """ + pass + + @namelist_item + def light_inhibit(self) -> bool: + """ + Switch to inihibit photosynthesis in daytime + Lloyd et al. 2010, & Metcalfe et al. 2012 + """ + pass + + @namelist_item + def modifyphoto_and_lmr_forcrop(self) -> bool: + """ + Modify photosynthesis and leaf maintence respiration for crop + """ + pass + + @namelist_item + def rootstem_acc(self) -> bool: + """ + Switch to turn on root and stem respiratory acclimation + Atkin, Fisher et al. (2008) and Lombardozzi et al. (2015) + """ + pass + + @namelist_item + def stomatalcond_method(self) -> str: + """ + Stomatal conductance model method to use + + Ball-Berry1987 --- Ball Berry 1987 methodology + Medlyn2011 ------- Medlyn 2011 methodology + """ + pass + + @namelist_group + class popd_streams(): + + @namelist_item + def model_year_align_popdens(self) -> int: + """ + Simulation year that aligns with stream_year_first_popdens value + """ + pass + + @namelist_item + def popdens_tintalgo(self) -> str: + """ + Time interpolation method to use with human population density streams + """ + pass + + @namelist_item + def popdensmapalgo(self) -> str: + """ + Mapping method from human population density input file to the model resolution + bilinear = bilinear interpolation + nn = nearest neighbor + nnoni = nearest neighbor on the "i" (longitude) axis + nnonj = nearest neighbor on the "j" (latitude) axis + spval = set to special value + copy = copy using the same indices + """ + pass + + @namelist_item + def stream_fldfilename_popdens(self) -> int: + """ + Filename of input stream data for human population density + """ + pass + + @namelist_item + def stream_year_first_popdens(self) -> int: + """ + First year to loop over for human population density data + """ + pass + + @namelist_item + def stream_year_last_popdens(self) -> int: + """ + Last year to loop over for human population density data + """ + pass + + @namelist_group + class rooting_profile_inparm(): + + @namelist_item + def rooting_profile_method_carbon(self) -> int: + """ + Index of rooting profile for carbon + + Changes rooting profile from Zeng 2001 double exponential (0) to + Jackson 1996 single exponential (1) to Koven uniform exponential (2). + """ + pass + + @namelist_item + def rooting_profile_method_water(self) -> int: + """ + Index of rooting profile for water + + Changes rooting profile from Zeng 2001 double exponential (0) to + Jackson 1996 single exponential (1) to Koven uniform exponential (2). + """ + pass + + @namelist_group + class soil_moisture_streams(): + + @namelist_item + def model_year_align_soilm(self) -> int: + """ + Simulation year that aligns with stream_year_first_soilm value + """ + pass + + @namelist_item + def soilm_offset(self) -> int: + """ + Offset in time coordinate for soil moisture streams (sec) + """ + pass + + @namelist_item + def soilm_tintalgo(self) -> str: + """ + Time interpolation method to use for prescribed soil moisture streams data + """ + pass + + @namelist_item + def stream_fldfilename_soilm(self) -> str: + """ + Filename of input stream data for prescribed soil moisture streams data + """ + pass + + @namelist_item + def stream_year_first_soilm(self) -> int: + """ + First year to loop over for prescribed soil moisture streams data + """ + pass + + @namelist_item + def stream_year_last_soilm(self) -> str: + """ + Last year to loop over for prescribed soil moisture streams data + """ + pass + + @namelist_group + class soil_resis_inparm(): + + @namelist_item + def soil_resis_method(self) -> int: + """ + Index of evaporative resistance method. + + Changes soil evaporative resistance method from Sakaguchi and Zeng + 2009 Beta function (0) to Swenson and Lawrence 2014 dry surface layer + formulation (1). + """ + pass + + @namelist_group + class soilhydrology_inparm(): + + @namelist_item + def baseflow_scalar(self) -> float: + """ + Scalar multiplier for base flow rate + (ONLY used if lower_boundary_condition is not aquifer or table) + """ + pass + + @namelist_group + class soilwater_movement_inparm(): + + @namelist_item + def dtmin(self) -> float: + """ + minimum time step length (seconds) for adaptive time stepping in richards equation + """ + pass + + @namelist_item + def expensive(self) -> int: + """ + ??? + """ + pass + + @namelist_item + def flux_calculation(self) -> int: + """ + ??? + """ + pass + + @namelist_item + def inexpensive(self) -> int: + """ + ??? + """ + pass + + @namelist_item + def lower_boundary_condition(self) -> int: + """ + Index of lower boundary condition for Richards equation. + + lower_boundary_condition = 1 : flux lower boundary condition (use with soilwater_movement_method=adaptive time stepping) + lower_boundary_condition = 2 : zero-flux lower boundary condition (use with soilwater_movement_method=adaptive time stepping) + lower_boundary_condition = 3 : water table head-based lower boundary condition w/ aquifer layer. (use with soilwater_movement_method=adaptive time stepping) + lower_boundary_condition = 4 : 11-layer solution w/ aquifer layer (only used with soilwater_movement_method=Zeng&Decker 2009) + + TODO(bja, 2015-09) these should be strings so they have meaningful names instead of ints. + """ + pass + + @namelist_item + def soilwater_movement_method(self) -> int: + """ + Index of solution method of Richards equation. + + Change method for richards equation solution and boundary + conditions. + + CLM 4.5 - soilwater_movement_method = 0 (Zeng and Decker, 2009, method). + CLM 5.0 - soilwater_movement_method = 1 (adaptive time stepping moisture form from Martyn Clark). + + 1 (adaptive time stepping moisture form + """ + pass + + @namelist_item + def upper_boundary_condition(self) -> int: + """ + Index of upper boundary condition for Richards equation. + """ + pass + + @namelist_item + def verySmall(self) -> float: + """ + a very small number: used to check for sub step completion for adaptive time stepping in richards equation + """ + pass + + @namelist_item + def xTolerLower(self) -> float: + """ + tolerance to double length of substep for adaptive time stepping in richards equation + """ + pass + + @namelist_item + def xTolerUpper(self) -> float: + """ + tolerance to halve length of substep for adaptive time stepping in richards equation + """ + pass + + @namelist_group + class urbantv_streams(): + + @namelist_item + def model_year_align_urbantv(self) -> int: + """ + Simulation year that aligns with stream_year_first_urbantv value + """ + pass + + @namelist_item + def stream_fldfilename_urbantv(self) -> str: + """ + Filename of input stream data for urban time varying + """ + pass + + @namelist_item + def stream_year_first_urbantv(self) -> int: + """ + First year to loop over for urban time varying data + """ + pass + + @namelist_item + def stream_year_last_urbantv(self) -> int: + """ + Last year to loop over for urban time varying data + """ + pass + + @namelist_item + def urbantvmapalgo(self) -> str: + """ + Mapping method from urban time varying input file to the model resolution + bilinear = bilinear interpolation + nn = nearest neighbor + nnoni = nearest neighbor on the "i" (longitude) axis + nnonj = nearest neighbor on the "j" (latitude) axis + spval = set to special value + copy = copy using the same indices + """ + pass \ No newline at end of file diff --git a/namelist_generator/clm5nl/structures/utils.py b/namelist_generator/clm5nl/structures/utils.py new file mode 100644 index 0000000000..8665dfb1d9 --- /dev/null +++ b/namelist_generator/clm5nl/structures/utils.py @@ -0,0 +1,100 @@ +from collections import OrderedDict +from io import StringIO + +def lnd_nl_groups() -> list: + """ + Namelist groups sorted in the same order as the lnd_in namelist generated by CLM5. + """ + return ["clm_inparm", + "ndepdyn_nml", + "popd_streams", + "urbantv_streams", + "light_streams", + "soil_moisture_streams", + "lai_streams", + "atm2lnd_inparm", + "lnd2atm_inparm", + "clm_canopyhydrology_inparm", + "cnphenology", + "clm_soilhydrology_inparm", + "dynamic_subgrid", + "cnvegcarbonstate", + "finidat_consistency_checks", + "dynpft_consistency_checks", + "clm_initinterp_inparm", + "century_soilbgcdecompcascade", + "soilhydrology_inparm", + "luna", + "friction_velocity", + "mineral_nitrogen_dynamics", + "soilwater_movement_inparm", + "rooting_profile_inparm", + "soil_resis_inparm", + "bgc_shared", + "canopyfluxes_inparm", + "aerosol", + "clmu_inparm", + "clm_soilstate_inparm", + "clm_nitrogen", + "clm_snowhydrology_inparm", + "cnprecision_inparm", + "clm_glacier_behavior", + "crop", + "irrigation_inparm", + "ch4par_in", + "clm_humanindex_inparm", + "cnmresp_inparm", + "photosyns_inparm", + "cnfire_inparm", + "cn_general", + "nitrif_inparm", + "lifire_inparm", + "ch4finundated", + "clm_canopy_inparm"] + +def nl_to_str(nl_obj: dict, group_name: str = None, sort_groups = False) -> str: + fortran_nml = StringIO() + + def convert_nl_group(group_name: str, params: dict): + nonlocal fortran_nml + p = OrderedDict(sorted(params.items(), key=lambda t: t[0])) + fortran_nml.write("&" + group_name + "\n") + for key, value in p.items(): + new_value = to_fortran_type(value) + fortran_nml.write(" {} = {}\n".format(key, new_value)) + fortran_nml.write("/\n") + + if group_name is None: + if sort_groups: + nl = OrderedDict(sorted(nl_obj.items(), key=lambda t: t[0])) + for group, params in nl.items(): + convert_nl_group(group, params) + else: + groups_added = [] + for group in lnd_nl_groups(): + if group in nl_obj: + groups_added.append(group) + convert_nl_group(group, nl_obj[group]) + else: + convert_nl_group(group, {}) + if len(groups_added) < len(nl_obj.keys()): + for group, params in nl_obj.items(): + if group not in groups_added: + convert_nl_group(group, params) + elif group_name in nl_obj: + convert_nl_group(group_name, nl_obj[group_name]) + return fortran_nml.getvalue() + +def to_fortran_type(obj) -> str: + if isinstance(obj, bool): + value = ".true." if obj else ".false." + elif isinstance(obj, str): + value = "'{}'".format(obj) + elif isinstance(obj, list): + if isinstance(obj[0], str): + value = ", ".join("'{}'".format(s) for s in obj) + else: + value = ", ".join(str(s) for s in obj) + else: + value = str(obj) + return value \ No newline at end of file diff --git a/namelist_generator/model_params_example.yaml b/namelist_generator/model_params_example.yaml new file mode 100644 index 0000000000..9bd1a32973 --- /dev/null +++ b/namelist_generator/model_params_example.yaml @@ -0,0 +1,63 @@ +%YAML 1.2 +--- +file_version: 1.0 +general_options: + bgc_mode: "bgc" + clm_accelerated_spinup: "off" + clm_start_type: "arb_ic" + co2_ppmv: 367.0 + co2_type: "constant" + crop: 1 + drydep: False + dtime: None + dynamic_vegetation: 0 + fire_emis: False + GLC_TWO_WAY_COUPLING: False + glc_nec: 10 + ignore_ic_date: False + ignore_ic_year: False + l_ncpl: 48 + light_res: "default" + lnd_frac: "/p/scratch/nrw_test_case/domain.lnd.300x300_NRW_300x300_NRW.190619.nc" + lnd_tuning_mode: "clm5_0_CRUv7" + mask: None + megan: True + nrevsn: None + override_nsrest: None + res: "UNSET" + sim_year: "2000" + sim_year_range: "constant" + ssp_rcp: "hist" + start_ymd: 20170101 + use_case: None + use_dynroot: False + use_init_interp: True + vichydro: 0 + +lnd_in: + # files + finidat: '/p/scratch/nrw_test_case/FSpinup_300x300_NRW.clm2.r.2222-01-01-00000.nc' + fsnowaging: '/p/scratch/nrw_test_case/snicar_drdt_bst_fit_60_c070416.nc' + fsnowoptics: '/p/scratch/nrw_test_case/snicar_optics_5bnd_c090915.nc' + fsurdat: '/p/scratch/nrw_test_case/surfdata_300x300_NRW_hist_78pfts_CMIP6_simyr2000_c190619.nc' + paramfile: '/p/scratch/nrw_test_case/clm5_params.c171117.nc' + stream_fldfilename_ndep: '/p/scratch/nrw_test_case/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc' + stream_fldfilename_popdens: '/p/scratch/nrw_test_case/clmforc.Li_2017_HYDEv3.2_CMIP6_hdm_0.5x0.5_AVHRR_simyr1850-2016_c180202.nc' + stream_fldfilename_urbantv: '/p/scratch/nrw_test_case/CLM50_tbuildmax_Oleson_2016_0.9x1.25_simyr1849-2106_c160923.nc' + stream_fldfilename_lightng: '/p/scratch/nrw_test_case/clmforc.Li_2012_climo1995-2011.T62.lnfm_Total_c140423.nc' + stream_fldfilename_ch4finundated: '/p/scratch/nrw_test_case/finundated_inversiondata_0.9x1.25_c170706.nc' + + #clm_inparm: + co2_ppmv: 367.0 + hist_empty_htapes: True + hist_fincl1: ['TLAI','TSOI','TOTSOMC','TOTVEGC','TOTECOSYSC'] + hist_mfilt: 365 + hist_nhtfrq: -24 + use_init_interp: True + + #urban + urban_hac: 'ON_WASTEHEAT' + urban_traffic: False + +drv_flds_in: + megan_factors_file: '/p/scratch/nrw_test_case/megan21_emis_factors_78pft_c20161108.nc' diff --git a/namelist_generator/pyproject.toml b/namelist_generator/pyproject.toml new file mode 100644 index 0000000000..07de284aa5 --- /dev/null +++ b/namelist_generator/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" \ No newline at end of file diff --git a/namelist_generator/setup.cfg b/namelist_generator/setup.cfg new file mode 100644 index 0000000000..e201d4827e --- /dev/null +++ b/namelist_generator/setup.cfg @@ -0,0 +1,23 @@ +# Read more about the various options under: +# https://setuptools.readthedocs.io/en/latest/userguide/declarative_config.html + +[metadata] +name = clm5nl +version = 0.1 +description = CLM5 namelist generator +author = kvrigor +author_email = kvrigor@users.noreply.github.com +license = MIT +classifiers = + Development Status :: 3 - Alpha + Programming Language :: Python + +[options] +zip_safe = False +packages = find_namespace: +package_dir = {clm5nl = clm5nl} +scripts = build-clm5nl +install_requires = + importlib-metadata; python_version<"3.8" + docopt + ruamel.yaml \ No newline at end of file diff --git a/namelist_generator/setup.py b/namelist_generator/setup.py new file mode 100644 index 0000000000..864b617c60 --- /dev/null +++ b/namelist_generator/setup.py @@ -0,0 +1,2 @@ +import setuptools +setuptools.setup() \ No newline at end of file