diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index b32248d4eb..6ef2db80b6 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,26 +1,41 @@ + + + + + ### Description of changes + + ### Specific notes -Contributors other than yourself, if any: +**Contributors other than yourself, if any:** +- (Replace this text and add more list items as needed) -CTSM Issues Fixed (include github issue #): +**CTSM issues resolved or otherwise addressed, if any:** +- (Replace this text, including GitHub issue #, and add more list items as needed) + + -Are answers expected to change (and if so in what way)? +**If answers are expected to change, describe (delete this line otherwise):** -Any User Interface Changes (namelist or namelist defaults changes)? +**Any user interface changes (namelist or namelist defaults changes)?** -Does this create a need to change or add documentation? Did you do so? +**Testing planned or performed, if any:** +- [ ] (Replace this text and add more list items as needed) + -Testing performed, if any: -(List what testing you did to show your changes worked as expected) -(This can be manual testing or running of the different test suites) -(Documentation on system testing is here: https://github.com/ESCOMP/ctsm/wiki/System-Testing-Guide) -(aux_clm on derecho for intel/gnu and izumi for intel/gnu/nag/nvhpc is the standard for tags on master) -**NOTE: Be sure to check your coding style against the standard -(https://github.com/ESCOMP/ctsm/wiki/CTSM-coding-guidelines) and review -the list of common problems to watch out for -(https://github.com/ESCOMP/CTSM/wiki/List-of-common-problems).** -**If this PR changes the CTSM web documentation, please see our [contribution guidelines for documentation](https://escomp.github.io/CTSM/users_guide/working-with-documentation/docs-intro.html#contribution-guidelines).** \ No newline at end of file +### Requirements before merge: +- [ ] I have followed the [CTSM contribution guidelines](https://github.com/ESCOMP/CTSM/blob/master/CONTRIBUTING.md). + +- [ ] The code in this PR branch builds with no errors. +- [ ] The code in this PR branch runs with no errors. **Briefly describe tested configuration(s):** +- [ ] This either (a) does not change answers, (b) it only changes answers at roundoff level, or (c) I have performed a scientific evaluation of the answer changes. **Which?:** + +- [ ] I have reviewed relevant parts of the CLM documentation [Tech Note](https://escomp.github.io/CTSM/tech_note/index.html) or [User's Guide](https://escomp.github.io/CTSM/users_guide/index.html) to determine if anything needs to be changed or added. **If it does, describe:** +- [ ] This PR either (a) does not create a need to update the documentation or (b) includes required documentation updates (see [guidelines for contributing documentation](https://escomp.github.io/CTSM/users_guide/working-with-documentation/docs-intro.html#contribution-guidelines)). **Which?:** diff --git a/.github/workflows/docs-build-and-deploy.yml b/.github/workflows/docs-build-and-deploy.yml index 55ad033ed7..7951532848 100644 --- a/.github/workflows/docs-build-and-deploy.yml +++ b/.github/workflows/docs-build-and-deploy.yml @@ -11,8 +11,8 @@ on: - '!doc/*ChangeSum*' - '!doc/UpdateChangelog.pl' # Include all include::ed files outside doc/ directory! - - 'src/README.unit_testing' - - 'tools/README' + - 'src/README.unit_testing.md' + - 'tools/README.md' - 'doc/test/test_container_eq_ctsm_pylib.sh' # Allows you to run this workflow manually from the Actions tab diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 6c211d2a3c..4832192fd9 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -13,8 +13,8 @@ on: - '!doc/UpdateChangelog.pl' - '.github/workflows/docs-common.yml' # Include all include::ed files outside doc/ directory! - - 'src/README.unit_testing' - - 'tools/README' + - 'src/README.unit_testing.md' + - 'tools/README.md' - 'doc/test/test_container_eq_ctsm_pylib.sh' pull_request: @@ -27,8 +27,8 @@ on: - '!doc/UpdateChangelog.pl' - '.github/workflows/docs-common.yml' # Include all include::ed files outside doc/ directory! - - 'src/README.unit_testing' - - 'tools/README' + - 'src/README.unit_testing.md' + - 'tools/README.md' - 'doc/test/test_container_eq_ctsm_pylib.sh' workflow_dispatch: @@ -82,3 +82,138 @@ jobs: with: name: test-build-docs-container_failed path: build-logs/ + + check-docs-style: + if: ${{ always() }} + name: Check documentation against style guide + runs-on: ubuntu-latest + steps: + + - name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Disallow fake degree signs + if: always() + # Prevents anyone from using the masculine ordinal indicator, as well as superscript-o/O if + # preceded by a digit in + # - Markdown math style, + # - reStructuredText math style, + # - MyST text style, and + # - reStructuredText text style, + # with or without curly brackets and/or spaces. + # + # What follows is an explanation of the regex. Keep in mind that the superscript-o will + # match whether it's an uppercase O or lowercase o because of the -i flag to grep, so that's + # not handled in the regex. + # + # Markdown math style: + # Markdown math superscripts look like $^o$. There can also be curly brackets, like + # $^{o}$, which would allow you to put multiple characters (including spaces) in the + # superscript. The preceding digit can be inside or outside the dollar signs, again with + # or without spaces. + # + # There are two regex patterns separated by |, to handle the cases where the preceding + # digit is outside or inside the dollar signs, respectively: + # [0-9]\s*\\$\s*\^\{?\s*o + # [0-9] Any digit + # \s* Any number of spaces, including none + # \\$ A literal dollar sign + # \s* Any number of spaces, including none + # \^ A literal caret + # \{? Optionally a literal left curly bracket + # \s* Any number of spaces, including none + # o Lowercase o + # \\\$[0-9]+\s*\^\{?\s*o\s*\}? + # \\\$ A literal dollar sign + # [0-9]+ One or more digits + # \s* Any number of spaces, including none + # \^ A literal caret + # \{? Optionally a literal left curly bracket + # \s* Any number of spaces, including none + # o Lowercase o + # \s* Any number of spaces, including none + # \}? Optionally a literal right curly bracket + # + # MyST text style: + # MyST text superscripts look like {sup}`o`. Here's the regex: + # [0-9]\s*\{sup}\`\s*o\` + # [0-9] Any digit + # \s* Any number of spaces, including none + # \{ A literal left curly bracket + # sup The text "sup" designating the superscript role + # \} A literal right curly bracket + # \` A literal backtick + # \s* Any number of spaces, including none + # o Lowercase o + # \` A literal backtick + # + # reStructuredText text style + # Similar to MyST text superscripts, but with colons instead of curly brackets: :sup:`o`. + # Another difference is that spaces aren't allowed inside the backticks. Also, there has + # to be a space preceding the first colon; this can be preceded by a backslash to avoid + # putting an extraneous space in the rendered text. Here's the regex: + # [0-9]\\\? :sup:\`o\` + # [0-9] Any digit + # \\\? Optionally a literal backslash + # (A literal space) + # :sup: The text ":sup:" designating the superscript role + # \` A literal backtick + # o Lowercase o + # \` A literal backtick + # + # reStructuredText math style + # Mostly the same as reStructuredText text superscripts, but with :math: instead of + # :sup:. In addition, the superscript can optionally be in curly brackets. There can be + # a space after the first backtick but not before the last one. + # + # There are two regex patterns separated by |, to handle the cases where the preceding + # digit is outside or inside the dollar signs, respectively: + # [0-9]\\\? :math:\`\s*\^\{?\s*o\s*\}?\` + # [0-9] Any digit + # \\\? Optionally a literal backslash + # (A literal space) + # :math: The text ":math:" designating the math role + # \` A literal backtick + # \s* Any number of spaces, including none + # \^ A literal caret + # \{? Optionally a literal left curly bracket + # \s* Any number of spaces, including none + # o Lowercase o + # \s* Any number of spaces, including none + # \}? Optionally a literal right curly bracket + # \` A literal backtick + # :math:\`\s*[0-9]+\s*\^\{?\s*o\s*\}?\` + # :math: The text ":math:" designating the math role + # \` A literal backtick + # \s* Any number of spaces, including none + # [0-9]+ One or more digits + # \s* Any number of spaces, including none + # \^ A literal caret + # \{? Optionally a literal left curly bracket + # \s* Any number of spaces, including none + # o Lowercase o + # \s* Any number of spaces, including none + # \}? Optionally a literal right curly bracket + # \` A literal backtick + run: | + set +e + instances_of_fake_degree_signs="$(grep -ionE "[0-9]\s*\\$\s*\^\{?\s*o|\\\$[0-9]+\s*\^\{?\s*o\s*\}?|[0-9]\s*\{sup}\`\s*o\`|[0-9]\\\? :sup:\`o\`|[0-9]\\\? :math:\`\s*\^\{?\s*o\s*\}?\`| :math:\`\s*[0-9]+\s*\^\{?\s*o\s*\}?\`|º" $(find doc -name "*.md" -or -name "*.rst"))" + set -e + if [[ "$instances_of_fake_degree_signs" ]] then + echo -e "Instances of superscript-o or masculine ordinal indicator (º) instead of degree sign (°):\n${instances_of_fake_degree_signs}" + echo -e "\nSee https://escomp.github.io/CTSM/users_guide/working-with-documentation/docs-style-guide.html" + exit 1 + fi + exit 0 + + - name: Disallow curly apostrophes/quotes + if: always() + run: | + set +e + instances_of_curlies="$(grep -onE "“|”|‘|’" $(find doc -name "*.md" -or -name "*.rst"))" + set -e + if [[ "$instances_of_curlies" ]] then + echo -e "Instances of curly apostrophes and/or quote marks:\n${instances_of_curlies}" + exit 1 + fi + exit 0 diff --git a/.gitmodules b/.gitmodules index 586bde8bc0..93bd975139 100644 --- a/.gitmodules +++ b/.gitmodules @@ -124,7 +124,7 @@ fxDONOTUSEurl = https://github.com/ESMCI/mpi-serial [submodule "doc-builder"] path = doc/doc-builder url = https://github.com/ESMCI/doc-builder -fxtag = v3.1.0 +fxtag = v3.1.1 fxrequired = ToplevelOptional # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESMCI/doc-builder diff --git a/README b/README deleted file mode 100644 index deca3cd8d2..0000000000 --- a/README +++ /dev/null @@ -1,184 +0,0 @@ -$CTSMROOT/README 11/24/2025 - -Community Terrestrial Systems Model (CTSM) science version 5.4 series -- source code, tools, -offline-build and test scripts. This gives you everything you need -to run CTSM with CESM with the CMEPS driver and CDEPS data models to provide CRUJRA or GSWP3 forcing data (some older options also available) in -place of a modeled atmosphere. - -CMEPS is the Community Mediator for Earth Prediction Systems. And CDEPS is the -Community Data Models for Earth Prediction System. They are both NUOPC based models -used to drive the CESM (Community Earth System Model) of which CTSM is a component of. -NUOPC is the National Unified Operational Prediction Capability a standard way of building -coupled model systems. The NUOPC layer is based on the Earth System Modeling Framework (ESMF). - -For lists of current bugs (issues) and current development see the CTSM GitHub page: - -https://github.com/ESCOMP/CTSM - -For Code of Conduct (how to work with each other on the CTSM project): - -https://github.com/ESCOMP/CTSM?tab=coc-ov-file - -INFORMATION ON THE CMEPS DRIVER: - -https://escomp.github.io/CMEPS - -https://earthsystemmodeling.org/nuopc/ - -IMPORTANT NOTE ON CESM CHECKOUT VERSUS A CTSM CHECKOUT: - -If this is the top level directory from making a clone of CTSM the -directory structure is a little bit different than if CTSM is from -a clone of the entire CESM. If this is part of CESM this directory -will be under components/clm alongside other CESM component models. -For a CTSM checkout this will be the top level directory. - -Other documentation will refer to $CTSMROOT and it means the directory -that this file is at. CIMEROOT is the directory where "cime" is for -this checkout. For a CESM checkout $CIMEROOT will be the "cime" directory -beneath the top level directory. For a CTSM checkout $CIMEROOT will -be $CTSMROOT/cime. - -IMPORTANT NOTE ABOUT (deprecated) - -Anything marked with (deprecated) is something is going to be removed in a future update. -Often this means it will be replaced with something else. - - -General directory structure ($CTSMROOT): - -doc --------------- Documentation of CTSM. -bld --------------- build-namelist scripts for CTSM. -src --------------- CTSM Source code. -lilac ------------- Lightweight Infrastructure for Land-Atmosphere Coupling (for coupling to a host atmosphere model) -tools ------------- CTSM Offline tools to prepare input datasets and process output. -cime_config ------- Configuration files of cime for compsets and CTSM settings -bin/git-fleximod -- Script to manage the needed sub-component source directories (handled with git submodule) -py_env_create ----- Script to setup the python environment for CTSM python tools using conda -python ------------ Python modules used in tools and testing and automated checking of ALL CTSM python scripts - -Directory structure only for a CTSM checkout: - -components -------- Other active sub-components needed for CTSM to run (river routing and land-ice models) -libraries --------- CESM libraries: PIO (deprecated) -share ------------- CESM shared code -ccs_config -------- CIME configure files (for grids, compsets, and machines) for CESM - -cime/scripts --------------- cesm/cime driver scripts - -components/cmeps -------------------- CESM top level driver (for NUOPC driver [which is the default]) source code. -components/cdeps -------------------- CESM top level data model shared code (for NUOPC driver). -components/cism --------------------- CESM Community land Ice Sheet Model. -components/mosart ------------------- Model for Scale Adaptive River Transport -components/mizuroute ---------------- Reached based river transport model for water routing - (allows both gridded river and Hydrologic Responce Unit river grids) -components/rtm ---------------------- CESM River Transport Model. - -Top level documentation ($CTSMROOT): - -README ------------------- This file -README.md ---------------- File that displays on github under https::/github.com/ESCOMP/CTSM.git -README.rst --------------- File that displays under the project in github -README_GITFLEXIMOD.rst --- Information on how to work with git-fleximod for CTSM -WhatsNewInCTSM5.4.md ----- Overview document of the changes between ctsm5.3 and ctsm5.4 -Copyright ---------------- CESM Copyright file -doc/UpdateChangeLog.pl --- Script to add documentation on a tag to the - ChangeLog/ChangeSum files -doc/ChangeLog ------------ Documents different CTSM versions -doc/ChangeSum ------------ Summary documentation of different CTSM versions - -doc/design --------------- Software Engineering and code design document files - -Checklists for standard Software Engineering tasks - -./doc/README.CHECKLIST.master_tags -./bld/namelist_files/README.CHECKLIST.interpolating_initial_conditions.md - -Documentation of Namelist Items: (view the following in a web browser) - -bld/namelist_files/namelist_definition_ctsm.xml --- Definition of all namelist items -bld/namelist_files/namelist_defaults_ctsm.xml ----- Default values - -============================================================================================= -Important files in main directories (under $CTSMROOT): -============================================================================================= - -run_sys_tests --------------- Python script to send the standard CTSM testing off (submits - the create_test test suite for several different compilers on the - machines we do standard CTSM testing on). - -parse_cime.cs.status -------- Script to parse test status files cs.status.* created by create_test - (can be used along with run_sys_tests) -doc/Quickstart.GUIDE -------- Quick guide to using NUOPC scripts. -doc/IMPORTANT_NOTES.md ------ Some important notes about this version of - CTSM, configuration modes and namelist items - that are not validated or functional. -doc/ChangeLog --------------- Detailed list of changes for each model version. -doc/ChangeSum --------------- Summary one-line list of changes for each - model version. -doc/UsersGuide -------------- CTSM Users Guide - -bld/README ------------------ Description of how to use the build-namelist scripts. -bld/build-namelist ---------- Lower level script to build CTSM namelists. - -cime_config/buildnml ------------- Build the CTSM namelist for CIME -cime_config/buildlib ------------- Build the CTSM library -cime_config/config_compsets.xml -- Define CTSM compsets -cime_config/config_component.xml - Define CTSM XML settings -cime_config/config_tests.xml ----- Define CTSM specific tests -cime_config/config_pes.xml ------- Define Processor layouts for various CTSM grids and compsets -cime_config/testdefs ------------- Directory for specification of CTSM testing -cime_config/testdefs/ExpectedTestFails.xml -- List of tests that are expected to fail -cime_config/usermods_dirs/clm ---- Directories of sets of user-modification subdirs - (These are directories that add specific user modifications to - simulations created using "cime/scripts/create_newcase --user-mods-dir clm/*) - -tools/mksurfdata_esmf --------- Directory to build program to create surface dataset - at any resolution. -tools/mkmapgrids -------------- NCL script to create a SCRIP grid file for a regular lat/lon grid (deprecated) -tools/crop_calendars ---------- Tools to process and process and create crop calendar datasets for CTSM -tools/modify_input_files ------ Script to modify existing CTSM input datasets in standard ways -tools/site_and_regional ------- Scripts to create input datasets for single site and regional - cases, primarily by modifying existing global datasets -tools/contrib ----------------- Miscellansous useful scripts for pre and post processing - as well as case management of CTSM. These scripts are - contributed by users and may not be as well tested or - supported as other tools. -.vscode ----------------------- Suggested settings for using MS Visual Studio code with CTSM. - - -============================================================================================= -Source code directory structure: -============================================================================================= - -src/biogeochem ---- Biogeochemisty -src/main ---------- Main control and high level code -src/cpl ----------- Land model high level caps for NUOPC driver (and LILAC) -src/biogeophys ---- Biogeophysics (Hydrology) -src/dyn_subgrid --- Dynamic land unit change -src/init_interp --- Online interpolation -scr/fates --------- FATES model and sub-directories - Functionally Assembled Terrestrial Ecosystem Simulator (FATES) - Ecosystem Demography model -src/utils --------- Utility codes -src/self_tests ---- Internal testing (unit tests run as a part of a CTSM system test) -src/unit_test_shr - Unit test shared modules for unit testing -src/unit_test_stubs Unit test stubs that replicate CTSM code simpler - -============================================================================================= - QUICKSTART: using the NUOPC driver scripts -============================================================================================= - - cd $CIMEROOT/scripts - ./create_newcase # get help on how to run create_newcase - ./create_newcase --case testI --res f09_t232 --compset I2000Clm60BgcCrop - # create new "I" case for default machine at 1.9x2.5_gx1v7 - # "I2000Clm60BgcCrop" case is clm6_0 physics, CDEPS, and inactive ice/ocn/glc - # and MOSART for river-routing - cd testI - ./case.setup # create the $CASE.run file - ./case.build # build model and create namelists - ./case.submit # submit script - # (NOTE: ./xmlchange RESUBMIT=10 to set RESUBMIT to number - # # of times to automatically resubmit -- 10 in this example) - diff --git a/README.CHECKLIST.new_case b/README.CHECKLIST.new_case deleted file mode 100644 index 71ba4a8284..0000000000 --- a/README.CHECKLIST.new_case +++ /dev/null @@ -1,42 +0,0 @@ -$CTSMROOT/README.CHECKLIST.new_case 03/01/2021 - -This is a check list of things to do when setting up a new case in order to help ensure everything is correct. There -are lots of tiny details that need to be right and it's easy to get something wrong. So the first screening to make -sure it's right is for you to carefully check through your case and make sure it's right. - -The following assumes you have created a new case and are in it's case directory. - -General Checklist to always do: - - - Make sure CLM_ env settings are correct - (./xmlquery -p CLM) - - Make sure you are using the correct CLM_PHYSICS_VERSION - (./xmlquery -p CLM_PHYSICS_VERSION) - - Make sure you are running the appropriate overall CLM vegetation model. - The "-bgc" option of either Satellite Phenology (sp), or - Full BioGeoChemistry (bgc), or FATES (fates) - (./xmlquery -p CLM_BLDNML_OPTS) - - Also if you are running the bgc model, check to see if you should be running the prognostic crop model - (option -crop in CLM_BLDNML_OPTS) - - Make sure the LND_TUNING_MODE is correct - (./xmlquery LND_TUNING_MODE) - - For an "I compset" make sure you are running over the right forcing years - (usually ./xmlquery -p DATM_YR) - - Again for an "I compset" make sure the DATM streams are operating over the right years - (look at the CaseDocs/datm.streams.xml file) - - First and align year for streams should be the start year of a historical simulation - (./xmlquery RUN_STARTDATE) - (grep stream_year_first CaseDocs/lnd_in; grep model_year_align CaseDocs/lnd_in) - - Last year for streams should be the last year you are going to run to (or beyond it) - (grep stream_year_last CaseDocs/lnd_in) - - Make sure you are starting from appropriate spunup initial conditions - (Check the run-type with: ./xmlquery RUN_TYPE) - (check finidat for a startup or hybrid simulation: grep finidat CaseDocs/lnd_in) - (check nrevsn for a branch simulation: grep nrevsn CaseDocs/lnd_in) - - Run for a month (or some short period) and go over the log files and especially the settings and files read in them. - (For an I case you especially want to look at the lnd.log and atm.log files) - -Some other suggestions on things that can be done: - -- Compare namelist files to an existing case if you are doing something almost the same as a previous simulation. -- Ask another collaborator to look over your case directory diff --git a/README.CHECKLIST.new_case.md b/README.CHECKLIST.new_case.md new file mode 100755 index 0000000000..868cfe1c09 --- /dev/null +++ b/README.CHECKLIST.new_case.md @@ -0,0 +1,27 @@ +`$CTSMROOT/README.CHECKLIST.new_case` 03/01/2021 + +This is a check list of things to do when setting up a new case in order to help ensure everything is correct. There are lots of tiny details that need to be right and it's easy to get something wrong. So the first screening to make sure it's right is for you to carefully check through your case and make sure it's right. + +The following assumes you have created a new case and are in its case directory. + +General Checklist to always do: + +- Make sure `CLM_` environment settings are correct: `./xmlquery -p CLM` +- Make sure you are using the correct `CLM_PHYSICS_VERSION`: `./xmlquery -p CLM_PHYSICS_VERSION` +- Make sure you are running the appropriate overall CLM vegetation model, i.e. the `-bgc` option of either Satellite Phenology (`sp`) or Full BioGeoChemistry (`bgc`) or FATES (`fates`): `./xmlquery -p CLM_BLDNML_OPTS` +- If you are running the `bgc` model, check to see if you should be running the prognostic crop model: option `-crop` in `CLM_BLDNML_OPTS` +- Make sure the `LND_TUNING_MODE` is correct: `./xmlquery LND_TUNING_MODE` +- For an "`I` compset" make sure you are running over the correct forcing years: usually `./xmlquery -p DATM_YR` +- For an "`I` compset" make sure the DATM streams are operating over the correct years: look at the `CaseDocs/datm.streams.xml` file +- First and align year for streams should be the start year of a historical simulation: `./xmlquery RUN_STARTDATE; grep stream_year_first CaseDocs/lnd_in; grep model_year_align CaseDocs/lnd_in` +- Last year for streams should be the last year you are going to run to (or beyond it): `grep stream_year_last CaseDocs/lnd_in` +- Make sure you are starting from appropriate spunup initial conditions: + - Check the run-type with: `./xmlquery RUN_TYPE` + - Check finidat for a startup or hybrid simulation: `grep finidat CaseDocs/lnd_in` + - Check nrevsn for a branch simulation: `grep nrevsn CaseDocs/lnd_in` +- Run for a month (or some short period) and go over the log files and especially the settings and files read in them: for an `I` case you especially want to look at the `lnd.log` and `atm.log` files + +Some other suggestions on things that can be done: + +- Compare namelist files to an existing case if you are doing something almost the same as a previous simulation +- Ask another collaborator to look over your case directory \ No newline at end of file diff --git a/README_GITFLEXIMOD.md b/README_GITFLEXIMOD.md new file mode 100755 index 0000000000..1ed51a8b59 --- /dev/null +++ b/README_GITFLEXIMOD.md @@ -0,0 +1,110 @@ +# Obtaining the full model code and associated scripting infrastructure + +CTSM is released via GitHub. You will need some familiarity with git in order +to modify the code and commit these changes. However, to simply checkout and run the +code, no git knowledge is required other than what is documented in the following steps. + +To obtain the CTSM code you need to do the following: + +1. Clone the repository. : + + git clone https://github.com/ESCOMP/CTSM.git my_ctsm_sandbox + + This will create a directory `my_ctsm_sandbox/` in your current working directory. + +2. Run `./bin/git-fleximod update`: + + cd my_ctsm_sandbox + ./bin/git-fleximod update + ./bin/git-fleximod --help # for a user's guide + + `git-fleximod` is a package manager that will + populate the ctsm directory with the relevant versions of each of the + components along with the CIME infrastructure code. + Additional documentation for git-fleximod appears here: + + +"components" here refers to seperate git repositories for seperable parts of +the code (such as the MOSART or mizuRoute river models). Because they are +managed with "submodule" in git hereafter we will refer to them as "submodule(s)". + +At this point you have a working version of CTSM. + +To see full details of how to set up a case, compile and run, see the CIME documentation at . + +## More details on git-fleximod + +The file `.gitmodules` in your top-level CTSM directory tells +`git-fleximod` which tag/branch of each submodule +should be brought in to generate your sandbox. + +NOTE: If you manually modify a submodule without updating `.gitmodules`, +e.g. switch to a different tag, then rerunning git-fleximod will warn you of +local changes you need to resolve. +git-fleximod will not change a modified submodule back to what is specified in +`.gitmodules` without the `--force` option. +See below documentation [Customizing your CTSM sandbox](#customizing-your-ctsm-sandbox) for more details. + +**You need to rerun git-fleximod whenever `.gitmodules` has +changed** (unless you have already manually updated the relevant +submodule(s) to have the correct branch/tag checked out). Common times +when this is needed are: + +- After checking out a new CTSM branch/tag +- After merging some other CTSM branch/tag into your currently + checked-out branch + +# Customizing your CTSM sandbox + +There are several use cases to consider when you want to customize or modify your CTSM sandbox. + +## Switching to a different CTSM branch or tag + +If you have already checked out a branch or tag and **HAVE NOT MADE ANY +MODIFICATIONS** it is simple to change your sandbox. Say that you +checked out ctsm5.2.0 but really wanted to have ctsm5.3.0; +you would simply do the following: + + git checkout ctsm5.3.0 + ./bin/git-fleximod update + +You should **not** use this method if you have made any source code +changes, or if you have any ongoing CTSM cases that were created from +this sandbox. In these cases, it is often easiest to do a second `git +clone`. + +## Pointing to a different version of a submodule + +Each entry in `.gitmodules` has the following form (we use CIME as an +example below): + + [submodule "cime"] + path = cime + url = https://github.com/ESMCI/cime + fxtag = cime6.0.246 + fxrequired = ToplevelRequired + fxDONOTUSEurl = https://github.com/ESMCI/cime + +Each entry specifies either a tag or a hash. To point to a new tag or hash: + +1. Modify the relevant entry/entries in `.gitmodules` (e.g., changing + `cime6.0.246` to `cime6.0.247` above) + +2. Checkout the new submodule(s): + + ./bin/git-fleximod update + +Keep in mind that changing individual submodule from a tag may result +in an invalid model (won't compile, won't run, not scientifically +meaningful) and is unsupported. + +### Committing your change to `.gitmodules` + +After making this change, it's a good idea to commit the change in your +local CTSM git repository. First create a branch in your local +repository, then commit it. Feel free to create whatever local branches +you'd like in git. For example: + + git checkout -b my_ctsm_branch + git add .gitmodules + git commit -m "Update CIME to cime6.0.247" diff --git a/README_GITFLEXIMOD.rst b/README_GITFLEXIMOD.rst deleted file mode 100644 index d1ab767645..0000000000 --- a/README_GITFLEXIMOD.rst +++ /dev/null @@ -1,118 +0,0 @@ -Obtaining the full model code and associated scripting infrastructure -===================================================================== - -CTSM is released via GitHub. You will need some familiarity with git in order -to modify the code and commit these changes. However, to simply checkout and run the -code, no git knowledge is required other than what is documented in the following steps. - -To obtain the CTSM code you need to do the following: - -#. Clone the repository. :: - - git clone https://github.com/ESCOMP/CTSM.git my_ctsm_sandbox - - This will create a directory ``my_ctsm_sandbox/`` in your current working directory. - -#. Run **./bin/git-fleximod update**. :: - - cd my_ctsm_sandbox - ./bin/git-fleximod update - ./bin/git-fleximod --help # for a user's guide - - **git-fleximod** is a package manager that will - populate the ctsm directory with the relevant versions of each of the - components along with the CIME infrastructure code. - Additional documentation for git-fleximod appears here: - https://github.com/ESMCI/git-fleximod?tab=readme-ov-file#git-fleximod - -"components" here refers to seperate git repositories for seperable parts of -the code (such as the MOSART or mizuRoute river models). Because they are -managed with "submodule" in git hereafter we will refer to them as "submodule(s)". - -At this point you have a working version of CTSM. - -To see full details of how to set up a case, compile and run, see the CIME documentation at http://esmci.github.io/cime/ . - -More details on git-fleximod ----------------------------- - -The file **.gitmodules** in your top-level CTSM directory tells -**git-fleximod** which tag/branch of each submodule -should be brought in to generate your sandbox. - -NOTE: If you manually modify a submodule without updating .gitmodules, -e.g. switch to a different tag, then rerunning git-fleximod will warn you of -local changes you need to resolve. -git-fleximod will not change a modified submodule back to what is specified in -.gitmodules without the --force option. -See below documentation `Customizing your CTSM sandbox`_ for more details. - -**You need to rerun git-fleximod whenever .gitmodules has -changed** (unless you have already manually updated the relevant -submodule(s) to have the correct branch/tag checked out). Common times -when this is needed are: - -* After checking out a new CTSM branch/tag - -* After merging some other CTSM branch/tag into your currently - checked-out branch - -Customizing your CTSM sandbox -============================= - -There are several use cases to consider when you want to customize or modify your CTSM sandbox. - -Switching to a different CTSM branch or tag -------------------------------------------- - -If you have already checked out a branch or tag and **HAVE NOT MADE ANY -MODIFICATIONS** it is simple to change your sandbox. Say that you -checked out ctsm5.2.0 but really wanted to have ctsm5.3.0; -you would simply do the following:: - - git checkout ctsm5.3.0 - ./bin/git-fleximod update - -You should **not** use this method if you have made any source code -changes, or if you have any ongoing CTSM cases that were created from -this sandbox. In these cases, it is often easiest to do a second **git -clone**. - -Pointing to a different version of a submodule ----------------------------------------------- - -Each entry in **.gitmodules** has the following form (we use CIME as an -example below):: - - [submodule "cime"] - path = cime - url = https://github.com/ESMCI/cime - fxtag = cime6.0.246 - fxrequired = ToplevelRequired - fxDONOTUSEurl = https://github.com/ESMCI/cime - -Each entry specifies either a tag or a hash. To point to a new tag or hash: - -#. Modify the relevant entry/entries in **.gitmodules** (e.g., changing - ``cime6.0.246`` to ``cime6.0.247`` above) - -#. Checkout the new submodule(s):: - - ./bin/git-fleximod update - -Keep in mind that changing individual submodule from a tag may result -in an invalid model (won't compile, won't run, not scientifically -meaningful) and is unsupported. - -Committing your change to .gitmodules -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -After making this change, it's a good idea to commit the change in your -local CTSM git repository. First create a branch in your local -repository, then commit it. Feel free to create whatever local branches -you'd like in git. For example:: - - git checkout -b my_ctsm_branch - git add .gitmodules - git commit -m "Update CIME to cime6.0.247" - diff --git a/README_on_CTSM.md b/README_on_CTSM.md new file mode 100644 index 0000000000..e59074e1b7 --- /dev/null +++ b/README_on_CTSM.md @@ -0,0 +1,161 @@ +$CTSMROOT/README 11/24/2025 + +Community Terrestrial Systems Model (CTSM) science version 5.4 series -- source code, tools, +offline-build and test scripts. This gives you everything you need +to run CTSM with CESM with the CMEPS driver and CDEPS data models to provide CRUJRA or GSWP3 forcing data (some older options also available) in +place of a modeled atmosphere. + +CMEPS is the Community Mediator for Earth Prediction Systems. And CDEPS is the +Community Data Models for Earth Prediction System. They are both NUOPC based models +used to drive the CESM (Community Earth System Model) of which CTSM is a component of. +NUOPC is the National Unified Operational Prediction Capability a standard way of building +coupled model systems. The NUOPC layer is based on the Earth System Modeling Framework (ESMF). + +For lists of current bugs (issues) and current development see the CTSM GitHub page: + +https://github.com/ESCOMP/CTSM + +For Code of Conduct (how to work with each other on the CTSM project): + +https://github.com/ESCOMP/CTSM?tab=coc-ov-file + +INFORMATION ON THE CMEPS DRIVER: +- https://escomp.github.io/CMEPS +- https://earthsystemmodeling.org/nuopc/ + +IMPORTANT NOTE ON CESM CHECKOUT VERSUS A CTSM CHECKOUT: + +If this is the top level directory from making a clone of CTSM the +directory structure is a little bit different than if CTSM is from +a clone of the entire CESM. If this is part of CESM this directory +will be under `components/clm` alongside other CESM component models. +For a CTSM checkout this will be the top level directory. + +Other documentation will refer to `$CTSMROOT` and it means the directory +that this file is at. CIMEROOT is the directory where "cime" is for +this checkout. For a CESM checkout `$CIMEROOT` will be the "cime" directory +beneath the top level directory. For a CTSM checkout `$CIMEROOT` will +be `$CTSMROOT/cime`. + +IMPORTANT NOTE ABOUT (deprecated) + +Anything marked with (deprecated) is something is going to be removed in a future update. +Often this means it will be replaced with something else. + + +General directory structure ($CTSMROOT): + +- `doc`: Documentation of CTSM +- `bld`: build-namelist scripts for CTSM +- `src`: CTSM Source code +- `lilac`: Lightweight Infrastructure for Land-Atmosphere Coupling (for coupling to a host atmosphere model) +- `tools`: CTSM Offline tools to prepare input datasets and process output +- `cime_config`: Configuration files of cime for compsets and CTSM settings +- `bin/git-fleximod`: Script to manage the needed sub-component source directories (handled with git submodule) +- `py_env_create`: Script to setup the python environment for CTSM python tools using conda +- `python`: Python modules used in tools and testing and automated checking of ALL CTSM python scripts + +Directory structure only for a CTSM checkout: + +- `components`: Other active sub-components needed for CTSM to run (river routing and land-ice models) +- `libraries`: CESM libraries: PIO (deprecated) +- `share`: CESM shared code +- `ccs_config`: CIME configure files (for grids, compsets, and machines) for CESM + +- `cime/scripts`: cesm/cime driver scripts + +- `components/cmeps`: CESM top level driver (for NUOPC driver [which is the default]) source code +- `components/cdeps`: CESM top level data model shared code (for NUOPC driver) +- `components/cism`: CESM Community land Ice Sheet Model +- `components/mosart`: Model for Scale Adaptive River Transport +- `components/mizuroute`: Reached based river transport model for water routing (allows both gridded river and Hydrologic Responce Unit river grids) +- `components/rtm`: CESM River Transport Model + +Top level documentation ($CTSMROOT): + +- `README_on_CTSM.md`: This file +- `README.md`: File that displays on github under https::/github.com/ESCOMP/CTSM.git +- `README_GITFLEXIMOD.md`: Information on how to work with git-fleximod for CTSM +- `README.CHECKLIST.new_case.md`: Information on starting a new case (i.e. simulation) +- `WhatsNewInCTSM5.4.md`: Overview document of the changes between ctsm5.3 and ctsm5.4 (earlier versions in /doc) +- `Copyright`: CESM Copyright file +- `doc/UpdateChangeLog.pl`: Script to add documentation on a tag to the ChangeLog/ChangeSum files +- `doc/ChangeLog`: Documents different CTSM versions +- `doc/ChangeSum`: Summary documentation of different CTSM versions +- `doc/design`: Software Engineering and code design document files + +Checklists for standard Software Engineering tasks + +- `./doc/README.CHECKLIST.master_tags.md` +- `./bld/namelist_files/README.CHECKLIST.interpolating_initial_conditions.md` + +Documentation of Namelist Items: (view the following in a web browser) + +- `bld/namelist_files/namelist_definition_ctsm.xml`: Definition of all namelist items +- `bld/namelist_files/namelist_defaults_ctsm.xml`: Default values + +Important files in main directories (under $CTSMROOT): +============================================================================================= + +- `run_sys_tests`: Python script to send the standard CTSM testing off (submits the create_test test suite for several different compilers on the machines we do standard CTSM testing on) + +- `parse_cime.cs.status`: Script to parse test status files `cs.status.*` created by create_test (can be used along with run_sys_tests) +- `doc/Quickstart.GUIDE`: Quick guide to using NUOPC scripts +- `doc/IMPORTANT_NOTES.md`: Some important notes about this version of CTSM, configuration modes and namelist items that are not validated or functional +- `doc/ChangeLog`: Detailed list of changes for each model version +- `doc/ChangeSum`: Summary one-line list of changes for each model version +- `doc/UsersGuide`: CTSM Users Guide + +- `bld/README`: Description of how to use the `build-namelist` scripts +- `bld/build-namelist`: Lower level script to build CTSM namelists + +- `cime_config/buildnml`: Build the CTSM namelist for CIME +- `cime_config/buildlib`: Build the CTSM library +- `cime_config/config_compsets.xml`: Define CTSM compsets +- `cime_config/config_component.xml`: Define CTSM XML settings +- `cime_config/config_tests.xml`: Define CTSM specific tests +- `cime_config/config_pes.xml`: Define Processor layouts for various CTSM grids and compsets +- `cime_config/testdefs`: Directory for specification of CTSM testing +- `cime_config/testdefs/ExpectedTestFails.xml`: List of tests that are expected to fail +- `cime_config/usermods_dirs/clm`: Directories of sets of user-modification subdirs; these are directories that add specific user modifications to simulations created using `cime/scripts/create_newcase --user-mods-dir clm/*` + +- `tools/mksurfdata_esmf`: Directory to build program to create surface dataset at any resolution +- `tools/mkmapgrids`: NCL script to create a SCRIP grid file for a regular lat/lon grid (deprecated) +- `tools/crop_calendars`: Tools to process and process and create crop calendar datasets for CTSM +- `tools/modify_input_files`: Script to modify existing CTSM input datasets in standard ways +- `tools/site_and_regional`: Scripts to create input datasets for single site and regional cases, primarily by modifying existing global datasets +- `tools/contrib`: Miscellansous useful scripts for pre and post processing as well as case management of CTSM. These scripts are contributed by users and may not be as well tested or supported as other tools +- `.vscode`: Suggested settings for using MS Visual Studio code with CTSM + + +Source code directory structure: +============================================================================================= + +- `src/biogeochem`: Biogeochemisty +- `src/main`: Main control and high level code +- `src/cpl`: Land model high level caps for NUOPC driver (and LILAC) +- `src/biogeophys`: Biogeophysics (Hydrology) +- `src/dyn_subgrid`: Dynamic land unit change +- `src/init_interp`: Online interpolation +- `scr/fates`: FATES (Functionally Assembled Terrestrial Ecosystem Simulator) ecosystem demography model and sub-directories +- `src/utils`: Utility codes +- `src/self_tests`: Internal testing (unit tests run as a part of a CTSM system test) +- `src/unit_test_shr`: Unit test shared modules for unit testing +src/unit_test_stubs Unit test stubs that replicate CTSM code simpler + +QUICKSTART: using the NUOPC driver scripts +============================================================================================= + + cd $CIMEROOT/scripts + ./create_newcase # get help on how to run create_newcase + ./create_newcase --case testI --res f09_t232 --compset I2000Clm60BgcCrop + # create new "I" case for default machine at 1.9x2.5_gx1v7 + # "I2000Clm60BgcCrop" case is clm6_0 physics, CDEPS, and inactive ice/ocn/glc + # and MOSART for river-routing + cd testI + ./case.setup # create the $CASE.run file + ./case.build # build model and create namelists + ./case.submit # submit script + # (NOTE: ./xmlchange RESUBMIT=10 to set RESUBMIT to number + # # of times to automatically resubmit -- 10 in this example) + diff --git a/bld/README b/bld/README.md similarity index 51% rename from bld/README rename to bld/README.md index feb0b8495c..76dfcd6e1c 100644 --- a/bld/README +++ b/bld/README.md @@ -1,47 +1,47 @@ $CTSMROOT/bld/README Jun/08/2018 -CLM build and configure directory and scripts. Scripts to help -you prepare to build CLM as a component within CESM, and setup -a namelist for it. +CLM build and configure directory and scripts. Scripts to help you prepare to build CLM as a component within CESM, and setup a namelist for it. This is a lower level script called from with CESM/CIME. Important files/directories: ---------- Namelist build scripts +# Namelist build scripts -config_files/clm_phys_vers.pm ------------- Perl module to handle different CLM versions -config_files/config_definition_ctsm.xml --- XML file defining CTSM configuration items (mainly physics version) +config_files/clm_phys_vers.pm ------------- Perl module to handle different CLM versions +config_files/config_definition_ctsm.xml --- XML file defining CTSM configuration items (mainly physics version) ---------- Scripts to build the namelists -build-namelist --- Build the namelists needed +# Scripts to build the namelists +build-namelist --- Build the namelists needed -env_run.xml --- Sample case runtime environment variables, so build-namelist can run outside of a case directory. +env_run.xml --- Sample case runtime environment variables, so build-namelist can run outside of a case directory ---------- Test scripts directory -unit_testers --- Directory of scripts to test scipts in this directory - (most notably build-namelist) +# Test scripts directory ----------- XML Files describing namelists in namelist_files -namelist_files/namelist_defaults_ctsm.xml --------- List of default values for the ctsm namelist -namelist_files/namelist_defaults_overall.xml ------ List of default values for overall settings -namelist_files/namelist_defaults_usr_files.xml ---- List of default values for the user-files (deprecated) -namelist_files/namelist_definition_ctsm.xml ------- Definition of all namelist items for ctsm -namelist_files/namelist_definition.xsl ------------ Describes how to view the xml file as html -namelist_files/use_cases -------------------------- Specific configurations that build-namelist uses -namelist_files/use_cases/README ------------------- File explaining the naming convention for use_cases +unit_testers --- Directory of scripts to test scipts in this directory (most notably build-namelist) ----------- Driver namelist files, duplicated information from cime/driver/cime_config -namelist_files/namelist_defaults_drv.xml ---------- List of default values for driver namelist defaults -namelist_files/namelist_defaults_drydep.xml ------- List of default values for dry deposition and MEGAN fields -namelist_files/namelist_defaults_fire_emis.xml ---- List of default values for fire emission fields -namelist_files/namelist_defaults_dust_emis.xml ---- List of default values for the dust emissions module. -namelist_files/namelist_definition_drv.xml -------- Definition of all driver namelist items -namelist_files/namelist_definition_drv_flds.xml --- Definition of add driver fieldsnamelist items +# XML Files describing namelists in namelist_files +namelist_files/namelist_defaults_ctsm.xml --------- List of default values for the ctsm namelist +namelist_files/namelist_defaults_overall.xml ------ List of default values for overall settings +namelist_files/namelist_defaults_usr_files.xml ---- List of default values for the user-files (deprecated) +namelist_files/namelist_definition_ctsm.xml ------- Definition of all namelist items for ctsm +namelist_files/namelist_definition.xsl ------------ Describes how to view the xml file as html +namelist_files/use_cases -------------------------- Specific configurations that build-namelist uses +namelist_files/use_cases/README ------------------- File explaining the naming convention for use_cases + +# Driver namelist files, duplicated information from cime/driver/cime_config + +namelist_files/namelist_defaults_drv.xml ---------- List of default values for driver namelist defaults +namelist_files/namelist_defaults_drydep.xml ------- List of default values for dry deposition and MEGAN fields +namelist_files/namelist_defaults_fire_emis.xml ---- List of default values for fire emission fields +namelist_files/namelist_defaults_dust_emis.xml ---- List of default values for the dust emissions module +namelist_files/namelist_definition_drv.xml -------- Definition of all driver namelist items +namelist_files/namelist_definition_drv_flds.xml --- Definition of add driver fieldsnamelist items + +# XML helper files + +namelist_files/LogMessages.pm ---- Perl module to handle log output +namelist_files/history_fields.xsl - Style sheet for history fields as created by script that lists all of the history fields from the source files (../src/main/findHistFields.pl) ----------- XML helper files -namelist_files/LogMessages.pm ---- Perl module to handle log output -namelist_files/history_fields.xsl - Style sheet for history fields as created by script that lists all of the - history fields from the source files (../src/main/findHistFields.pl) diff --git a/bld/namelist_files/use_cases/README b/bld/namelist_files/use_cases/README.md similarity index 68% rename from bld/namelist_files/use_cases/README rename to bld/namelist_files/use_cases/README.md index f139759b57..98672ff756 100644 --- a/bld/namelist_files/use_cases/README +++ b/bld/namelist_files/use_cases/README.md @@ -30,13 +30,10 @@ Present day options (uses default present-day simulation year -- which right now Where -yyyy = Simulation year (such as 1850 or 2000). -yyyy-yyyy = Range of simulation years to run over (i.e.. 1850-2000). -yyyy-PD = Range of simulation years to run over until present day (i.e.. 2018-2024). -$ssp_rcp = Shared Socieconomic Pathway (SSP) Representative concentration pathway (RCP) description string - for future scenarios: - SSP#-#.# (for example: SSP5-8.5, SSP1-2.6, SSP4-6.0 - [can be blank for historical cases]. -$desc = Description of anything else -- alpha-numeric. - Should start with an underscore ("_") if not by itself - (for _transient and _control). +yyyy = Simulation year (such as 1850 or 2000) +yyyy-yyyy = Range of simulation years to run over (i.e.. 1850-2000) +yyyy-PD = Range of simulation years to run over until present day (i.e.. 2018-2024) +$ssp_rcp = Shared Socieconomic Pathway (SSP) Representative concentration pathway (RCP) description string for future scenarios: + SSP#-#.# (e.g., SSP5-8.5, SSP1-2.6, SSP4-6.0) [can be blank for historical cases] +$desc = Description of anything else -- alpha-numeric; should start with an underscore ("_") if not by itself (for _transient and _control) + diff --git a/doc/ChangeLog b/doc/ChangeLog index 1cdee24868..9b06393243 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,4 +1,67 @@ =============================================================== +Tag name: ctsm5.4.038 +Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310) +Date: Thu May 7 03:29:26 PM MDT 2026 +One-line Summary: Merge b4b-dev to master + +Purpose and description of changes +---------------------------------- + +Pull requests (PRs) coming in with this b4b-dev merge to master: +#4001 from samsrabin/fix-residual-curlies +#3942 from wwieder/documentation_2.23 +#3958 from adrifoster/docs_photosynthetic_capacity_update +#3990 from samsrabin/enforce-docs-style +#3981 from samsrabin/docs-docs-vscode-setup +#3982 from samsrabin/docs-docs-embedding +#3929 from olyson/docs-I3886-1.7-Troubleshooting +#3967 from wwieder/documentation_2.19 +#3994 from samsrabin/doc-builder-improve-verbosity-filter +#3974 from samsrabin/docs-docs-20260427 +#3930 from slevis-lmwg/upd_sec_2.17.2 +#3971 from wwieder/Sturm +#3816 from slevis-lmwg/readmes_to_md +#3986 from samsrabin/update-pr-template-20260501 +#3960 from linniahawkins/edit-docs +#3916 from olyson/docs-I3849-2-3-Surface-Albedos +#3913 from olyson/docs-I3862-2-16-Urban-Model +#3972 from samsrabin/docs-pr-preview-tool + +Bugs fixed +---------- +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: + Resolves long list of documentation issues that appear directly in the above PRs. + +Notes of particular relevance for users +--------------------------------------- +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + Possibly as pertains to the documentation. + +Changes to documentation: + All the PRs relate to documentation updates. + +Contributors: + @wwieder @adrifoster @samsrabin @olyson @linniahawkins @slevis-lmwg + +Notes of particular relevance for developers: +--------------------------------------------- + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + +Answer changes +-------------- + +Changes answers relative to baseline: No + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/4000 + +=============================================================== +=============================================================== Tag name: ctsm5.4.037 Originator(s): Ryan Knox, Matvey Debolskiy Date: Mon May 4 04:51:35 PM MDT 2026 diff --git a/doc/ChangeSum b/doc/ChangeSum index d52a150328..525bc0dc37 100644 --- a/doc/ChangeSum +++ b/doc/ChangeSum @@ -1,5 +1,6 @@ Tag Who Date Summary ============================================================================================================================ + ctsm5.4.038 slevis 05/07/2026 Merge b4b-dev to master ctsm5.4.037 multiple 05/04/2026 Fix for FATES year-boundary restart issue ctsm5.4.036 multiple 04/27/2026 Complete the FATES-CLM nitrogen coupling ctsm5.4.035 erik 04/26/2026 Merge b4b-dev to master diff --git a/doc/README.CHECKLIST.master_tags.md b/doc/README.CHECKLIST.master_tags.md index 4dd21356cc..5a42fb0d30 100644 --- a/doc/README.CHECKLIST.master_tags.md +++ b/doc/README.CHECKLIST.master_tags.md @@ -27,7 +27,7 @@ https://github.com/ESCOMP/ctsm/wiki/CTSM-development-workflow 3c -- make sure you understand any changes to the baselines -- to document in ChangeLog 3d -- Check the log file for run_sys_tests (`../run_sys_test.log`, to make sure that submodules are correct (see 2c above) - 3e -- When Izumi’s baseline is ready, manually open read permissions to all. + 3e -- When Izumi's baseline is ready, manually open read permissions to all. > [!TIP] > Always test on your fork with a feature-branch so that we can change tag order if needed. Put > baselines in the next tag name, as we can easily change afterwards if needed. diff --git a/doc/WhatsNewInCTSM5.3.md b/doc/WhatsNewInCTSM5.3.md index 4717deac30..d8fabaa3e3 100644 --- a/doc/WhatsNewInCTSM5.3.md +++ b/doc/WhatsNewInCTSM5.3.md @@ -18,7 +18,7 @@ Changes to defaults for `clm6_0` physics: * Urban explicit A/C turned on (links above). * Snow thermal conductivity method is now `Sturm1997`. ([PR \#2348](https://github.com/ESCOMP/CTSM/pull/2348); see also [discussion \#1960](https://github.com/ESCOMP/CTSM/discussions/1960)) -* New initial conditions files for f09 ("1-degree" 1850, 2000), f19 (“2-degree” 1850), and ne30 (1850, 1979, 2000) resolutions. +* New initial conditions files for f09 ("1-degree" 1850, 2000), f19 ("2-degree" 1850), and ne30 (1850, 1979, 2000) resolutions. * New crop calendars. ([PR \#2664](https://github.com/ESCOMP/CTSM/pull/2664); informed by [Rabin et al., 2023](https://gmd.copernicus.org/articles/16/7253/2023/gmd-16-7253-2023.html)) * Dust emissions method is now `Leung_2023` (links above). * Excess ice is turned on. ([PR \#1787](https://github.com/ESCOMP/CTSM/pull/1787)) @@ -35,8 +35,8 @@ Changes for all physics versions: ### Heads up -* Small glacier changes mean that you can’t use a 5.3 surface dataset with pre-5.3 code and vice versa anymore. (Merged with [PR \#2500](https://github.com/ESCOMP/CTSM/pull/2500)) -* Updates the definition of history variable “time” from *end* of `time_bounds` to *middle* of `time_bounds`. ([PR \#2838](https://github.com/ESCOMP/CTSM/pull/2838); see section below) +* Small glacier changes mean that you can't use a 5.3 surface dataset with pre-5.3 code and vice versa anymore. (Merged with [PR \#2500](https://github.com/ESCOMP/CTSM/pull/2500)) +* Updates the definition of history variable "time" from *end* of `time_bounds` to *middle* of `time_bounds`. ([PR \#2838](https://github.com/ESCOMP/CTSM/pull/2838); see section below) * Standardizes history variable attributes and a history dimension name. ([PR \#2052](https://github.com/ESCOMP/CTSM/pull/2052); see section below) ## @@ -49,7 +49,7 @@ Changes for all physics versions: Startup and hybrid runs no longer run the 0th time step, consistent with the same change in CAM. (Branch and continue runs never had this 0th time step.) This means you will not get an extraneous initial history file anymore. In some circumstances this may also affect the names of history files. -In most cases, the history `time` variable is now defined as the middle of a history file’s `time_bounds` instead of the end, for consistency with the same change in CAM. The exception is if you specify `hist_avgflag_pertape = 'I'` for that file, in which case it will be treated as an “instantaneous” file. Instantaneous history files (a) have their `time` coordinate set to the end of the last timestep (as did all history files before this tag) and (b) do not include `time_bounds`. +In most cases, the history `time` variable is now defined as the middle of a history file's `time_bounds` instead of the end, for consistency with the same change in CAM. The exception is if you specify `hist_avgflag_pertape = 'I'` for that file, in which case it will be treated as an "instantaneous" file. Instantaneous history files (a) have their `time` coordinate set to the end of the last timestep (as did all history files before this tag) and (b) do not include `time_bounds`. The history dimension name `hist_interval` (of output variable `time_bounds`) is standardized to be `nbnd`. History variables `time_bounds`, `mcdate`, `mcsec`, `mdcur`, and `mscur` are standardized to include the calendar attribute. @@ -77,7 +77,7 @@ The history dimension name `hist_interval` (of output variable `time_bounds`) is ### Changes to rpointer files -The rpointer files are simple text files that CESM uses to keep track of how far simulations have progressed, pointing to the filename of the latest restart file for that component. There is one such file for each component, so for CTSM `I` cases that's `lnd`, `cpl`, and `atm` (and `rof` if it's active). Normally, when the user is just extending the length of simulations, there’s no need to worry about these files. +The rpointer files are simple text files that CESM uses to keep track of how far simulations have progressed, pointing to the filename of the latest restart file for that component. There is one such file for each component, so for CTSM `I` cases that's `lnd`, `cpl`, and `atm` (and `rof` if it's active). Normally, when the user is just extending the length of simulations, there's no need to worry about these files. However, if there was a problem when a simulation shut down, it's possible that different components will have mismatched restarts and rpointer files. In the past, this meant figuring out what restart file should be pointed to in each component rpointer file and correcting it by hand in an editor. There was only the final set of rpointer files that was kept for a case. diff --git a/doc/WhatsNewInCTSM5.4.md b/doc/WhatsNewInCTSM5.4.md index 17b43d9f80..4cd4584245 100755 --- a/doc/WhatsNewInCTSM5.4.md +++ b/doc/WhatsNewInCTSM5.4.md @@ -14,7 +14,7 @@ * Unsupported script that checks for spinup equilibrium in `tools/contrib/` for spectral element grids ([PR #2991](https://github.com/ESCOMP/ctsm/pull/2991)). * New paramfile tools that allow users to query and modify CLM parameter files ([documentation](https://escomp.github.io/CTSM/users_guide/using-clm-tools/paramfile-tools.html)) -* Optional time-evolving \`leafcn\_target\`. More under “Additional detail” below. +* Optional time-evolving \`leafcn\_target\`. More under "Additional detail" below. * New vertical movement scheme for soil nitrate, which is off by default (PR [#2992](https://github.com/ESCOMP/CTSM/pull/2992)). * Documentation improvements and new URL: https://escomp.github.io/CTSM/index.html. * FATES: @@ -32,9 +32,9 @@ Changes to defaults for \`clm6\` physics: * Updates to MEGAN for BVOCs (https://github.com/ESCOMP/CTSM/pull/3065 https://github.com/ESCOMP/CTSM/pull/3309). Removes dependence on soil moisture from clm6 physics. * New model parameter values that were calibrated to improve carbon cycle representation with CRUJRA. * New model parameter values that were calibrated to improve the fire model. Now using li2024 fire code. -* New initial conditions files for f09 ("1-degree" 1850, 2000), f19 (“2-degree” 1850), and ne30 (1850, 1979, 2000\) resolutions. +* New initial conditions files for f09 ("1-degree" 1850, 2000), f19 ("2-degree" 1850), and ne30 (1850, 1979, 2000\) resolutions. * Change default for glcmec\_downscale\_longwave to FALSE for clm6 physics as turning off the LW downscaling improves the melt and runoff biases. -* See “Changes to FATES and the FATES parameter file” below. +* See "Changes to FATES and the FATES parameter file" below. * Namelist defaults change so that * use\_c13/use\_c14 are on only for HistClm60Bgc compsets with CRUJRA2024 or CAM7 forcing; examples of when use\_c13/use\_c14 are now off include SSP and single-point compsets, as well as cases using older forcings, such as CAM6, GSWP3v1, Qian, and CRUv7 * when use\_c13 or use\_c14 is on, turn on the corresponding time series file (responding to the CLM_CMIP_ERA flag) @@ -44,13 +44,13 @@ Changes to defaults for \`clm6\` physics: Changes for all physics versions: * Parameters updated: Added MIMICS parameter \`mimics\_fi\` (fraction of litter inputs that bypass litter pools, directly contributing to SOM) and updated other MIMICS parameters (https://github.com/ESCOMP/CTSM/pull/2365) to remove NPP control on turnover, fix density dependent control on turnover, add litterfall fluxes that bypass litter pools and contribute directly to soil organic matter. -* FATES parameter file updated: ([PR \#2965](https://github.com/ESCOMP/CTSM/pull/2965), [PR \#2904](https://github.com/ESCOMP/CTSM/pull/2904), [PR \#1344](https://github.com/NGEET/fates/pull/1344), [PR \#3087](https://github.com/ESCOMP/CTSM/pull/3087)). See “FATES parameter file” section below for details. -* New surface datasets and landuse timeseries files (see “surface datasets” section below). +* FATES parameter file updated: ([PR \#2965](https://github.com/ESCOMP/CTSM/pull/2965), [PR \#2904](https://github.com/ESCOMP/CTSM/pull/2904), [PR \#1344](https://github.com/NGEET/fates/pull/1344), [PR \#3087](https://github.com/ESCOMP/CTSM/pull/3087)). See "FATES parameter file" section below for details. +* New surface datasets and landuse timeseries files (see "surface datasets" section below). * CMIP7 C13/C14 atmospheric timeseries data ## Heads up -* History tapes now split into two files from hX to hXi and hXa, where X is the tape number (e.g. h0i/h0a) and where "i" stands for history file containing instantaneous fields, while "a" stands for history file containing non-instantaneous fields. Details in the “history files” section below and in the PRs https://github.com/ESCOMP/ctsm/pull/2445 https://github.com/ESCOMP/MOSART/pull/117 https://github.com/ESCOMP/RTM/pull/61 and the corresponding issues. +* History tapes now split into two files from hX to hXi and hXa, where X is the tape number (e.g. h0i/h0a) and where "i" stands for history file containing instantaneous fields, while "a" stands for history file containing non-instantaneous fields. Details in the "history files" section below and in the PRs https://github.com/ESCOMP/ctsm/pull/2445 https://github.com/ESCOMP/MOSART/pull/117 https://github.com/ESCOMP/RTM/pull/61 and the corresponding issues. * Adding time to 1d weighting fields in transient simulations PR https://github.com/ESCOMP/CTSM/pull/3328 * Regarding CMIP7 vs. CMIP6 inputs: * C13/C14 isotope datasets are the new CMIP7 datasets using streams, while when CLM_CMIP_ERA==cmip6, the older cmip6 files are used @@ -59,14 +59,14 @@ Changes for all physics versions: * For DATM we supply only CMIP6 aerosols. * For DATM we supply only CMIP6 CO2. * Issue with DOUT\_S\_SAVE\_INTERIM\_REST [https://github.com/ESCOMP/CTSM/issues/3351](https://github.com/ESCOMP/CTSM/issues/3351) was fixed. -* As of ctsm5.3.040, the new ctsm\_pylib conda environment is incompatible with our tools from before ctsm5.3.040 and vice versa. More under “Additional detail” below. +* As of ctsm5.3.040, the new ctsm\_pylib conda environment is incompatible with our tools from before ctsm5.3.040 and vice versa. More under "Additional detail" below. # Additional detail ## Changes related to history files (Note 1: The same information in this section applies to MOSART and RTM. -Note 2: The gist of the information in this section also appears in the [CTSM User’s Guide](https://escomp.github.io/CTSM/users_guide/setting-up-and-running-a-case/customizing-the-clm-namelist.html#various-ways-to-change-history-output-averaging-flags)). +Note 2: The gist of the information in this section also appears in the [CTSM User's Guide](https://escomp.github.io/CTSM/users_guide/setting-up-and-running-a-case/customizing-the-clm-namelist.html#various-ways-to-change-history-output-averaging-flags)). Following ctsm5.3.018 "Change history time to be the middle of the time bounds" and keeping CLM history consistent with CAM history, the CTSM5.4 change intends to prevent confusion associated with the time corresponding to instantaneous history fields by putting them on separate files than non-instantaneous fields. @@ -99,7 +99,7 @@ The CLM handles empty history (and corresponding history-restart) files by not g ## Changes to FATES and the FATES parameter file -* See [HLM-FATES compatibility table](https://fates-users-guide.readthedocs.io/en/latest/user/release-tags-compat-table.html) in the FATES user’s guide for all FATES tags associated with CTSM tag updates +* See [HLM-FATES compatibility table](https://fates-users-guide.readthedocs.io/en/latest/user/release-tags-compat-table.html) in the FATES user's guide for all FATES tags associated with CTSM tag updates * FATES answer changing updates * The default hydro solver is updated to 2D Picard from 1D Taylor ([ctsm5.3.027](https://github.com/ESCOMP/CTSM/releases/tag/ctsm5.3.027)) * Simplified leaf sun-shade fraction for two-stream radiation ([sci.1.83.0\_api.39.0.0](https://github.com/NGEET/fates/releases/tag/sci.1.83.0_api.39.0.0)) diff --git a/doc/doc-builder b/doc/doc-builder index 243025ac2b..6607280dd7 160000 --- a/doc/doc-builder +++ b/doc/doc-builder @@ -1 +1 @@ -Subproject commit 243025ac2bb2050f0b2088b21351cca212248648 +Subproject commit 6607280dd7a96d5606fbd6e8abe547ac0da4d62f diff --git a/doc/source/tech_note/CN_Pools/CLM50_Tech_Note_CN_Pools.rst b/doc/source/tech_note/CN_Pools/CLM50_Tech_Note_CN_Pools.rst index ebff41577a..80f3e95398 100644 --- a/doc/source/tech_note/CN_Pools/CLM50_Tech_Note_CN_Pools.rst +++ b/doc/source/tech_note/CN_Pools/CLM50_Tech_Note_CN_Pools.rst @@ -23,61 +23,73 @@ In addition to the vegetation pools, CLM includes a series of decomposing carbon Tissue Stoichiometry ----------------------- -As of CLM5, vegetation tissues have a flexible stoichiometry, as described in :ref:`Ghimire et al. (2016) `. Each tissue has a target C\:N ratio, with the target leaf C\:N varying by plant functional type (see :numref:`Table Plant functional type (PFT) target CN parameters`), and nitrogen is allocated at each timestep in order to allow the plant to best match the target stoichiometry. Nitrogen downregulation of productivity acts by increasing the C\:N ratio of leaves when insufficient nitrogen is available to meet stoichiometric demands of leaf growth, thereby reducing the N available for photosynthesis and reducing the :math:`V_{\text{c,max25}}` and :math:`J_{\text{max25}}` terms, as described in Chapter :numref:`rst_Photosynthetic Capacity`. Details of the flexible tissue stoichiometry are described in Chapter :numref:`rst_CN Allocation`. - -.. _Table Plant functional type (PFT) target CN parameters: - -.. table:: Plant functional type (PFT) target C:N parameters. - - +----------------------------------+-------------------+ - | PFT | target leaf C:N | - +==================================+===================+ - | NET Temperate | 58.00 | - +----------------------------------+-------------------+ - | NET Boreal | 58.00 | - +----------------------------------+-------------------+ - | NDT Boreal | 25.81 | - +----------------------------------+-------------------+ - | BET Tropical | 29.60 | - +----------------------------------+-------------------+ - | BET temperate | 29.60 | - +----------------------------------+-------------------+ - | BDT tropical | 23.45 | - +----------------------------------+-------------------+ - | BDT temperate | 23.45 | - +----------------------------------+-------------------+ - | BDT boreal | 23.45 | - +----------------------------------+-------------------+ - | BES temperate | 36.42 | - +----------------------------------+-------------------+ - | BDS temperate | 23.26 | - +----------------------------------+-------------------+ - | BDS boreal | 23.26 | - +----------------------------------+-------------------+ - | C\ :sub:`3` arctic grass | 28.03 | - +----------------------------------+-------------------+ - | C\ :sub:`3` grass | 28.03 | - +----------------------------------+-------------------+ - | C\ :sub:`4` grass | 35.36 | - +----------------------------------+-------------------+ - | Temperate Corn | 25.00 | - +----------------------------------+-------------------+ - | Spring Wheat | 20.00 | - +----------------------------------+-------------------+ - | Temperate Soybean | 20.00 | - +----------------------------------+-------------------+ - | Cotton | 20.00 | - +----------------------------------+-------------------+ - | Rice | 20.00 | - +----------------------------------+-------------------+ - | Sugarcane | 25.00 | - +----------------------------------+-------------------+ - | Tropical Corn | 25.00 | - +----------------------------------+-------------------+ - | Tropical Soybean | 20.00 | - +----------------------------------+-------------------+ - | Miscanthus | 25.00 | - +----------------------------------+-------------------+ - | Switchgrass | 25.00 | - +----------------------------------+-------------------+ +As of CLM5, vegetation tissues have a flexible stoichiometry, as described in :ref:`Ghimire et al. (2016) `. Each tissue has a target C\:N ratio, with the target leaf C\:N, :math:`CN_{\text{target}}^\text{pft}`, varying by plant functional type (PFT) (:numref:`Table PFT target leaf CN`). Nitrogen is allocated at each timestep to allow the plant to best match the target stoichiometry. Nitrogen downregulation of productivity acts by increasing the actual C\:N ratio of leaves when insufficient nitrogen is available to meet stoichiometric demands of leaf growth, thereby reducing the N available for photosynthesis and reducing the :math:`V_{\text{c,max25}}` and :math:`J_{\text{max25}}` terms, as described in Chapter :numref:`rst_Photosynthetic Capacity`. Details of the flexible tissue stoichiometry are described in Chapter :numref:`rst_CN Allocation`. + +As of CLM5.4, the target leaf C\:N may be time-evolving, :math:`CN_{\text{target}}^{\text{pft,CO2}}`, as a logarithmic function of atmospheric CO\ :sub:`2` that we denote :math:`CN_{\text{perturb}}^{\text{CO2}}`: + +.. math:: + :label: time-evolv target leaf CN + + \begin{split} + CN_{\text{perturb}}^{\text{CO2}} &= CN_{\text{slope}}^{\text{CO2}} \cdot \ln\left(\frac{\text{CO2}_{\text{atm}}}{\text{CO2}_{\text{atm}}^{\text{ref}}}\right), \text{where } CN_{\text{perturb}}^{\text{CO2}} &\ge 0 \\ + CN_{\text{target}}^{\text{pft,CO2}} &= CN_{\text{target}}^\text{pft} + CN_{\text{perturb}}^{\text{CO2}} + \end{split} + +where :math:`CN_{\text{target}}^\text{pft}` is the time-invarying target leaf C\:N at reference CO\ :sub:`2` that depends on PFT, :math:`CN_{\text{slope}}^{\text{CO2}}` (unitless) is the slope of the function, :math:`\text{CO2}_{\text{atm}}` is atmospheric CO\ :sub:`2` in parts per million by volume (ppmv), and :math:`\text{CO2}_{\text{atm}}^{\text{ref}}` is the reference CO\ :sub:`2` (ppmv) above which atmospheric CO\ :sub:`2` begins to scale the target leaf C\:N. The optional time-evolving target leaf C\:N was documented in :ref:`Hauser et al. (2023) `, and its current default is off by setting :math:`CN_{\text{slope}}^{\text{CO2}} = 0`. + +.. _Table PFT target leaf CN: + +.. table:: Plant functional type (PFT) target leaf C:N, :math:`CN_{\text{target}}^\text{pft}`. + + +--------------------------+-----------------+ + | PFT | target leaf C:N | + +==========================+=================+ + | NET Temperate | 58.00 | + +--------------------------+-----------------+ + | NET Boreal | 60.24 | + +--------------------------+-----------------+ + | NDT Boreal | 28.92 | + +--------------------------+-----------------+ + | BET Tropical | 36.03 | + +--------------------------+-----------------+ + | BET temperate | 34.59 | + +--------------------------+-----------------+ + | BDT tropical | 18.63 | + +--------------------------+-----------------+ + | BDT temperate | 21.64 | + +--------------------------+-----------------+ + | BDT boreal | 17.09 | + +--------------------------+-----------------+ + | BES temperate | 36.42 | + +--------------------------+-----------------+ + | BDS temperate | 23.26 | + +--------------------------+-----------------+ + | BDS boreal | 21.40 | + +--------------------------+-----------------+ + | C\ :sub:`3` arctic grass | 20.70 | + +--------------------------+-----------------+ + | C\ :sub:`3` grass | 29.39 | + +--------------------------+-----------------+ + | C\ :sub:`4` grass | 35.36 | + +--------------------------+-----------------+ + | Temperate Corn | 25.00 | + +--------------------------+-----------------+ + | Spring Wheat | 20.00 | + +--------------------------+-----------------+ + | Temperate Soybean | 20.00 | + +--------------------------+-----------------+ + | Cotton | 20.00 | + +--------------------------+-----------------+ + | Rice | 20.00 | + +--------------------------+-----------------+ + | Sugarcane | 25.00 | + +--------------------------+-----------------+ + | Tropical Corn | 25.00 | + +--------------------------+-----------------+ + | Tropical Soybean | 20.00 | + +--------------------------+-----------------+ + | Miscanthus | 20.00 | + +--------------------------+-----------------+ + | Switchgrass | 20.00 | + +--------------------------+-----------------+ diff --git a/doc/source/tech_note/Decomposition/CLM50_Tech_Note_Decomposition.rst b/doc/source/tech_note/Decomposition/CLM50_Tech_Note_Decomposition.rst index bf6d52ee45..bc66464cc1 100644 --- a/doc/source/tech_note/Decomposition/CLM50_Tech_Note_Decomposition.rst +++ b/doc/source/tech_note/Decomposition/CLM50_Tech_Note_Decomposition.rst @@ -189,7 +189,7 @@ where :math:`{\Psi}_{j}` is the soil water potential in layer *j*, :math:`{\Psi} \psi \left(T\right)=-\frac{L_{f} \left(T-T_{f} \right)}{10^{3} T} -An additional frozen decomposition limitation can be specified using a ‘frozen Q\ :sub:`10`' following :ref:`Koven et al. (2011) `, however the default value of this is the same as the unfrozen Q\ :sub:`10` value, and therefore the basic hypothesis is that frozen respiration is limited by liquid water availability, and can be modeled following the same approach as thawed but dry soils. +An additional frozen decomposition limitation can be specified using a 'frozen Q\ :sub:`10`' following :ref:`Koven et al. (2011) `, however the default value of this is the same as the unfrozen Q\ :sub:`10` value, and therefore the basic hypothesis is that frozen respiration is limited by liquid water availability, and can be modeled following the same approach as thawed but dry soils. An additional rate scalar, :math:`{r}_{oxygen}` is enabled when the CH\ :sub:`4` submodel is used (set equal to 1 for the single layer model or when the CH\ :sub:`4` submodel is disabled). This limits decomposition when there is insufficient molecular oxygen to satisfy stoichiometric demand (1 mol O\ :sub:`2` consumed per mol CO\ :sub:`2` produced) from heterotrophic decomposers, and supply from diffusion through soil layers (unsaturated and saturated) or aerenchyma (Chapter 19). A minimum value of :math:`{r}_{oxygen}` is set at 0.2, with the assumption that oxygen within organic tissues can supply the necessary stoichiometric demand at this rate. This value lies between estimates of 0.025–0.1 (Frolking et al. 2001), and 0.35 (Wania et al. 2009); the large range of these estimates poses a large unresolved uncertainty. diff --git a/doc/source/tech_note/External_Nitrogen_Cycle/CLM50_Tech_Note_External_Nitrogen_Cycle.rst b/doc/source/tech_note/External_Nitrogen_Cycle/CLM50_Tech_Note_External_Nitrogen_Cycle.rst index d1c476099d..345693c40c 100644 --- a/doc/source/tech_note/External_Nitrogen_Cycle/CLM50_Tech_Note_External_Nitrogen_Cycle.rst +++ b/doc/source/tech_note/External_Nitrogen_Cycle/CLM50_Tech_Note_External_Nitrogen_Cycle.rst @@ -3,63 +3,40 @@ External Nitrogen Cycle =========================== -.. _Summary of CLM5.0 updates relative to CLM4.5: - -Summary of CLM5.0 updates relative to CLM4.5 ------------------------------------------------------ - -We describe external inputs to the nitrogen cycle in CLM5.0.  Much of the following information appeared in the CLM4.5 Technical Note (:ref:`Oleson et al. 2013 `) as well as :ref:`Koven et al. (2013) `. - -CLM5.0 includes the following changes to terrestrial nitrogen inputs: - -- Time varrying deposition of reactive nitrogen. In off-line runs this changes monthly. In coupled simulations N deposition is passed at the coupling timestep (e.g., half-hourly). - -- Asymbiotic (or free living) N fixation is a function of evapotranspiration and is added to the inorganic nitrogen (NH\ :sub:`4`\ :sup:`+`) pool (described below). - -- Symbiotic N fixation is handled by the FUN model (chapter :numref:`rst_FUN`) and is passed straight to the plant, not the mineral nitrogen pool. Overview ----------------------------------------------------- In addition to the relatively rapid cycling of nitrogen within the plant – litter – soil organic matter system, CLM also represents several processes which couple the internal nitrogen cycle to external sources and sinks. Inputs of new mineral nitrogen are from atmospheric deposition and biological nitrogen fixation. Losses of mineral nitrogen are due to nitrification, denitrification, leaching, and losses in fire. While the short-term dynamics of nitrogen limitation depend on the behavior of the internal nitrogen cycle, establishment of total ecosystem nitrogen stocks depends on the balance between sources and sinks in the external nitrogen cycle (:ref:`Thomas et al. 2015 `). -As with CLM4.5, CLM5.0 represents inorganic N transformations based on the Century N-gas model; this includes separate NH\ :sub:`4`\ :sup:`+` and NO\ :sub:`3`\ :sup:`-` pools, as well as environmentally controlled nitrification and denitrification rates that is described below. +CLM represents inorganic N transformations based on the Century N-gas model; this includes separate NH\ :sub:`4`\ :sup:`+` and NO\ :sub:`3`\ :sup:`-` pools, as well as environmentally controlled nitrification and denitrification rates that is described below. Atmospheric Nitrogen Deposition ------------------------------------ -CLM uses a single variable to represent the total deposition of mineral nitrogen onto the land surface, combining wet and dry deposition of NO\ :sub:`y` and NH\ :sub:`x` as a single flux (:math:`{NF}_{ndep\_sminn}`, gN m\ :sup:`-2` s\ :sup:`-1`). This flux is intended to represent total reactive nitrogen deposited to the land surface which originates from the following natural and anthropogenic sources (Galloway et al. 2004): formation of NO\ :sub:`x` during lightning, NO\ :math:`{}_{x }`\ and NH\ :sub:`3` emission from wildfire, NO\ :sub:`x` emission from natural soils, NH\ :sub:`3` emission from natural soils, vegetation, and wild animals, NO\ :sub:`x` and NH\ :sub:`3` emission during fossil fuel combustion (both thermal and fuel NO\ :sub:`x` production), NO\ :sub:`x` and NH\ :sub:`3` emission from other industrial processes, NO\ :sub:`x` and NH\ :sub:`3` emission from fire associated with deforestation, NO\ :sub:`x` and NH\ :sub:`3` emission from agricultural burning, NO\ :sub:`x` emission from agricultural soils, NH\ :sub:`3` emission from agricultural crops, NH\ :sub:`3` emission from agricultural animal waste, and NH\ :sub:`3` emission from human waste and waste water. The deposition flux is provided as a spatially and (potentially) temporally varying dataset (see section :numref:`Atmospheric Coupling` for a description of the default input dataset). +CLM uses a single variable to represent the total deposition of mineral nitrogen onto the land surface, combining wet and dry deposition of NO\ :sub:`y` and NH\ :sub:`x` as a single flux (:math:`{NF}_{ndep\_sminn}`, gN m\ :sup:`-2` s\ :sup:`-1`). This flux is intended to represent total reactive nitrogen deposited to the land surface which originates from the following natural and anthropogenic sources (Galloway et al. 2004): formation of NO\ :sub:`x` during lightning, NO\ :sub:`x`\ and NH\ :sub:`3` emission from wildfire, NO\ :sub:`x` emission from natural soils, NH\ :sub:`3` emission from natural soils, vegetation, and wild animals, NO\ :sub:`x` and NH\ :sub:`3` emission during fossil fuel combustion (both thermal and fuel NO\ :sub:`x` production), NO\ :sub:`x` and NH\ :sub:`3` emission from other industrial processes, NO\ :sub:`x` and NH\ :sub:`3` emission from fire associated with deforestation, NO\ :sub:`x` and NH\ :sub:`3` emission from agricultural burning, NO\ :sub:`x` emission from agricultural soils, NH\ :sub:`3` emission from agricultural crops, NH\ :sub:`3` emission from agricultural animal waste, and NH\ :sub:`3` emission from human waste and waste water. The deposition flux is provided as a spatially and temporally varying dataset (see section :numref:`Atmospheric Coupling` for a description of the default input dataset). -The nitrogen deposition flux is assumed to enter the NH\ :sub:`4`\ :sup:`+` pool, and is vertically distributed throughout the soil profile. Although N deposition inputs include both oxidized and reduced forms, CLM5 only reads in total N deposition. This approach is held over from CLM4.0, which only represented a single mineral nitrogen pool, however, real pathways for wet and dry nitrogen deposition can be more complex than currently represented in the CLM5.0, including release from melting snowpack and direct foliar uptake of deposited NO\ :sub:`y` (:ref:`Tye et al. 2005 `; :ref:`Vallano and Sparks, 2007 `). +The nitrogen deposition flux is assumed to enter the NH\ :sub:`4`\ :sup:`+` pool, and is vertically distributed throughout the soil profile. Although N deposition inputs include both oxidized and reduced forms, CLM5.0 and CLM6.0 only read in total N deposition. This approach is held over from CLM4.0, which only represented a single mineral nitrogen pool, however, real pathways for wet and dry nitrogen deposition can be more complex than currently represented in CLM, including release from melting snowpack and direct foliar uptake of deposited NO\ :sub:`y` (:ref:`Tye et al. 2005 `; :ref:`Vallano and Sparks, 2007 `). -In offline (uncoupled) CLM5.0 simulations monthly estimates of N deposition are provided, as opposed to decadal files supplied with previous versions of the model. In coupled simulations, N depositions fluxes are passed to the land model at the frequency of the time step (every half hour) through the coupler. +As of CLM5.0, in off line (uncoupled) simulations monthly estimates of N deposition are provided, In coupled simulations, N depositions fluxes are passed to the land model at the frequency of the time step (every half hour) through the coupler. Biological Nitrogen Fixation --------------------------------- +The fixation of new reactive nitrogen from atmospheric N\ :sub:`2` by soil microorganisms is an important component of both preindustrial and modern-day nitrogen budgets, but a mechanistic understanding of global-scale controls on biological nitrogen fixation (BNF) is still only poorly developed (:ref:`Cleveland et al. 1999 `; :ref:`Galloway et al. 2004 `). CLM5 introduced a new representation of biological nitrogen fixation (BNF) that includes both symbiotic and free-living (asymbiotic) components. The symbiotic component is calculated using the Fixation and Uptake of Nitrogen (FUN) model (chapter :numref:`rst_FUN`) to calculate the carbon cost of nitrogen fixation and the amount of nitrogen acquired through symbiotic fixation. This nitrogen is immediately available to plants. One drawback to this approach is that under elevated CO2, when plant productivity increases, FUN predicts increased rates of symbiotic nitrogen fixation, which may not be realistic (:ref:`Wieder et al. 2019 `; :ref:`Kou-Giesbrecht et al. 2025 `). Future work should address this issue. -The fixation of new reactive nitrogen from atmospheric N\ :sub:`2` by soil microorganisms is an important component of both preindustrial and modern-day nitrogen budgets, but a mechanistic understanding of global-scale controls on biological nitrogen fixation (BNF) is still only poorly developed (:ref:`Cleveland et al. 1999 `; :ref:`Galloway et al. 2004 `). CLM5.0 uses the FUN model (chapter :numref:`rst_FUN`) to calculate the carbon cost and nitrogen acquired through symbotic nitrogen fixation. This nitrogen is immediately available to plants. - -:ref:`Cleveland et al. (1999) ` suggested an empirical relationships that predicts BNF as a function of either evapotranspiration rate or net primary productivity for natural vegetation. CLM5.0 adopts the evapotranspiration approach to calculate asymbiotic, or free-living, N fixation. This function has been modified from the :ref:`Cleveland et al. (1999) ` estimates to provide lower estimate of free-living nitrogen fixation in CLM5.0 (:math:`{CF}_{ann\_ET}`, mm yr\ :sup:`-1`). This moves away from the NPP approach used in CLM4.0 and 4.5 and avoids unrealistically increasing freeliving rates of N fixation under global change scenarios (:ref:`Wieder et al. 2015 ` The expression used is: +The free-living component is calculated using an empirical relationship following :ref:`Cleveland et al. (1999) ` who suggested using either evapotranspiration rate or net primary productivity to predicts rates of BNF for natural vegetation. CLM5.0 adopted the evapotranspiration approach to calculate asymbiotic, or free-living, N fixation. This function has been modified from the :ref:`Cleveland et al. (1999) ` estimates to provide lower estimate of free-living nitrogen fixation in CLM (:math:`{CF}_{ann\_ET}`, mm yr\ :sup:`-1`). This moves away from the NPP approach used in CLM4.0 and 4.5 and avoids unrealistically increasing freeliving rates of N fixation under global change scenarios (:ref:`Wieder et al. 2015 `). The expression used is: .. math:: :label: 22.1) NF_{nfix,sminn} ={0.0006\left(0.0117+CF_{ann\_ ET}\right)\mathord{\left/ {\vphantom {0.0006\left(0.0117+ CF_{ann\_ ET}\right) \left(86400\cdot 365\right)}} \right.} \left(86400\cdot 365\right)} -Where :math:`{NF}_{nfix,sminn}` (gN m\ :sup:`-2` s\ :sup:`-1`) is the rate of free-living nitrogen fixation in :numref:`Figure Biological nitrogen fixation`. - -.. _Figure Biological nitrogen fixation: - -.. figure:: image1.png - - Free-living nitrogen fixation as a function of annual evapotranspiration. Results here show annual N inputs from free-living N fixations, but the model actually calculates inputs on a per second basis. - -As with Atmospheric N deposition, free-living N inputs are added directly to the NH\ :sub:`4`\ :sup:`+` pool. +Where :math:`{NF}_{nfix,sminn}` (gN m\ :sup:`-2` s\ :sup:`-1`) is the rate of free-living nitrogen fixation, calculated on a per second basis. As with atmospheric N deposition, free-living N inputs are added directly to the soil NH\ :sub:`4`\ :sup:`+` pool. Nitrification and Denitrification Losses of Nitrogen --------------------------------------------------------- -Nitrification is an autotrophic process that converts less mobile ammonium ions into nitrate, that can more easily be lost from soil systems by leaching or denitrification. The process catalyzed by ammonia oxidizing archaea and bacteria that convert ammonium (NH\ :sub:`4`\ :sup:`+`) into nitrite, which is subsequently oxidized into nitrate (NO\ :sub:`3`\ :sup:`-`). Conditions favoring nitrification include high NH\ :sub:`4`\ :sup:`+` concentrations, well aerated soils, a neutral pH and warmer temperatures. +Nitrification is an autotrophic process that converts less mobile ammonium ions into nitrate, that can more easily be lost from soil systems by leaching or denitrification. The process catalyzed by ammonia oxidizing archaea and bacteria that convert ammonium (NH\ :sub:`4`\ :sup:`+`) into nitrite, which is subsequently oxidized into nitrate (NO\ :sub:`3`\ :sup:`-`). Conditions favoring nitrification include high NH\ :sub:`4`\ :sup:`+` concentrations, well aerated soils, a neutral pH, and warmer temperatures. Under aerobic conditions in the soil oxygen is the preferred electron acceptor supporting the metabolism of heterotrophs, but anaerobic conditions favor the activity of soil heterotrophs which use nitrate as an electron acceptor (e.g. *Pseudomonas* and *Clostridium*) supporting respiration. This process, known as denitrification, results in the transformation of nitrate to gaseous N\ :sub:`2`, with smaller associated production of NO\ :sub:`x` and N\ :sub:`2`\ O. It is typically assumed that nitrogen fixation and denitrification were approximately balanced in the preindustrial biosphere ( :ref:`Galloway et al. 2004 `). It is likely that denitrification can occur within anaerobic microsites within an otherwise aerobic soil environment, leading to large global denitrification fluxes even when fluxes per unit area are rather low (:ref:`Galloway et al. 2004 `). @@ -70,7 +47,7 @@ CLM includes a detailed representation of nitrification and denitrification base f_{nitr,p} =\left[NH_{4} \right]k_{nitr} f\left(T\right)f\left(H_{2} O\right)f\left(pH\right) -where :math:`{f}_{nitr,p}` is the potential nitrification rate (prior to competition for NH\ :sub:`4`\ :sup:`+` by plant uptake and N immobilization), :math:`{k}_{nitr}` is the maximum nitrification rate (10 % day\ :math:`\mathrm{-}`\ 1, (:ref:`Parton et al. 2001 `), and *f(T)* and *f(H\)*\ :sub:`2`\ O) are rate modifiers for temperature and moisture content. CLM uses the same rate modifiers as are used in the decomposition routine. *f(pH)* is a rate modifier for pH; however, because CLM does not calculate pH, instead a fixed pH value of 6.5 is used in the pH function of :ref:`Parton et al. (1996) `. +where :math:`{f}_{nitr,p}` is the potential nitrification rate (prior to competition for NH\ :sub:`4`\ :sup:`+` by plant uptake and N immobilization), :math:`{k}_{nitr}` is the maximum nitrification rate (10 % day\ :math:`\mathrm{-}`\ 1, (:ref:`Parton et al. 2001 `), and *f(T)* and *f(H\)*\ :sub:`2`\ O) are rate modifiers for temperature and moisture content. CLM uses the same rate modifiers as are used in the decomposition routine. *f(pH)* is a rate modifier for pH. Although new surface datasets in CLM6.0 provide gridded estimates for soil pH, this information is not currently being used in the model. Instead, a fixed pH value of 6.5 is used in the pH function of :ref:`Parton et al. (1996) `. The potential denitrification rate is co-limited by NO\ :sup:`-3` concentration and C consumption rates, and occurs only in the anoxic fraction of soils: @@ -86,7 +63,7 @@ where :math:`{f}_{denitr,p}` is the potential denitrification rate and *f(decomp frac_{anox} =\exp \left(-aR_{\psi }^{-\alpha } V^{-\beta } C^{\gamma } \left[\theta +\chi \varepsilon \right]^{\delta } \right) -where *a*, :math:`\alpha`, :math:`\beta`, :math:`\gamma`, and :math:`\delta` are constants (equal to 1.5x10\ :sup:`-10`, 1.26, 0.6, 0.6, and 0.85, respectively), :math:`{R}_{\psi}` is the radius of a typical pore space at moisture content :math:`\psi`, *V* is the O\ :sub:`2` consumption rate, *C* is the O\ :sub:`2` concentration, :math:`\theta` is the water-filled pore space, :math:`\chi` is the ratio of diffusivity of oxygen in water to that in air, and :math:`\epsilon` is the air-filled pore space (:ref:`Arah and Vinten (1995) `). These parameters are all calculated separately at each layer to define a profile of anoxic porespace fraction in the soil. +where :math:`a` :math:`\alpha`, :math:`\beta`, :math:`\gamma`, and :math:`\delta` are constants (equal to 1.5x10\ :sup:`-10`, 1.26, 0.6, 0.6, and 0.85, respectively), :math:`{R}_{\psi}` is the radius of a typical pore space at moisture content :math:`\psi`, :math:`V` is the O\ :sub:`2` consumption rate, :math:`C` is the O\ :sub:`2` concentration, :math:`\theta` is the water-filled pore space, :math:`\chi` is the ratio of diffusivity of oxygen in water to that in air, and :math:`\epsilon` is the air-filled pore space (:ref:`Arah and Vinten 1995 `). These parameters are all calculated separately at each layer to define a profile of anoxic porespace fraction in the soil. The nitrification/denitrification models used here also predict fluxes of N\ :sub:`2`\ O via a "hole-in-the-pipe" approach (:ref:`Firestone and Davidson, 1989 `). A constant fraction (6 * 10\ :math:`{}^{-4}`, :ref:`Li et al. 2000 `) of the nitrification flux is assumed to be N\ :sub:`2`\ O, while the fraction of denitrification going to N\ :sub:`2`\ O, \ :math:`{P}_{N2:N2O}`, is variable, following the Century (:ref:`del Grosso et al. 2000 `) approach: @@ -136,8 +113,9 @@ where :math:`{WS}_{tot\_soil}` (kgH\ :sub:`2`\ O m\ :sup:`-2`) is the total mass Alternative way of evaluating the Leaching Losses of Nitrogen -------------------------------------------------------------- -The previous leaching mechanism is not designed for describing the vertical transport of :math:`{NO}_{3}^{-}` in soil, an alternative way to evaluate the vertical convective, diffusive, and dispersive of dissolved :math:`{NO}_{3}^{-}` in soil is provided in (:ref:`Luo et al. 2025 `). -To obtain the vertical profile of soil mineral N after vertical movement of each timestep, the vertical transport equation is summarized in :eq:`22.20`. +Leaching losses of :math:`{NO}_{3}^{-}` are notably low in CLM because of low rates of nitrification and high plant N uptake (:ref:`Houlton et al. 2015 `, :ref:`Nevison et al. 2022 `). Future work should address these biases. + +Towards this end, the previous leaching mechanism is not designed for describing the vertical transport of :math:`{NO}_{3}^{-}` in soil, an alternative way to evaluate the vertical convective, diffusive, and dispersive of dissolved :math:`{NO}_{3}^{-}` in soil is provided in (:ref:`Luo et al. 2025 `). This is option is not active by default in CLM6.0, but can be activated by the user. To obtain the vertical profile of soil mineral N after vertical movement of each timestep, the vertical transport equation is summarized in :eq:`22.20`. .. math:: :label: 22.20 diff --git a/doc/source/tech_note/External_Nitrogen_Cycle/image1.png b/doc/source/tech_note/External_Nitrogen_Cycle/image1.png deleted file mode 100755 index b28b5d1894..0000000000 --- a/doc/source/tech_note/External_Nitrogen_Cycle/image1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f3acfbbb90ad0c44ff7179a257c44f59d4b0b5a0da348825b02aa5034bee1640 -size 29009 diff --git a/doc/source/tech_note/FUN/CLM50_Tech_Note_FUN.rst b/doc/source/tech_note/FUN/CLM50_Tech_Note_FUN.rst index 1c4a43deb6..3b3247bcb9 100644 --- a/doc/source/tech_note/FUN/CLM50_Tech_Note_FUN.rst +++ b/doc/source/tech_note/FUN/CLM50_Tech_Note_FUN.rst @@ -6,7 +6,7 @@ Fixation and Uptake of Nitrogen (FUN) Introduction ----------------- -The Fixation and Uptake of Nitrogen model is based on work by :ref:`Fisher et al. (2010)`, :ref:`Brzostek et al. (2014)`, and :ref:`Shi et al. (2016)`. The concept of FUN is that in most cases, Nitrogen uptake requires the expenditure of energy in the form of carbon, and further, that there are numerous potential sources of Nitrogen in the environment which a plant may exchange for carbon. The ratio of carbon expended to Nitrogen acquired is referred to here as the cost, or exchange rate, of N acquisition (:math:`E_{nacq}`, gC/gN)). There are eight pathways for N uptake: +The Fixation and Uptake of Nitrogen model (FUN) is based on work by :ref:`Fisher et al. (2010)`, :ref:`Brzostek et al. (2014)`, and :ref:`Shi et al. (2016)`, as described in :ref:`Fisher et al. (2019)`.The concept of FUN is that in most cases, nitrogen (N) uptake requires the expenditure of energy in the form of carbon (C), and further, that there are numerous potential sources of N in the environment which a plant may exchange for C. The ratio of carbon expended to nitrogen acquired is referred to here as the cost, or exchange rate, of N acquisition (:math:`E_{nacq}`, gC/gN)). There are eight pathways for N uptake: 1. Fixation by symbiotic bacteria in root nodules (for N fixing plants) (:math:`_{fix}`) 2. Retranslocation of N from senescing tissues (:math:`_{ret}`) @@ -17,12 +17,14 @@ The Fixation and Uptake of Nitrogen model is based on work by :ref:`Fisher et al 7. Nonmycorrhizal uptake of NH4 (:math:`_{nonmyc,nh4}`) 8. Nonmycorrhizal uptake of NO3 (:math:`_{nonmyc,no3}`) -The notation suffix for each pathway is given in parentheses here. At each timestep, each of these pathways is associated with a cost term (:math:`N_{cost,x}`), a payment in carbon (:math:`C_{nuptake,x}`), and an influx of Nitrogen (:math:`N_{uptake,x}`) where :math:`x` is one of the eight uptake streams listed above. +The notation suffix for each pathway is given in parentheses here. At each timestep, each of these pathways is associated with a cost term (:math:`N_{cost,x}`), a payment in carbon (:math:`C_{nuptake,x}`), and an influx of nitrogen (:math:`N_{uptake,x}`) where :math:`x` is one of the eight uptake streams listed above. -For each PFT, we define a fraction of the total C acquisition that can be used for N fixation (:math:`f_{fixers}`), which is broadly equivalent to the fraction of a given PFT that is capable of fixing Nitrogen, and thus represents an upper limit on the amount to which fixation can be increased in low n conditions. For each PFT, the cost calculation is conducted twice. Once where fixation is possible and once where it is not. (:math:`f_{fixers}`) +For each PFT, we define a fraction of the total C acquisition that can be used for N fixation (:math:`f_{fixers}`), which is broadly equivalent to the fraction of a given PFT that is capable of fixing Nitrogen, and thus represents an upper limit on the amount to which fixation can be increased in low N conditions. For each PFT, the cost calculation is conducted twice. Once where fixation is possible and once where it is not (:math:`f_{fixers}`). For all of the active uptake pathways, whose cost depends on varying concentrations of N through the soil profile, the costs and fluxes are also determined by soil layer :math:`j`. +Notable changes to FUN in CLM6 include: (1) Updated the emperical function describing the temperature sensitivity of nitrogen fixation (:ref:`Bytnerowicz et al. 2022`). (2) Corrected an error in the parameter values for nonmycorrhizal uptake of inorganic N that was published in :ref:`Brzostek et al. (2014)`. And (3) introduced an empirical function that adjusts target leaf C:N ratios with atmospheric concentrations of CO\ :sub:`2` (:ref:`Hauser et al 2023`, this is documented in section :numref:`rst_CN Pools` and is turned off by default in CLM6). We also acknowledge that previously identified limitations of the implementation of FUN in CLM remain. These include a reduction in interannual variability of net ecosystem productivity (:ref:`Wieder et al. 2021`) and strong increases in rates of symbiotic nitrogen fixation under elevated CO\ :sub:`2` (:ref:`Wieder et al. 2019 `; :ref:`Kou-Giesbrecht et al. 2025 `). Future work should address these issues. + Boundary conditions of FUN -------------------------------------------------------- @@ -30,23 +32,54 @@ Available Carbon ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The carbon available for FUN, :math:`C_{avail}` (gC m\ :sup:`-2`) is the total canopy photosynthetic uptake (GPP), minus the maintenance respiration fluxes (:math:`m_r`) and multiplied by the time step in seconds (:math:`\delta t`). Thus, the remainder of this chapter considers fluxes per timestep, and integrates these fluxes as they are calculated. - .. math:: +.. math:: + :label: C_avail_1 C_{avail} = (GPP - m_r) \delta t Growth respiration is thus only calculated on the part of the carbon uptake that remains after expenditure of C by the FUN module. -Available Soil Nitrogen -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Cost of Nitrogen Fixation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The cost of fixation is derived from :ref:`Houlton et al. (2008)`. - .. math:: +Nitrogen fixation rates are temperature dependent. In CLM6 the carbon cost of nitrogen fixation was derived from an empirical function fit to data from a greenhouse experiment measuring nitrogen fixation by woody plants from :ref:`Bytnerowicz et al. (2022)`. CLM5 used a different empirical function to describe the temperature dependence of nitrogenase activity from :ref:`Houlton et al. (2008)`. + +This Bytnerowicz formulation (:math:`F_B`) defines a temperature dependent N fixation rate function as: + +.. math:: + :label: F_B + + F_{B} = \left(\frac{T_{max} - T_{soil}}{T_{max} - T_{opt}}\right) \left(\frac{T_{soil} - T_{min}}{T_{opt} - T_{min}}\right)^{\frac{T_{opt}-T_{min}}{T_{max}-T_{opt}}} + +where :math:`T_{soil}` is soil temperature (°C), and :math:`T_{min}`, :math:`T_{opt}` , and :math:`T_{max}` define the lower bound, optimum, and upper bound of the biome-specific temperature response. The function is unitless and bounded between 0 and 1. The function is calculated separately for each soil layer and weighted by the fraction of roots present in that layer. The rate function is interpreted as a conductance like term for N acquisition, and its inverse is used to represent a temperature-limited carbon cost of nitrogen fixation (:math:`N_{cost,fix}`) to give a temperature limited cost in terms of C to N ratios: + +.. math:: + :label: N_cost_fix_1 + + N_{cost,fix} = \frac{S_{fix}}{F_{B}} + +The minimum cost of N fixation, :math:`S_{fix}`, occurs at :math:`T_{opt}` and is set as 6 gC :math:`\mathrm{gN}^{-1}`. When soil temperature falls outside the range of :math:`T_{min}` and :math:`T_{max}`, the cost of fixation is set to an arbitrarily large value (10\ :sup:`9`) to effectively suppress N fixation. Parameters for :math:`T_{min}`, :math:`T_{opt}`, :math:`T_{max}` differ between tropical and extra tropical plant functional types (PFTs), following the biome specific estimates reported by :ref:`Bytnerowicz et al. (2022)`. Parameter values for tropical and extra-tropical PFTs are as follows: + +\ Tropical: :math:`T_{min}` =7.04, :math:`T_{opt}` =33.22, and :math:`T_{max}` =45.35. + +\ Extra-tropical: :math:`T_{min}` =−2.04, :math:`T_{opt}` =32.10, and :math:`T_{max}` =43.98. + + +The Houlton function used in CLM5 the cost of fixation (:math:`N_{cost,fix}`) calculated as: + +.. math:: + :label: N_cost_fix_2 + + N_{cost,fix} = -S_{fix}/(1.25 e^{a_{fix} + b_{fix} . T_{soil} (1 - 0.5 T_{soil}/ c_{fix}) }) + +Herein, :math:`a_{fix}`, :math:`b_{fix}` and :math:`c_{fix}` are all parameters of the temperature response function of fixation reported by Houlton et al. (2008) (:math:`exp[a+bT_{soil}(1-0.5T_{soil}/c)]`). :math:`T_{soil}` is the soil temperature in C. The values of these parameters are fitted to empirical data as a=-3.62 :math:`\pm` 0.52, b=0.27 :math:`\pm` 0.04 and c=25.15 :math:`\pm` 0.66. The hardwired coefficient 1.25 converts from the temperature response function to a 0-1 limitation factor (as specifically employed by Houlton et al.). This function is a 'rate' of uptake for a given temperature. Here we assimilated the rate of fixation into the cost term by assuming that the rate is analogous to a conductance for N, and inverting the term to produce a cost/resistance analogue. We then multiply this temperature term by the minimum cost at optimal temperature (:math:`S_{fix}`) to give a temperature limited cost in terms of C to N ratios. + +.. _Figure Carbon costs of N fixation as a function of soil temperature: + +.. figure:: image1.png + + Figure Carbon costs of N fixation as a function of soil temperature. Bytnerowicz et al(2022) function for tropical and extra-tropical PFTs (red and blue lines, respectively) that are used in CLM6; and the Houlton et al (2008) function (black line) that was used in CLM5. - N_{cost,fix} = -s_{fix}/(1.25 e^{a_{fix} + b_{fix} . t_{soil} (1 - 0.5 t_{soil}/ c_{fix}) }) -Herein, :math:`a_{fix}`, :math:`b_{fix}` and :math:`c_{fix}` are all parameters of the temperature response function of fixation reported by Houlton et al. (2008) (:math:`exp[a+bT_s(1-0.5T_s/c)`). t_{soil} is the soil temperature in C. The values of these parameters are fitted to empirical data as a=-3.62 :math:`\pm` 0.52, b=0.27:math:`\pm` 0.04 and c=25.15 :math:`\pm` 0.66. 1.25 converts from the temperature response function to a 0-1 limitation factor (as specifically employed by Houlton et al.). This function is a 'rate' of uptake for a given temperature. Here we assimilated the rate of fixation into the cost term by assuming that the rate is analagous to a conductance for N, and inverting the term to produce a cost/resistance analagoue. We then multiply this temperature term by the minimum cost at optimal temperature (:math:`s_{fix}`) to give a temperature limited cost in terms of C to N ratios. Cost of Active Uptake ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -55,20 +88,22 @@ The cost of N uptake from soil, for each layer :math:`j`, is controlled by two u For non-mycorrhizal uptake: - .. math:: +.. math:: + :label: N_cost,nonmyc,j N_{cost,nonmyc,j} = \frac{k_{n,nonmyc}}{N_{smin,j}} + \frac{k_{c,nonmyc}}{c_{root,j}} and for active uptake: - .. math:: +.. math:: + :label: N_cost,active,j N_{cost,active,j} = \frac{k_{n,active}}{N_{smin,j}} + \frac{k_{c,active}}{c_{root,j}} where :math:`k_{n,active}` varies according to whether we are considering ecto or arbuscular mycorrhizal uptake. - .. math:: - :label: 18.2 +.. math:: + :label: k_n,active k_{n,active} = \left\{\begin{array}{lr} @@ -76,39 +111,48 @@ where :math:`k_{n,active}` varies according to whether we are considering ecto o k_{n,Aactive}& e = 0 \end{array}\right\} -where m=1 pertains to the fraction of the PFT that is ecotmycorrhizal, as opposed to arbuscular mycorrhizal. +where e = 1 pertains to the fraction of the PFT that is ectomycorrhizal, as opposed to arbuscular mycorrhizal. + +CLM6 corrects an error in the calculation of non-mycorrhizal uptake in CLM5, which had swapped parameter values for :math:`k_{c,nonmyc}` and :math:`k_{n,nonmyc}` that were inherited from the original publication of :ref:`Brzostek et al. (2014)`. Resolving N cost across simultaneous uptake streams -------------------------------------------------------- -The total cost of N uptake is calculated based on the assumption that carbon is partitioned to each stream in proportion to the inverse of the cost of uptake. So, more expensive pathways receive less carbon. Earlier versions of FUN :ref:`(Fisher et al., 2010)`) utilized a scheme whereby plants only took up N from the cheapest pathway. :ref:`Brzostek et al. (2014)` introduced a scheme for the simultaneous uptake from different pathways. Here we calcualate a 'conductance' to N uptake (analagous to the inverse of the cost function conceptualized as a resistance term) :math:`N_{conductance}` ( gN/gC) as: +The total cost of N uptake is calculated based on the assumption that carbon is partitioned to each stream in proportion to the inverse of the cost of uptake. So, more expensive pathways receive less carbon. Earlier versions of FUN :ref:`(Fisher et al. 2010`) utilized a scheme whereby plants only took up N from the cheapest pathway. :ref:`Brzostek et al. (2014)` introduced a scheme for the simultaneous uptake from different pathways. Here we calculate a 'conductance' to N uptake (analogous to the inverse of the cost function conceptualized as a resistance term) :math:`N_{conductance}` (gN/gC) as: - .. math:: +.. math:: + :label: N_conductance - N_{conductance,f}= \sum{(1/N_{cost,x})} + N_{conductance}= \sum{(1/N_{cost,x})} From this, we then calculate the fraction of the carbon allocated to each pathway as - .. math:: +.. math:: + :label: C_frac,x C_{frac,x} = \frac{1/N_{cost,x}}{N_{conductance}} These fractions are used later, to calculate the carbon expended on different uptake pathways. Next, the N acquired from each uptake stream per unit C spent (:math:`N_{exch,x}`, gN/gC) is determined as - .. math:: +.. math:: + :label: N_exch,x N_{exch,x} = \frac{C_{frac,x}}{N_{cost,x}} We then determine the total amount of N uptake per unit C spent (:math:`N_{exch,tot}`, gN/gC) as the sum of all the uptake streams. - .. math:: +.. math:: + :label: N_exch,tot + N_{exch,tot} = \sum{N_{exch,x}} and thus the subsequent overall N cost is - .. math:: +.. math:: + :label: N_cost,tot + N_{cost,tot} = 1/{N_{exch,tot}} - Retranslocation is determined via a different set of mechanisms, once the :math:`N_{cost,tot}` is known. +Retranslocation is determined via a different set of mechanisms, once the :math:`N_{cost,tot}` is known. Nitrogen Retranslocation -------------------------------------------------------- @@ -116,37 +160,42 @@ The retranslocation uses an iterative algorithm to remove Nitrogen from each pie At each timestep, the pool of carbon in falling leaves (:math:`C_{fallingleaf}`, g m\ :sup:`-2`) is generated from the quantity of litterfall on that day (see Phenology chapter for details). The amount of N in the litter pool (:math:`N_{fallingleaf}`, g m\ :sup:`-2`) is calculated as the total leaf N multiplied by the fraction of the leaf pool passed to litter that timestep. - .. math:: +.. math:: + :label: N_fallingleaf_1 - N_{fallingleaf} = N_{leaf}.C_{fallingleaf}/C_{leaf} + N_{fallingleaf} = N_{leaf}.C_{fallingleaf}/C_{leaf} The carbon available at the beginning of the iterative retranslocation calculation is equal to the :math:`C_{avail}` input into FUN. - .. math:: +.. math:: + :label: C_avail,retrans,0 - C_{avail,retrans,0} = C_{avail} + C_{avail,retrans,0} = C_{avail} Free Retranslocation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Some part of the leaf Nitrogen pool is removed without the need for an C expenditure. This 'free' N uptake amount, (:math:`N_{retrans,free}`, gN m\ :sup:`-2`) is calculated as - .. math:: +.. math:: + :label: N_retrans,free - N_{retrans,free} = max(N_{fallingleaf} - (C_{fallingleaf}/CN_{litter,min} ),0.0) + N_{retrans,free} = max(N_{fallingleaf} - (C_{fallingleaf}/CN_{litter,min} ),0.0) where :math:`CN_{litter,min}` is the minimum C:N ratio of the falling litter (currently set to 1.5 x the target C:N ratio). The new :math:`N_{fallingleaf}` (gN m\ :sup:`-2`) is then determined as - .. math:: +.. math:: + :label: N_fallingleaf_2 - N_{fallingleaf} = N_{fallingleaf} - N_{retrans,free} + N_{fallingleaf} = N_{fallingleaf} - N_{retrans,free} and the new litter C:N ratio as - .. math:: +.. math:: + :label: CN_fallingleaf - CN_{fallingleaf}=C_{fallingleaf}/N_{fallingleaf} + CN_{fallingleaf}=C_{fallingleaf}/N_{fallingleaf} Paid-for Retranslocation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -158,139 +207,166 @@ The remaining calculations conduct an iterative calculation to determine the deg First we calculate the cost of extraction (:math:`cost_{retrans}`, gC/gN) for the current leaf C:N ratio as - .. math:: +.. math:: + :label: cost_retrans + + cost_{retrans}= k_{retrans} / (1/CN_{fallingleaf})^{1.3} - cost_{retrans}= k_{retrans} / (1/CN_{fallingleaf})^{1.3} +where :math:`k_{retrans}` is a parameter controlling the overall cost of resorption, which also increases exponentially as the C:N ratio increases. -where :math:`k_{retrans}` is a parameter controlling the overall cost of resorption, which also increases exponentially as the C:N ratio increases +Next, we calculate the amount of C needed to be spent to increase the falling leaf C:N ratio by 1.0 in this iteration +:math:`i` (:math:`C_{retrans,spent,i}`, gC m\ :sup:`-2`) as: -Next, we calculate the amount of C needed to be spent to increase the falling leaf C:N ratio by 1.0 in this iteration :math:`i` (:math:`C_{retrans_spent,i}`, gC m\ :sup:`-2`) as: - .. math:: +.. math:: + :label: C_retrans,spent,i_1 - C_{retrans,spent,i} = cost_{retrans}.(N_{fallingleaf} - C_{fallingleaf}/ + C_{retrans,spent,i} = cost_{retrans}.(N_{fallingleaf} - C_{fallingleaf}/ (CN_{fallingleaf} + 1.0)) (wherein the retranslocation cost is assumed to not change over the increment of 1.0 in C:N ratio). Next, we calculate whether this is larger than the remaining C available to spend. - .. math:: +.. math:: + :label: C_retrans,spent,i_2 - C_{retrans,spent,i} = min(C_{retrans,spent,i}, C_{avail,retrans,i}) + C_{retrans,spent,i} = min(C_{retrans,spent,i}, C_{avail,retrans,i}) -The amount of N retranslocated from the leaf in this iteration (:math:`N_{retrans_paid,i}`, gN m\ :sup:`-2`) is calculated, checking that it does not fall below zero: +The amount of N retranslocated from the leaf in this iteration (:math:`N_{retrans,paid,i}`, gN m\ :sup:`-2`) is calculated, checking that it does not fall below zero: - .. math:: +.. math:: + :label: N_retrans,paid,i - N_{retrans,paid,i} = min(N_{fallingleaf},C_{retrans,spent,i} / cost_{retrans}) + N_{retrans,paid,i} = min(N_{fallingleaf},C_{retrans,spent,i} / cost_{retrans}) The next step calculates the growth C which is accounted for by this amount of N extraction in this iteration (:math:`C_{retrans,accounted,i}`). This is calculated using the current plant C:N ratio, and also for the additional C which will need to be spent on growth respiration to build this amount of new tissue. - .. math:: +.. math:: + :label: C_retrans,accouned,i - C_{retrans,accounted,i} = N_{retrans,paid,i} . CN_{plant} . (1.0 + gr_{frac}) + C_{retrans,accounted,i} = N_{retrans,paid,i} . CN_{plant} . (1.0 + gr_{frac}) Then the falling leaf N is updated: - .. math:: +.. math:: + :label: N_fallingleaf_3 - N_{fallingleaf} = N_{fallingleaf} - N_{ret,i} + N_{fallingleaf} = N_{fallingleaf} - N_{ret,i} -and the :math:`CN_{fallingleaf}` and cost_{retrans} are updated. The amount of available carbon that is either unspent on N acquisition nor accounted for by N uptake is updated: +and the :math:`CN_{fallingleaf}` and :math:`cost_{retrans}` are updated. The amount of available carbon that is either unspent on N acquisition nor accounted for by N uptake is updated: - .. math:: +.. math:: + :label: C_avail,retrans,i+1 - C_{avail,retrans,i+1} = C_{avail,retrans,i} - C_{retrans,spent,i} - C_{retrans,accounted,i} + C_{avail,retrans,i+1} = C_{avail,retrans,i} - C_{retrans,spent,i} - C_{retrans,accounted,i} Outputs of Retranslocation algorithm. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The final output of the retranslocation calculation are the retranslocated N (:math:`N_{retrans}`, gN m\ :sup:`-2`), C spent on retranslocation (:math:`C_{retrans_paid}`, gC m\ :sup:`-2`), and C accounted for by retranslocation (:math:`C_{retrans_accounted}`, gC m\ :sup:`-2`). +The final output of the retranslocation calculation are the retranslocated N (:math:`N_{retrans}`, gN m\ :sup:`-2`), C spent on retranslocation (:math:`C_{retrans,paid}`, gC m\ :sup:`-2`), and C accounted for by retranslocation (:math:`C_{retrans,accounted}`, gC m\ :sup:`-2`). -For paid-for uptake, we accumulate the total carbon spent on retranslocation (:math:`C_{spent_retrans}`), +For paid-for uptake, we accumulate the total carbon spent on retranslocation (:math:`C_{spent,retrans}`), - .. math:: +.. math:: + :label: C_retrans,spent - C_{retrans,spent} = \sum{C_{retrans,i}} + C_{retrans,spent} = \sum{C_{retrans,i}} The total N acquired from retranslocation is - .. math:: +.. math:: + :label: N_retrans - N_{retrans} = N_{retrans,paid}+N_{retrans,free} + N_{retrans} = N_{retrans,paid}+N_{retrans,free} where N acquired by paid-for retranslocation is - .. math:: +.. math:: + :label: N_retrans,paid - N_{retrans,paid} = \sum{N_{retrans,paid,i}} + N_{retrans,paid} = \sum{N_{retrans,paid,i}} -The total carbon accounted for by retranslocation is the sum of the C accounted for by paid-for N uptake (:math:`N_{retrans_paid}`) and by free N uptake (:math:`N_{retrans_free}`). +The total carbon accounted for by retranslocation is the sum of the C accounted for by paid-for N uptake (:math:`N_{retrans,paid}`) and by free N uptake (:math:`N_{retrans,free}`). - .. math:: +.. math:: + :label: C_retrans,accounted - C_{retrans,accounted} = \sum{C_{retrans,accounted,i}}+N_{retrans,free}.CN_{plant} . (1.0 + gr_{frac}) + C_{retrans,accounted} = \sum{C_{retrans,accounted,i}}+N_{retrans,free}.CN_{plant} . (1.0 + gr_{frac}) The total available carbon in FUN to spend on fixation and active uptake (:math:`C_{tospend}`, gC m\ :sup:`-2`) is calculated as the carbon available minus that account for by retranslocation: - .. math:: +.. math:: + :label: C_tospend - C_{tospend} = C_{avail} - C_{retrans,accounted} + C_{tospend} = C_{avail} - C_{retrans,accounted} Carbon expenditure on fixation and active uptake. -------------------------------------------------------- At each model timestep, the overall cost of N uptake is calculated (see below) in terms of C:N ratios. The available carbon (:math:`C_{avail}`, g m\ :sup:`-2` s\ :sup:`-1`) is then allocated to two alternative outcomes, payment for N uptake, or conservation for growth. For each carbon conserved for growth, a corresponding quantity of N must be made available. In the case where the plant target C:N ratio is fixed, the partitioning between carbon for growth (:math:`C_{growth}`) and carbon for N uptake (:math:`C_{nuptake}`) is calculated by solving a system of simultaneous equations. First, the carbon available must equal the carbon spent on N uptake plus that saved for growth. - .. math:: +.. math:: + :label: C_avail_2 C_{growth}+C_{nuptake}=C_{avail} Second, the nitrogen acquired from expenditure of N (left hand side of term below) must equal the N that is required to match the growth carbon (right hand side of term below). - .. math:: +.. math:: + :label: C_nuptake_over_N_cost C_{nuptake}/N_{cost} =C_{growth}/CN_{target} The solution to these two equated terms can be used to estimate the ideal :math:`C_{nuptake}` as follows, - .. math:: +.. math:: + :label: C_nuptake_1 + C_{nuptake} =C_{tospend}/ ( (1.0+f_{gr}*(CN_{target} / N_{cost}) + 1) . and the other C and N fluxes can be determined following the logic above. Modifications to allow variation in C:N ratios -------------------------------------------------------- -The original FUN model as developed by :ref:`Fisher et al. (2010)` and :ref:`Brzostek et al. (2014)` assumes a fixed plant tissue C:N ratio. This means that in the case where N is especially limiting, all excess carbon will be utilized in an attempt to take up more Nitrogen. It has been repeatedly observed, however, that in these circumstances in real life, plants have some flexibility in the C:N stoichiometry of their tissues, and therefore, this assumption may not be realistic. However, the degree to which the C:N ratio varies with N availability is poorly documented, and existing global nitrogen models use a variety of heuristic methods by which to incorporate changing C:N ratios (Zaehle and Friend 2010; Ghimire et al. 2016). This algorithm exists as a placeholder to allow variable C:N ratios to occur, and to allow exploration of how much the parameters controlling their flexibility has on model outcomes. Incorporation of emerging understanding of the controls on tissue stoichiometry should ultimately replace this scheme. +The original FUN model as developed by :ref:`Fisher et al. (2010)` and :ref:`Brzostek et al. (2014)` assumes a fixed plant tissue C:N ratio. This means that in the case where N is especially limiting, all excess carbon will be utilized in an attempt to take up more nitrogen. It has been repeatedly observed, however, that in these circumstances in real life, plants have some flexibility in the C:N stoichiometry of their tissues, and therefore, this assumption may not be realistic. However, the degree to which the C:N ratio varies with N availability is poorly documented, and existing global nitrogen models use a variety of heuristic methods by which to incorporate changing C:N ratios (:ref:`Zaehle and Friend 2010`; :ref:`Ghimire et al. 2016`). This algorithm exists as a placeholder to allow variable C:N ratios to occur, and to allow exploration of how much the parameters controlling their flexibility has on model outcomes. Incorporation of emerging understanding of the controls on tissue stoichiometry should ultimately replace this scheme. -Thus, in CLM5, we introduce the capacity for tissue C:N ratios to be prognostic, rather than static. Overall N and C availability (:math:`N_{uptake}` and :math:`C_{growth}`) and hence tissue C:N ratios, are both determined by FUN. Allocation to individual tissues is discussed in the allocation chapter +Thus, in CLM5, we introduce the capacity for tissue C:N ratios to be prognostic, rather than static. Overall N and C availability (:math:`N_{uptake}` and :math:`C_{growth}`) and hence tissue C:N ratios, are both determined by FUN. Allocation to individual tissues is discussed in the allocation chapter. CLM5 introduced an algorithm which adjusts the C expenditure on uptake to allow varying tissue C:N ratios. Increasing C spent on uptake will directly reduce the C:N ratio, and reducing C spent on uptake (retaining more for tissue growth) will increase it. C spent on uptake is impacted by both the N cost in the environment, and the existing tissue C:N ratio of the plant. The output of this algorithm is :math:`\gamma_{FUN}`, the fraction of the ideal :math:`C_{nuptake}` calculated from the FUN equation above -Here we introduce an algorithm which adjusts the C expenditure on uptake to allow varying tissue C:N ratios. Increasing C spent on uptake will directly reduce the C:N ratio, and reducing C spent on uptake (retaining more for tissue growth) will increase it. C spent on uptake is impacted by both the N cost in the environment, and the existing tissue C:N ratio of the plant. The output of this algorithm is :math:`\gamma_{FUN}`, the fraction of the ideal :math:`C_{nuptake}` calculated from the FUN equation above +.. math:: + :label: C_nuptake_2 - .. math:: C_{nuptake} = C_{nuptake}.\gamma_{FUN} +Subsequent sensitivity tests found relatively low flexibility in the target C:N ratios resulting from this approach (:ref:`Fisher et al. 2019`). Thus, :ref:`Hauser et al. (2023)` introduced an additional function to force time evolving foliar C:N ratios to vary with atmospheric CO\ :sub:`2` concentrations as shown in Eq. :eq:`time-evolv target leaf CN` (section :numref:`rst_CN Pools`). + Response of C expenditure to Nitrogen uptake cost ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The environmental cost of Nitrogen (:math:`N_{cost,tot}`) is used to determine :math:`\gamma_{FUN}`. - .. math:: +.. math:: + :label: gamma_FUN_1 + \gamma_{FUN} = max(0.0,1.0 - (N_{cost,tot}-a_{cnflex})/b_{cnflex}) where :math:`a_{cnflex}` and :math:`b_{cnflex}` are parameters fitted to give flexible C:N ranges over the operating range of N costs of the model. Calibration of these parameters should be subject to future testing in idealized experimental settings; they are here intended as a placeholder to allow some flexible stoichiometry, in the absence of adequate understanding of this process. Here :math:`a_{cnflex}` operates as the :math:`N_{cost,tot}` above which there is a modification in the C expenditure (to allow higher C:N ratios), and :math:`b_{cnflex}` is the scalar which determines how much the C expenditure is modified for a given discrepancy between :math:`a_{cnflex}` and the actual cost of uptake. Response of C expenditure to plant C:N ratios ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -We first calculate a :math:`\delta_{CN}`, which is the difference between the target C:N (:math:`target_{CN}`) a model parameter, and the existing C:N ratio (:math:`CN_{plant}`) +We first calculate a :math:`\delta_{CN}`, which is the difference between the target C:N (:math:`CN_{target}`) a model parameter (:numref:`Table PFT target leaf CN`), and the existing C:N ratio (:math:`CN_{plant}`) - .. math:: +.. math:: + :label: CN_plant - CN_{plant} = \frac{C_{leaf} + C_{leaf,storage}}{N_{leaf} + N_{leaf,storage})} + CN_{plant} = \frac{C_{leaf} + C_{leaf,storage}}{N_{leaf} + N_{leaf,storage})} and - .. math:: - \delta_{CN} = CN_{plant} - target_{CN} + +.. math:: + :label: delta_CN + + \delta_{CN} = CN_{plant} - CN_{target} We then increase :math:`\gamma_{FUN}` to account for situations where (even if N is expensive) plant C:N ratios have increased too far from the target. Where :math:`\delta_{CN}` is negative, we reduce C spent on N uptake and retain more C for growth - .. math:: +.. math:: + :label: gamma_FUN_2 \gamma_{FUN} = \left\{\begin{array}{lr} @@ -300,7 +376,9 @@ We then increase :math:`\gamma_{FUN}` to account for situations where (even if We then restrict the degree to which C expenditure can be reduced (to prevent unrealistically high C:N ratios) as - .. math:: +.. math:: + :label: gamma_FUN_3 + \gamma_{FUN} = max(min(1.0,\gamma_{FUN}),0.5) Calculation of N uptake streams from active uptake and fixation @@ -308,58 +386,68 @@ Calculation of N uptake streams from active uptake and fixation Once the final :math:`C_{nuptake}` is known, the fluxes of C to the individual pools can be derived as - .. math:: +.. math:: + :label: C_nuptake,x C_{nuptake,x} = C_{frac,x}.C_{nuptake} - .. math:: +.. math:: + :label: N_nuptake,x N_{uptake,x} = \frac{C_{nuptake}}{N_{cost}} Following this, we determine whether the extraction estimates exceed the pool size for each source of N. Where :math:`N_{active,no3} + N_{nonmyc,no3} > N_{avail,no3}`, we calculate the unmet uptake, :math:`N_{unmet,no3}` - .. math:: +.. math:: + :label: N_unmet,no3 N_{unmet,no3} = N_{active,no3} + N_{nonmyc,no3} - N_{avail,no3} then modify both fluxes to account - .. math:: +.. math:: + :label: N_active,no3 N_{active,no3} = N_{active,no3} + N_{unmet,no3}.\frac{N_{active,no3}}{N_{active,no3}+N_{nonmyc,no3}} - .. math:: +.. math:: + :label: N_nonmyc,no3 N_{nonmyc,no3} = N_{nonmyc,no3} + N_{unmet,no3}.\frac{N_{nonmyc,no3}}{N_{active,no3}+N_{nonmyc,no3}} and similarly, for NH4, where :math:`N_{active,nh4} + N_{nonmyc,nh4} > N_{avail,nh4}`, we calculate the unmet uptake, :math:`N_{unmet,no3}` - .. math:: +.. math:: + :label: N_unmet,nh4 N_{unmet,nh4} = N_{active,nh4} + N_{nonmyc,nh4} - N_{avail,nh4} then modify both fluxes to account - .. math:: +.. math:: + :label: N_active,nh4 N_{active,nh4} = N_{active,nh4} + N_{unmet,nh4}.\frac{N_{active,nh4}}{N_{active,nh4}+N_{nonmyc,nh4}} - .. math:: +.. math:: + :label: N_nonmyc,nh4 N_{nonmyc,nh4} = N_{nonmyc,nh4} + N_{unmet,nh4}.\frac{N_{nonmyc,nh4}}{N_{active,nh4}+N_{nonmyc,nh4}} and then update the C spent to account for hte new lower N acquisition in that layer/pool. - .. math:: +.. math:: + :label: C_active_and_nonmyc C_{active,nh4} = N_{active,nh4}.N_{cost,active,nh4}\\ C_{active,no3} = N_{active,no3}.N_{cost,active,no3}\\ - C_{nonmyc,no3} = N_{nonmyc,no3}.N_{cost,nonmyc,no3}\\ + C_{nonmyc,nh4} = N_{nonmyc,nh4}.N_{cost,nonmyc,nh4}\\ C_{nonmyc,no3} = N_{nonmyc,no3}.N_{cost,nonmyc,no3}\\ Following this, we determine how much carbon is accounted for for each soil layer. - .. math:: +.. math:: + :label: C_accounted,x,j C_{accounted,x,j} = C_{spent,j,x} - (N_{acquired,j,x}.CN_{plant}.(1.0+ gr_{frac})) diff --git a/doc/source/tech_note/FUN/image1.png b/doc/source/tech_note/FUN/image1.png new file mode 100644 index 0000000000..7851a7a0a8 --- /dev/null +++ b/doc/source/tech_note/FUN/image1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:824fd908c8bdc9cd99ee4a2510d3ccb05d70280c7bad4728dd0eee5e43365fc3 +size 247878 diff --git a/doc/source/tech_note/Glacier/CLM50_Tech_Note_Glacier.rst b/doc/source/tech_note/Glacier/CLM50_Tech_Note_Glacier.rst index 4c15ebbf56..81c017276e 100644 --- a/doc/source/tech_note/Glacier/CLM50_Tech_Note_Glacier.rst +++ b/doc/source/tech_note/Glacier/CLM50_Tech_Note_Glacier.rst @@ -113,7 +113,7 @@ The default behaviors for the world's glacier and ice sheet regions are describe Multiple elevation class scheme ------------------------------- -The glacier land unit contains multiple columns based on surface elevation. These are known as elevation classes, and the land unit is referred to as *glacier\_mec*. (As described in section :numref:`Glacier regions`, some regions have only a single elevation class, but they are still referred to as *glacier\_mec* land units.) The default is to have 10 elevation classes whose lower limits are 0, 200, 400, 700, 1000, 1300, 1600, 2000, 2500, and 3000 m. Each column is characterized by a fractional area and surface elevation that are read in during model initialization, and then possibly overridden by CISM as the run progresses. Each *glacier\_mec* column within a grid cell has distinct ice and snow temperatures, snow water content, surface fluxes, and SMB. +The glacier land unit contains multiple columns based on surface elevation. These are known as elevation classes, and the land unit is referred to as *glacier\_mec*. (As described in section :numref:`Glacier regions`, some regions have only a single elevation class, but they are still referred to as *glacier\_mec* land units.) The default is to have 10 elevation classes whose lower limits are 0, 200, 400, 700, 1000, 1300, 1600, 2000, 2500, and 3000 m. Each column is characterized by a fractional area and surface elevation that are read in during model initialization, and then possibly overridden by CISM as the run progresses. Each *glacier\_mec* column within a grid cell has distinct ice and snow temperatures, snow water content, surface fluxes, and SMB. In CLM6 users can optionally specify using :ref:`Sturm et al. (1997)` or :ref:`Jordan (1991)` parameterizations for snow thermal conductivity over glacier land units (see Chapter :numref:`rst_Soil and Snow Temperatures`), with Sturm (1997) set as the default. The atmospheric surface temperature, potential temperature, specific humidity, density, and pressure are downscaled from the atmosphere's mean grid cell elevation to the *glacier\_mec* column elevation using a specified lapse rate (typically 6.0 deg/km) and an assumption of uniform relative humidity. Longwave radiation is downscaled by assuming a linear decrease in downwelling longwave radiation with increasing elevation (0.032 W m\ :sup:`-2` m\ :sup:`-1`, limited to 0.5 - 1.5 times the gridcell mean value, then normalized to conserve gridcell total energy) :ref:`(Van Tricht et al., 2016)`. Total precipitation is partitioned into rain vs. snow as described in Chapter :numref:`rst_Surface Characterization, Vertical Discretization, and Model Input Requirements`. The partitioning of precipitation is based on the downscaled temperature, allowing rain to fall at lower elevations while snow falls at higher elevations. diff --git a/doc/source/tech_note/Introduction/CLM50_Tech_Note_Introduction.rst b/doc/source/tech_note/Introduction/CLM50_Tech_Note_Introduction.rst index b931dc8fed..46a134485b 100644 --- a/doc/source/tech_note/Introduction/CLM50_Tech_Note_Introduction.rst +++ b/doc/source/tech_note/Introduction/CLM50_Tech_Note_Introduction.rst @@ -51,14 +51,14 @@ P. O. Box 3000, Boulder, Colorado 80307-300 - :numref:`Figure Vegetation fluxes and pools` Vegetation fluxes and pools. +- :numref:`Figure Carbon costs of N fixation as a function of soil temperature` Carbon costs of N fixation as a function of soil temperature. + - :numref:`Figure annual phenology cycle` Example of annual phenology cycle for seasonal deciduous. - :numref:`Figure Schematic of decomposition model in CLM` Schematic of decomposition model in CLM. - :numref:`Figure Pool structure` Pool structure, transitions, respired fractions, and turnover times for the 2 alternate soil decomposition models included in CLM. -- :numref:`Figure Biological nitrogen fixation` Biological nitrogen fixation as a function of annual net primary production. - - :numref:`Figure Methane Schematic` Schematic representation of biological and physical processes integrated in CLM that affect the net CH4 surface flux. - :numref:`Figure Schematic of land cover change` Schematic of land cover change impacts on CLM carbon pools and fluxes. diff --git a/doc/source/tech_note/Lake/CLM50_Tech_Note_Lake.rst b/doc/source/tech_note/Lake/CLM50_Tech_Note_Lake.rst index 88cb77d737..acc3f0dc1c 100644 --- a/doc/source/tech_note/Lake/CLM50_Tech_Note_Lake.rst +++ b/doc/source/tech_note/Lake/CLM50_Tech_Note_Lake.rst @@ -485,7 +485,7 @@ The overall thermal conductivity :math:`\tau _{i}` for layer *i* with ice mass-f \tau _{i} =\frac{\tau _{ice,eff} \tau _{liq,i} }{\tau _{liq,i} I_{i} +\tau _{ice} \left(1-I_{i} \right)} . -The thermal conductivity of snow, soil, and bedrock layers above and below the lake, respectively, are computed identically to those for vegetated land units (Chapter :numref:`rst_Soil and Snow Temperatures`), except for the adjustment of thermal conductivity for frost heave or excess ice (:ref:`Subin et al., 2012a, Supporting Information`). +The thermal conductivity of snow, soil, and bedrock layers above and below the lake, respectively, are computed identically to those for vegetated land units (Chapter :numref:`rst_Soil and Snow Temperatures`), except for the adjustment of thermal conductivity for frost heave or excess ice (:ref:`Subin et al., 2012a, Supporting Information`). In CLM6 users can optionally specify using :ref:`Sturm et al. (1997)` or :ref:`Jordan (1991)` parameterizations for snow thermal conductivity over lakes (see Chapter :numref:`rst_Soil and Snow Temperatures`), with :ref:`Sturm et al. (1997)` set as the default. .. _Radiation Penetration: diff --git a/doc/source/tech_note/Photosynthetic_Capacity/CLM50_Tech_Note_Photosynthetic_Capacity.rst b/doc/source/tech_note/Photosynthetic_Capacity/CLM50_Tech_Note_Photosynthetic_Capacity.rst index af879dd830..30b110e710 100755 --- a/doc/source/tech_note/Photosynthetic_Capacity/CLM50_Tech_Note_Photosynthetic_Capacity.rst +++ b/doc/source/tech_note/Photosynthetic_Capacity/CLM50_Tech_Note_Photosynthetic_Capacity.rst @@ -3,13 +3,13 @@ Photosynthetic Capacity ======================= -The photosynthetic capacity is represented by two key parameters: 1) the maximum rate of carboxylation at 25 °C, :math:`V_{\text{c,max25}}`; and 2) the maximum rate of electron transport at 25 °C, :math:`J_{\text{max25}}`. They are predicted by a mechanistic model of leaf utilization of nitrogen for assimilation (LUNA V1.0) (:ref:`Ali et al. 2016`) based on an optimality hypothesis to nitrogen allocation among light capture, electron transport, carboxylation, respiration and storage. Specifically, the model allocates the nitrogen by maximizing the daily net photosynthetic carbon gain under following two key assumptions: +The photosynthetic capacity is represented by two key parameters: 1) the maximum rate of carboxylation at 25°C, :math:`V_{\text{c,max25}}`; and 2) the maximum rate of electron transport at 25°C, :math:`J_{\text{max25}}`. They are predicted by a mechanistic model of leaf utilization of nitrogen for assimilation (LUNA V1.0) (:ref:`Ali et al. 2016`) based on an optimality hypothesis to nitrogen allocation among light capture, electron transport, carboxylation, respiration and storage. Specifically, the model allocates the nitrogen by maximizing the daily net photosynthetic carbon gain under following two key assumptions: - nitrogen allocated for light capture, electron transport and carboxylation are co-limiting; - respiratory nitrogen is allocated to maintain dark respiration determined by :math:`V_{\text{c,max}}`. -Compared to traditional photosynthetic capacity models, a key advantage of LUNA is that the model is able to predict the potential acclimation of photosynthetic capacities at different environmental conditions as determined by temperature, radiation, CO :sub:`2` concentrations, day length, and humidity. +Compared to traditional photosynthetic capacity models, a key advantage of LUNA is that the model is able to predict the potential acclimation of photosynthetic capacities at different environmental conditions as determined by temperature, radiation, CO\ :sub:`2` concentrations, day length, and humidity. .. _Model inputs and parameter estimations: @@ -17,12 +17,12 @@ Model inputs and parameter estimations ------------------------------------------------------- The LUNA model includes the following four unitless parameters: -- :math:`J_{maxb0}` , which specifies the baseline proportion of nitrogen allocated for electron transport; -- :math:`J_{maxb1}` , which determines response of electron transport rate to light availability; -- :math:`t_{c,j0}` , which defines the baseline ratio of Rubisco-limited rate to light-limited rate; -- :math:`H` , which determines the response of electron transport rate to relative humidity. +- :math:`J_{maxb0}` , which specifies the baseline proportion of nitrogen allocated for electron transport rate; +- :math:`J_{maxb1}` , which determines response of electron transport rate to light availability; +- :math:`t_{c,j0}` , which defines the baseline ratio of Rubisco-limited rate to light-limited rate; +- :math:`H` , which determines the response of electron transport rate to relative humidity. -The above four parameters are estimated by fitting the LUNA model to a global compilation of >800 observations located at different biomes, canopy locations, and time of the year from 1993-2013 (Ali et al. 2015). The model inputs are area-based leaf nitrogen content, leaf mass per unit leaf area and the driving environmental conditions (average of past 10 days) including temperature, CO :sub:`2` concentrations, daily mean and maximum radiation, relative humidity and day length. The estimated values in CLM5 for the listed parameters are 0.0311, 0.17, 0.8054, and 6.0999, respectively. In LUNA V1.0, the estimated parameter values are for C3 natural vegetations. In view that potentially large differences in photosynthetic capacity could exist between crops and natural vegetations due to human selection and genetic modifications, in CLM5, the LUNA model are used only for C3 natural vegetations. The photosynthetic capacity for crops and C4 plants are thus still kept the same as CLM4.5. Namely, it is estimated based on the leaf nitrogen content, fixed RUBISCO allocations for :math:`V_{c\max 25}` and an adjusting factor to account for the impact of day length. In CLM5, the model simulates both sun-lit and shaded leaves; however, because the sun-lit and shaded leaves can changes through the day based on the sun angles, we do not differentiate the photosynthetic capacity difference for sun-lit or shaded leaves. +For CLM5, the above four parameters were estimated by fitting the LUNA model to a global compilation of >800 observations located at different biomes, canopy locations, and time of the year from 1993-2013 (:ref:`Ali et al. 2016`). The model inputs are area-based leaf nitrogen content, leaf mass per unit leaf area and the driving environmental conditions (average of the past 10 days) including temperature, CO\ :sub:`2` concentrations, daily mean and maximum radiation, relative humidity and day length. The estimated values in CLM5 for the listed parameters were 0.0311, 0.17, 0.8054, and 6.0999, respectively. As of CLM6, these values have since been updated during our calibration process. See the latest parameter file for the most up-to-date values. In LUNA V1.0, the estimated parameter values are for C3 natural vegetation. In view that potentially large differences in photosynthetic capacity could exist between crops and natural vegetation due to human selection and genetic modifications, the LUNA model is used only for C3 natural vegetation. The photosynthetic capacity for crops and C4 plants are thus still kept the same as CLM4.5. Namely, it is estimated based on the leaf nitrogen content, fixed rubisco allocations for :math:`V_{c\max 25}` and an adjusting factor to account for the impact of day length. In CLM, the model simulates both sun-lit and shaded leaves; however, because the sun-lit and shaded leaves can changes through the day based on the sun angles, we do not differentiate the photosynthetic capacity difference for sun-lit or shaded leaves. .. _Model structure: @@ -34,32 +34,32 @@ Model structure Plant Nitrogen '''''''''''''''''''''''''' -The structure of the LUNA model is adapted from :ref:`Xu et al. (2012)`, where the plant nitrogen at the leaf level ( :math:`\text{LNC}_{a}`; gN/ m :sup:`2` leaf) is divided into four pools: structural nitrogen( :math:`N_{\text{str}}`; gN/m :sup:`2` leaf), photosynthetic nitrogen ( :math:`N_{\text{psn}}`; gN/m :sup:`2` leaf), storage nitrogen( :math:`N_{\text{store}}`; gN/m :sup:`2` leaf), and respiratory nitrogen ( :math:`N_{\text{resp}}`; gN/m :sup:`2` leaf). Namely, +The structure of the LUNA model is adapted from :ref:`Xu et al. (2012)`, where the plant nitrogen at the leaf level (:math:`\text{LNC}_{a}`; gN/ m\ :sup:`2` leaf) is divided into four pools: structural nitrogen (:math:`N_{\text{str}}`; gN/m\ :sup:`2` leaf), photosynthetic nitrogen (:math:`N_{\text{psn}}`; gN/m\ :sup:`2` leaf), storage nitrogen (:math:`N_{\text{store}}`; gN/m\ :sup:`2` leaf), and respiratory nitrogen (:math:`N_{\text{resp}}`; gN/m\ :sup:`2` leaf). Namely, .. math:: - :label: 10.1) + :label: :lnc_a:) \text{LNC}_{a} = N_{\text{psn}} + N_{\text{str}}+ N_{\text{store}} + N_{\text{resp}}. -The photosynthetic nitrogen, :math:`N_{\text{psn}}`, is further divided into nitrogen for light capture ( :math:`N_{\text{lc}}`; gN/m :sup:`2` leaf), nitrogen for electron transport ( :math:`N_{\text{et}}`; gN/m :sup:`2` leaf), and nitrogen for carboxylation ( :math:`N_{\text{cb}}`; gN/m :sup:`2` leaf). Namely, +The photosynthetic nitrogen, :math:`N_{\text{psn}}`, is further divided into nitrogen for light capture (:math:`N_{\text{lc}}`; gN/m\ :sup:`2` leaf), nitrogen for electron transport (:math:`N_{\text{et}}`; gN/m\ :sup:`2` leaf), and nitrogen for carboxylation (:math:`N_{\text{cb}}`; gN/m\ :sup:`2` leaf). Namely, .. math:: - :label: 10.2) + :label: :N_psn:) N_{\text{psn}} =N_{\text{et}} + N_{\text{cb}} + N_{\text{lc}}. -The structural nitrogen, :math:`N_{\text{str}}`, is calculated as the multiplication of leaf mass per unit area (:math:`\text{LMA}`; g biomass/m :sup:`2` leaf), and the structural nitrogen content (:math:`\text{SNC}`; gN/g biomass). Namely, +The structural nitrogen, :math:`N_{\text{str}}`, is calculated as the multiplication of leaf mass per unit area (:math:`\text{LMA}`; g biomass/m\ :sup:`2` leaf), and the structural nitrogen content (:math:`\text{SNC}`; gN/g biomass). Namely, .. math:: - :label: 10.3) + :label: :N_str:) N_{\text{str}} = \text{SNC} \cdot \text{LMA} -where :math:`\text{SNC}` is set to be fixed at 0.004 (gN/g biomass), based on data on C:N ratio from dead wood (White etal.,2000), and :math:`\text{LMA}` is the inverse of specific leaf area at the canopy top (:math:`SLA_{\text{0}}`), a PFT-level parameter (:numref:`Table Plant functional type (PFT) leaf N parameters`). +where :math:`\text{SNC}` is set to be fixed at 0.004 (gN/g biomass), based on data on C:N ratio from dead wood :ref:`(White et al. 2000`), and :math:`\text{LMA}` is the inverse of specific leaf area at the canopy top (:math:`SLA_{\text{0}}`), a PFT-level parameter (:numref:`Table Plant functional type (PFT) leaf N parameters`). .. _Table Plant functional type (PFT) leaf N parameters: -.. table:: Plant functional type (PFT) leaf N parameters. +.. table:: Plant functional type (PFT) leaf N parameters. Note: These are the original CLM5 values and may not reflect current values. :math:`SLA_{\text{0}}` is the specific leaf area at the canopy top (m\ :sup:`2` leaf/g biomass). +----------------------------------+--------------------------+ | PFT | :math:`SLA_{\text{0}}` | @@ -113,51 +113,50 @@ where :math:`\text{SNC}` is set to be fixed at 0.004 (gN/g biomass), based on da | Switchgrass | 0.03500 | +----------------------------------+--------------------------+ -Notes: :math:`SLA_{\text{0}}` is the specific leaf area at the canopy top (m :sup:`2` leaf/g biomass) -We assume that plants optimize their nitrogen allocations (i.e., :math:`N_{\text{store}}`, :math:`N_{\text{resp}}`, :math:`N_{\text{lc}}`, :math:`N_{\text{et}}`, :math:`N_{\text{cb}}`) to maximize the photosynthetic carbon gain, defined as the gross photosynthesis ( :math:`A` ) minus the maintenance respiration for photosynthetic enzymes ( :math:`R_{\text{psn}}` ), under specific environmental conditions and given plant's strategy of leaf nitrogen use. Namely, the solutions of nitrogen allocations \{ :math:`N_{\text{store}}`, :math:`N_{\text{resp}}`, :math:`N_{\text{lc}}`, :math:`N_{\text{et}}`, :math:`N_{\text{cb}}` \} can be estimated as follows, +We assume that plants optimize their nitrogen allocations (i.e., :math:`N_{\text{store}}`, :math:`N_{\text{resp}}`, :math:`N_{\text{lc}}`, :math:`N_{\text{et}}`, :math:`N_{\text{cb}}`) to maximize the photosynthetic carbon gain, defined as the gross photosynthesis (:math:`A`) minus the maintenance respiration for photosynthetic enzymes (:math:`R_{\text{psn}}`), under specific environmental conditions and given the plant's strategy of leaf nitrogen use. Namely, the solutions of nitrogen allocations \{:math:`N_{\text{store}}`, :math:`N_{\text{resp}}`, :math:`N_{\text{lc}}`, :math:`N_{\text{et}}`, :math:`N_{\text{cb}}`\} can be estimated as follows, .. math:: - :label: 10.4) + :label: :N_allocations:) \left\{\hat{N}_{\text{{store}}}, \hat{N}_{\text{{resp}}}, \hat{\mathrm{N}}_{\text{lc}}, \hat{N}_{\text{et}}, \hat{\mathrm{N}}_{\text{cb}} \right\} = \underset{\mathrm{N}_{\text{store}}\,+\,\mathrm{N}_{\text{resp}}\,+\,\mathrm{N}_{\text{lc}}\,+\,\mathrm{N}_{\text{et}}\,+\,\mathrm{N}_{\text{cb}}\,<\text{FNC}_{\mathrm{a}}}{\text{argmax}} (A-R_{\text{psn}}), -where :math:`\text{FNC}_{a}` is the functional nitrogen content defined as the total leaf nitrogen content ( :math:`\text{LNC}_{a}`) minus the structural nitrogen content ( :math:`N_{\text{str}}` ). +where :math:`\text{FNC}_{a}` is the functional nitrogen content defined as the total leaf nitrogen content (:math:`\text{LNC}_{a}`) minus the structural nitrogen content (:math:`N_{\text{str}}`). -The gross photosynthesis, :math:`A`, was calculated with a coupled leaf gas exchange model based on the :ref:`Farquhar et al. (1980)` model of photosynthesis and Ball--Berry-type stomatal conductance model (Ball et al. 1987). The maintenance respiration for photosynthetic enzymes, :math:`R_{\text{psn}}`, is calculated by the multiplication of total photosynthetic nitrogen ( :math:`N_{\text{psn}}` ) and the maintenance respiration cost for photosynthetic enzymes. +The gross photosynthesis, :math:`A`, was calculated with a coupled leaf gas exchange model based on the :ref:`Farquhar et al. (1980)` model of photosynthesis and Ball-Berry-type stomatal conductance model :ref:`(Ball et al. 1987)`. The maintenance respiration for photosynthetic enzymes, :math:`R_{\text{psn}}`, is calculated by the multiplication of total photosynthetic nitrogen (:math:`N_{\text{psn}}`) and the maintenance respiration cost for photosynthetic enzymes. Maximum electron transport rate ''''''''''''''''''''''''''''''''' -In the LUNA model, the maximum electron transport rate ( :math:`J_{\text{max}}`; :math:`{\mu} mol` electron / m :sup:`2`/s) is simulated to have a baseline allocation of nitrogen and additional nitrogen allocation to change depending on the average daytime photosynthetic active radiation (PAR; :math:`{\mu} mol` electron / m :sup:`2`/s), day length (hours) and air humidity. Specifically, the LUNA model has +In the LUNA model, the maximum electron transport rate (:math:`J_{\text{max}}`; μmol electron/m\ :sup:`2`/s) is simulated to have a baseline allocation of nitrogen and additional nitrogen allocation to change depending on the average daytime photosynthetic active radiation (PAR; μmol electron/ m\ :sup:`2`/s), day length (hours) and air humidity. Specifically, the LUNA model has .. math:: - :label: 10.5) + :label: :J_max:) - J_{\text{{max}}} = J_{\text{max}0} + J_{\text{max}b1} + J_{\text{max}} = J_{\text{max}0} + J_{\text{max}b1} f\left(\text{day length} \right)f\left(\text{humidity} \right)\alpha \text{PAR} The baseline electron transport rate, :math:`J_{\text{max}0}`, is calculated as follows, .. math:: - :label: 10.6) + :label: :J_max0:) - J_{\text{max}0} = J_{\text{max}b0}{\text{FNC}}_{\mathrm{a}}{\text{NUE}}_{J_{\text{{max}}}} + J_{\text{max}0} = J_{\text{max}b0}{\text{FNC}}_{\mathrm{a}}{\text{NUE}}_{J_{\text{max}}} -where :math:`J_{\text{max}b0}` (unitless) is the baseline proportion of nitrogen allocated for electron transport rate. :math:`{\text{NUE}}_{J_{\text{{max}}}}` ( :math:`{\mu} mol` electron /s/g N) is the nitrogen use efficiency of :math:`J_{\text{{max}}}`. :math:`J_{\text{max}b1}` (unitless) is a coefficient determining the response of the electron transport rate to amount of absorbed light (i.e., :math:`\alpha \text{PAR}`). :math:`f\left(\text{day length} \right)` is a function specifies the impact of day length (hours) on :math:`J_{\text{max}}` in view that longer day length has been demonstrated by previous studies to alter :math:`V_{\mathrm{c}\text{max}25}` and :math:`J_{\text{max}25}` (Bauerle et al. 2012; Comstock and Ehleringer 1986) through photoperiod sensing and regulation (e.g., Song et al. 2013). Following Bauerle et al. (2012), :math:`f\left(\text{day length} \right)` is simulated as follows, +where :math:`J_{\text{max}b0}` (unitless) is the baseline proportion of nitrogen allocated for electron transport rate. :math:`{\text{NUE}}_{J_{\text{max}}}` (μmol electron/s/g N) is the nitrogen use efficiency of :math:`J_{\text{max}}`. :math:`J_{\text{max}b1}` (unitless) is a coefficient determining the response of the electron transport rate to amount of absorbed light (i.e., :math:`\alpha \text{PAR}`). :math:`f\left(\text{day length} \right)` is a function specifies the impact of day length (hours) on :math:`J_{\text{max}}` in view that longer day length has been demonstrated by previous studies to alter :math:`V_{\mathrm{c}\text{max}25}` and :math:`J_{\text{max}25}` (:ref:`Bauerle et al. 2012`; :ref:`Comstock and Ehleringer 1986`) through photoperiod sensing and regulation (e.g., :ref:`Song et al. 2013`). Following :ref:`Bauerle et al. (2012)`, :math:`f\left(\text{day length} \right)` is simulated as follows, .. math:: - :label: 10.7) + :label: :day_length:) f\left(\text{day length} \right) = \left(\frac{\text{day length}}{12} \right)^{2}. -:math:`f\left(\text{humidity} \right)` represents the impact of air humidity on :math:`J_{\text{{max}}}`. We assume that higher humidity leads to higher :math:`J_{\text{{max}}}` with less water limitation on stomata opening and that low relative humidity has a stronger impact on nitrogen allocation due to greater water limitation. When relative humidity (RH; unitless) is too low, we assume that plants are physiologically unable to reallocate nitrogen. We therefore assume that there exists a critical value of relative humidity ( :math:`RH_{0} = 0.25`; unitless), below which there is no optimal nitrogen allocation. Based on the above assumptions, we have +:math:`f\left(\text{humidity} \right)` represents the impact of air humidity on :math:`J_{\text{{max}}}`. We assume that higher humidity leads to higher :math:`J_{\text{max}}` with less water limitation on stomata opening and that low relative humidity has a stronger impact on nitrogen allocation due to greater water limitation. When relative humidity (RH; unitless) is too low, we assume that plants are physiologically unable to reallocate nitrogen. We therefore assume that there exists a critical value of relative humidity (:math:`RH_{0} = 0.25`; unitless), below which there is no optimal nitrogen allocation. Based on the above assumptions, we have .. math:: - :label: 10.8) + :label: :humidity:) f\left(\text{humidity} \right) = \left(1-\mathrm{e}^{\left(-H @@ -165,22 +164,22 @@ where :math:`J_{\text{max}b0}` (unitless) is the baseline proportion of nitrogen where :math:`H` (unitless) specifies the impact of relative humidity on electron transport rate. -The efficiency of light energy absorption (unitless), :math:`\alpha`, is calculated depending on the amount of nitrogen allocated for light capture, :math:`\mathrm{N}_{\text{lc}}`. Following Niinemets and Tenhunen (1997), the LUNA model has, +The efficiency of light energy absorption (unitless), :math:`\alpha`, is calculated depending on the amount of nitrogen allocated for light capture, :math:`\mathrm{N}_{\text{lc}}`. Following :ref:`Niinemets and Tenhunen (1997)`, the LUNA model has, .. math:: - :label: 10.9) + :label: :light_energy_absorp_alpha:) \alpha =\frac{0.292}{1+\frac{0.076}{\mathrm{N}_{\text{lc}}C_{b}}} -where 0.292 is the conversion factor from photon to electron. :math:`C_{b}` is the conversion factor (1.78) from nitrogen to chlorophyll. After we estimate :math:`J_{\text{{max}}}`, the actual electron transport rate with the daily maximum radiation ( :math:`J_{x}`) can be calculated using the empirical expression of leaf (1937), +where 0.292 is the conversion factor from photon to electron. :math:`C_{b}` is the conversion factor (set to 1.78) from nitrogen to chlorophyll. After we estimate :math:`J_{\text{max}}`, the actual electron transport rate with the daily maximum radiation (:math:`J_{x}`) can be calculated using the empirical expression of :ref:`Smith (1937)`, .. math:: - :label: 10.10) + :label: :J_x:) J_{x} = \frac{\alpha \text{PAR}_{\text{max}}} {\left(1 + \frac{\alpha^{2}{\text{PAR}}_{\text{{max}}}^{2}}{J_{\text{{max}}}^{2}} \right)^{0.5}} -where :math:`\text{PAR}_{\text{{max}}}` ( :math:`\mu mol`/m :sup:`2`/s) is the maximum photosynthetically active radiation during the day. +where :math:`\text{PAR}_{\text{max}}` (μmol/m\ :sup:`2`/s) is the maximum photosynthetically active radiation during the day. Maximum rate of carboxylation '''''''''''''''''''''''''''''' @@ -188,56 +187,56 @@ Maximum rate of carboxylation The maximum rate of carboxylation at 25°C varies with foliage nitrogen concentration and specific leaf area and is calculated as in :ref:`Thornton and Zimmermann (2007)`. At 25°C, .. math:: - :label: 10.11) + :label: :vcmax25:) V_{c\max 25} = N_{cb} NUE_{V_{c\max 25}} -where :math:`N_{cb}` is nitrogen for carboxylation (g N m\ :sup:`-2` leaf, :numref:`Table Plant functional type (PFT) leaf N parameters`), and :math:`NUE_{V_{c\max 25}}` = 47.3 x 6.25 and is the nitrogen use efficiency for :math:`V_{c\max 25}`. The constant 47.3 is the specific Rubisco activity ( :math:`\mu` mol CO\ :sub:`2` g\ :sup:`-1` Rubisco s\ :sup:`-1`) measured at 25°C, and the constant 6.25 is the nitrogen binding factor for Rubisco (g Rubisco g\ :sup:`-1` N; :ref:`Rogers 2014`). +where :math:`N_{cb}` is nitrogen for carboxylation (g N/m\ :sup:`2` leaf, :numref:`Table Plant functional type (PFT) leaf N parameters`), and :math:`NUE_{V_{c\max 25}}` = 47.3 x 6.25 and is the nitrogen use efficiency for :math:`V_{c\max 25}`. The constant 47.3 is the specific Rubisco activity (μmol CO\ :sub:`2`/g Rubisco/s) measured at 25°C, and the constant 6.25 is the nitrogen binding factor for Rubisco (g Rubisco/g N; :ref:`Rogers 2014`). :math:`V_{c\max 25}` additionally varies with daylength (:math:`DYL`) using the function :math:`f(DYL)`, which introduces seasonal variation to :math:`V_{c\max }` .. math:: - :label: 10.12) + :label: :f_DYL:) f\left(DYL\right)=\frac{\left(DYL\right)^{2} }{\left(DYL_{\max } \right)^{2} } with :math:`0.01\le f\left(DYL\right)\le 1`. Daylength (seconds) is given by .. math:: - :label: 10.13) + :label: :DYL:) DYL=2\times 13750.9871\cos ^{-1} \left[\frac{-\sin \left(lat\right)\sin \left(decl\right)}{\cos \left(lat\right)\cos \left(decl\right)} \right] -where :math:`lat` (latitude) and :math:`decl` (declination angle) are from section :numref:`Solar Zenith Angle`. Maximum daylength (:math:`DYL_{\max }` ) is calculated similarly but using the maximum declination angle for present-day orbital geometry (:math:`\pm`\ 23.4667° [:math:`\pm`\ 0.409571 radians], positive for Northern Hemisphere latitudes and negative for Southern Hemisphere). +where :math:`lat` (latitude) and :math:`decl` (declination angle) are from section :numref:`Solar Zenith Angle`. Maximum daylength (:math:`DYL_{\max }`) is calculated similarly but using the maximum declination angle for present-day orbital geometry (:math:`\pm`\ 23.4667° [:math:`\pm`\ 0.409571 radians], positive for Northern Hemisphere latitudes and negative for Southern Hemisphere). Implementation of Photosynthetic Capacity '''''''''''''''''''''''''''''''''''''''''' -Based on :ref:`Farquhar et al. (1980)` and Wullschleger (1993), we can calculate the electron-limited photosynthetic rate under daily maximum radiation ( :math:`W_{jx}`) and the Rubisco-limited photosynthetic rate ( :math:`W_{\mathrm{c}}`) as follows, +Based on :ref:`Farquhar et al. (1980)` and :ref:`Wullschleger (1993)`, we can calculate the electron-limited photosynthetic rate under daily maximum radiation (:math:`W_{jx}`) and the Rubisco-limited photosynthetic rate (:math:`W_{\mathrm{c}}`) as follows, .. math:: - :label: 10.14) + :label: :W_Jx:) W_{J_{x}} = K_{j}J_{x} , .. math:: - :label: 10.15) + :label: :W_c_1:) W_{\mathrm{c}} = K_{\mathrm{c}} V_{{\mathrm{c}, \text{max}}}, -where :math:`K_{j}` and :math:`K_{\mathrm{c}}` as the conversion factors for :math:`J_{x}` and :math:`V_{{\mathrm{c}, \text{max}}}` ( :math:`V_{{\mathrm{c}, \text{max}}}` to :math:`W_{\mathrm{c}}` and :math:`J_{x}` to :math:`W_{J_{x}}`), respectively. Based on :ref:`Xu et al. (2012)`, Maire et al. (2012) and Walker et al. (2014), we assume that :math:`W_{\mathrm{c}}` is proportional to :math:`W_{J_{x}}`. Specifically, we have +where :math:`K_{j}` and :math:`K_{\mathrm{c}}` as the conversion factors for :math:`J_{x}` and :math:`V_{{\mathrm{c}, \text{max}}}` (:math:`V_{{\mathrm{c}, \text{max}}}` to :math:`W_{\mathrm{c}}` and :math:`J_{x}` to :math:`W_{J_{x}}`), respectively. Based on :ref:`Xu et al. (2012)`, :ref:`Maire et al. (2012)` and :ref:`Walker et al. (2014)`, we assume that :math:`W_{\mathrm{c}}` is proportional to :math:`W_{J_{x}}`. Specifically, we have .. math:: - :label: 10.16) + :label: :W_c_2:) W_{\mathrm{c}}=t_{\alpha}t_{\mathrm{c}, j0}W_{J_{x}} -where :math:`t_{\mathrm{c}, j0}` is the baseline ratio of :math:`W_{\mathrm{c}}` to :math:`W_{J_{x}}`. We recognize that this ratio may change depending on the nitrogen use efficiency of carboxylation and electron transport (Ainsworth and Rogers 2007), therefore the LUNA model has the modification factor, :math:`t_{\alpha}`, to adjust baseline the ratio depending on the nitrogen use efficiency for electron vs carboxylation (:ref:`Ali et al. 2016`). +where :math:`t_{\mathrm{c}, j0}` is the baseline ratio of :math:`W_{\mathrm{c}}` to :math:`W_{J_{x}}`. We recognize that this ratio may change depending on the nitrogen use efficiency of carboxylation and electron transport (:ref:`Ainsworth and Rogers 2007`), therefore the LUNA model has the modification factor, :math:`t_{\alpha}`, to adjust baseline the ratio depending on the nitrogen use efficiency for electron vs carboxylation (:ref:`Ali et al. 2016`). Total Respiration ''''''''''''''''''' -Following :ref:`Collatz et al. (1991)`, the total respiration ( :math:`R_{\mathrm{t}}`) is calculated in proportion to :math:`V_{\text{c,max}}`, +Following :ref:`Collatz et al. (1991)`, the total respiration (:math:`R_{\mathrm{t}}`) is calculated in proportion to :math:`V_{\text{c,max}}`, .. math:: :label: 10.17) @@ -258,4 +257,4 @@ where :math:`D_{\text{day}}` and :math:`D_{\text{night}}` are daytime and nightt Numerical scheme --------------------------------------------------------- -The LUNA model searches for the "optimal" nitrogen allocations for maximum net photosynthetic carbon gain by incrementally increase the nitrogen allocated for light capture (i.e., :math:`N_{\text{lc}}`) (see :ref:`Ali et al. (2016)` for details). We assume that plants only optimize the nitrogen allocation when they can grow (i.e., GPP>0.0). If GPP become zero under stress, then the LUNA model assume a certain amount of enzyme will decay at daily rates of 0.1, in view that the half-life time for photosynthetic enzymes are short (~7 days) (Suzuki et al. 2001). To avoid unrealistic low values of photosynthetic capacity, the decay is only limited to 50 percent of the original enzyme levels. +The LUNA model searches for the "optimal" nitrogen allocations for maximum net photosynthetic carbon gain by incrementally increase the nitrogen allocated for light capture (i.e., :math:`N_{\text{lc}}`) (see :ref:`Ali et al. 2016` for details). We assume that plants only optimize the nitrogen allocation when they can grow (i.e., GPP > 0.0). If GPP becomes zero under stress, then the LUNA model assumes a certain amount of enzymes will decay at daily rates of 0.1, in the view that the half-life time for photosynthetic enzymes is short (~7 days) (:ref:`Suzuki et al. 2001`). To avoid unrealistically low values of photosynthetic capacity, this decay is limited to 50% of the original enzyme levels. diff --git a/doc/source/tech_note/References/CLM50_Tech_Note_References.rst b/doc/source/tech_note/References/CLM50_Tech_Note_References.rst index 58ab424a81..6d79f0c64f 100644 --- a/doc/source/tech_note/References/CLM50_Tech_Note_References.rst +++ b/doc/source/tech_note/References/CLM50_Tech_Note_References.rst @@ -11,6 +11,10 @@ Aber, J.D., Melillo, J.M. and McClaugherty, C.A., 1990. Predicting long-term pat Aber, J.D., Goodale, C.L., Ollinger, S.V., Smith, M.-L., Magill, A.H., Martin, M.E., Hallett, R.A., and Stoddard, J.L. 2003. Is nitrogen deposition altering the nitrogen status of northeastern forests? BioScience 53:375-389. +.. _AinsworthRogers2007: + +Ainsworth, E. A. and Rogers, A. 2007. The response of photosynthesis and stomatal conductance to rising (CO2): mechanisms and environmental interactions, Plant Cell Environ. 30:258-270. + .. _AlduchovandEskridge1996: Alduchov, O.A., and Eskridge, R.E. 1996. Improved Magnus form approximation of saturation vapor pressure. J. Appl. Meteor. 35:601-609. @@ -83,6 +87,10 @@ Baird, A.J., Beckwith, C.W., Waldron, S. and Waddington, J.M., 2004. Ebullition Baldocchi, D., et al. 2001. FLUXNET: A new tool to study the temporal and spatial variability of ecosystem-scale carbon dioxide, water vapor, and energy flux densities. Bull. Amer. Meteor. Soc. 82:2415-2433. +.. _Balletal1987: + +Ball, J.T., Woodrow, I.E., and Berry, J.A. 1987. A model predicting stomatal conductance and its contribution to the control of photosynthesis under different environmental conditions. Dordrecht, The Netherlands, 221-224. + .. _Barbottinetal2005: Barbottin, A., Lecomte, C., Bouchard, C., and Jeuffroy, M.-H. 2005. Nitrogen remobilization during grain filling in wheat: Genotypic and environmental effects. Crop Sci. 45:1141-1150. @@ -91,6 +99,11 @@ Barbottin, A., Lecomte, C., Bouchard, C., and Jeuffroy, M.-H. 2005. Nitrogen rem Batjes, N.H., 2006. ISRIC-WISE derived soil properties on a 5 by 5 arc-minutes global grid. Report 2006/02 (available through : http://www.isric.org) +.. _Bauerleetal2012: + +Bauerle, W.L., Oren, R., Way, D.A., Qian, S.S., Stoy, P.C., Thornton, P.E., Bowden, J.D., Hoffman, F.M., and Reynolds, R.F. 2012. Photoperiodic regulation of the seasonal pattern of photosynthetic capacity and the implications for carbon cycling. Proc. Natl. Acad. Sci. USA, 109:8612-8617. + + .. _Berger1978a: Berger, A.L. 1978a. Long-term variations of daily insolation and quaternary climatic changes. J. Atmos. Sci. 35:2362-2367. @@ -111,6 +124,10 @@ Berkowitz, B., and Balberg, I. 1992. Percolation approach to the problem of hydr Beven, K.J., and Kirkby, M.J. 1979. A physically based variable contributing area model of basin hydrology. Hydrol. Sci. Bull. 24:43-69. +.. _Birchetal2021: + +Birch, L., Schwalm, C.R., Natali, S., Lombardozzi, D., Keppel-Aleks, G., Watts, J., Lin, X., Zona, D., Oechel, W., Sachs, T., Black, T.A., and Rogers, B.M. 2021. Addressing biases in Arctic–boreal carbon cycling in the Community Land Model Version 5, Geosci. Model Dev., 14, 3361–3382. + .. _BohrenHuffman1983: Bohren, C. F., and Huffman, D. R. 1983. Absorption and scattering of light by small particles. John Wiley & Sons, New York, NY. @@ -187,9 +204,13 @@ Buzan, J.R., Oleson, K., and Huber, M. 2015: Implementation and comparison of a Byram, G.M., 1959. Combustion of forest fuels. In Forest fire: control and use.(Ed. KP Davis) pp. 61-89. +.. _Bytnerowiczetal2022: + +Bytnerowicz, T. A., Akana, P. R., Griffin, K. L., & Menge, D. N. L. 2022: Temperature sensitivity of woody nitrogen fixation across species and growing temperatures. Nature Plants, 8(3), 209-216. doi: 10.1038/s41477-021-01090-x. + .. _CampbellNorman1998: -Campbell, G.S., and Norman, J.M. 1998. An Introduction to Environmental Biophysics (2:math:`{}^{nd}` edition). Springer-Verlag, New York. +Campbell, G.S., and Norman, J.M. 1998. An Introduction to Environmental Biophysics (2nd edition). Springer-Verlag, New York. .. _Castilloetal2012: @@ -239,6 +260,10 @@ Collatz, G.J., Ribas-Carbo, M., and Berry, J.A. 1992. Coupled photosynthesis-sto Colmer, T.D., 2003. Long-distance transport of gases in plants: a perspective on internal aeration and radial oxygen loss from roots. Plant Cell and Environment 26:17-36. +.. _ComstockEhleringer1986: + +Comstock, J. and Ehleringer, J.R. 1986. Photoperiod and photosynthetic capacity in *Lotus scoparius*. Plant Cell Environ. 9:609-612. + .. _Comolaetal2019: Comola, F., Kok, J.F., Chamecki, M. and Martin, R.L., 2019. The intermittency of wind‐driven sand transport. Geophysical Research Letters, 46(22), pp.13430-13440. DOI:10.1029/2019GL085739. @@ -279,6 +304,10 @@ Dai, Y., Dickinson, R.E., and Wang, Y.-P. 2004. A two-big-leaf model for canopy Dai, A., and Trenberth, K.E. 2002. Estimates of freshwater discharge from continents: Latitudinal and seasonal variations. J. Hydrometeor. 3:660-687. +.. _Damseauxetal2025: + +Damseaux, A., Matthes, H., Dutch, V.R., Wake, L., and Rutter, N. 2025. Impact of snow thermal conductivity schemes on pan-Arctic permafrost dynamics in the Community Land Model version 5.0, The Cryosphere, 19, 1539–1558, DOI:10.5194/tc-19-1539-2025. + .. _Darmenovaetal2009: Darmenova, K., Sokolik, I.N., Shao, Y., Marticorena, B. and Bergametti, G., 2009. Development of a physically based dust emission module within the Weather Research and Forecasting (WRF) model: Assessment of dust emission parameterizations and input parameters for source regions in Central and East Asia. Journal of Geophysical Research: Atmospheres, 114(D14). DOI:10.1029/2008JD011236. @@ -339,6 +368,14 @@ Drewniak, B., Song, J., Prell, J., Kotamarthi, V.R., and Jacob, R. 2013. Modelin Dunfield, P., Knowles, R., Dumont, R. and Moore, T.R., 1993. Methane Production and Consumption in Temperate and Sub-Arctic Peat Soils - Response to Temperature and Ph. Soil Biology & Biochemistry 25:321-326. +.. _Dutchetal2022: + +Dutch, V.R., Rutter, N., Wake, L., Sandells, M., Derksen, C., Walker, B., Hould Gosselin, G., Sonnentag, O., Essery, R., Kelly, R., Marsh, P., King, J., Boike, J. 2022. Impact of measured and simulated tundra snowpack properties on heat transfer, The Cryosphere, 16, 4201–4222, doi:10.5194/tc-16-4201-2022. + +.. _Eiteletal2019: + +Eitel, J.U., Maguire, A.J., Boelman, N., Vierling, L.A., Griffin, K.L., Jensen, J., Magney, T.S., Mahoney, P.J., Meddens, A.J., Silva, C., and Sonnentag, O. 2019. Proximal remote sensing of tree physiology at northern treeline: Do late-season changes in the photochemical reflectance index (PRI) respond to climate or photoperiod? Remote Sens. Environ. 221:340–350. + .. _EntekhabiEagleson1989: Entekhabi, D., and Eagleson, P.S. 1989. Land surface hydrology parameterization for atmospheric general circulation models including subgrid scale spatial variability. J. Climate 2:816-831. @@ -347,6 +384,10 @@ Entekhabi, D., and Eagleson, P.S. 1989. Land surface hydrology parameterization Fang, X. and Stefan, H.G., 1996. Long-term lake water temperature and ice cover simulations/measurements. Cold Regions Science and Technology 24:289-304. +.. _Fangetal2026: + +Fang, B., Zhao, L., Oleson, K., Zhang, K., Lawrence, P., Sacks, B., Cao, C., He, C., Huang, Q., Liu, Z., and Lee, X. 2026. Representing dynamic urban land change in the Community Earth System Model (CESM). JAMES, in revision. + .. _Farouki1981: Farouki, O.T. 1981. The thermal properties of soils in cold regions. Cold Regions Sci. and Tech. 5:67-75. @@ -387,6 +428,10 @@ Fisher, R. A., S. Muszala, M. Verteinstein, P. Lawrence, C. Xu, N. G. McDowell, Fisher, R.A., C.D. Koven, W.R.L. Anderegg, et al., 2018: Vegetation demographics in Earth System Models: A review of progress and priorities. Glob Change Biol. 2018;24:35–54. https://doi.org/10.1111/gcb.13910 +.. _Fisheretal2019: + +Fisher, R.A., Wieder, W.R., Sanderson, B., Koven, C.D., Oleson, K.W., Xu, C., Fisher, J.B., Shi, M., Walker, A.P., Lawrence, D.M. 2019. Parametric controls on vegetation responses to biogeochemical forcing in the CLM5. Journal of Advances in Modeling Earth Systems, 11, 2879–2895. DOI:10.1029/2019MS001609 + .. _FlannerZender2005: Flanner, M.G., and Zender. C.S. 2005. Snowpack radiative heating: Influence on Tibetan Plateau climate. Geophys. Res. Lett. 32:L06501. DOI:10.1029/2004GL022076. @@ -431,6 +476,10 @@ Gallais, A., Coque, M., Gouis, J. L., Prioul, J. L., Hirel, B., and Quillere, I. Galloway, J.N., et al. 2004. Nitrogen cycles: past, present, and future. Biogeochem. 70:153-226. +.. _GaoOneill2020: + +Gao, J., and O'Neill, B.C. 2020. Mapping global urban land for the 21st century with data-driven simulations and Shared Socioeconomic Pathways. Nature Communications, 11(1), 2302. https://doi.org/10.1038/s41467-020-15788-7. + .. _Garciaetal1988: Garcia, R.L., Kanemasu, E.T., Blad, B.L., Bauer, A., Hatfield, J.L., Major, D.A., Reginato, R.J., and Hubbard, K.G. 1988. Interception and use efficiency of light in winter wheat under different nitrogen regimes. Agric. For. Meteor. 44:175-186. @@ -519,6 +568,10 @@ Hansen, M., DeFries, R.S., Townshend, J.R.G., Carroll, M., Dimiceli, C., and Soh Hastings, D.A., Dunbar, P.K., Elphingstone, G.M., Bootz, M., Murakami, H., Maruyama, H., Masaharu, H., Holland, P., Payne, J., Bryant, N.A., Logan, T.L., Muller, J.-P., Schreier, G., and MacDonald, J.S., eds., 1999. The Global Land One-kilometer Base Elevation (GLOBE) Digital Elevation Model, Version 1.0. National Oceanic and Atmospheric Administration, National Geophysical Data Center, 325 Broadway, Boulder, Colorado 80305-3328, U.S.A. +.. _Hauseretal2023: + +Hauser, E., Wieder, W.R., Bonan, G.B., and Cleveland, C.C. 2023. Flexible foliar stoichiometry reduces the magnitude of the global land carbon sink. Geophys. Res. Lett. 50(21), e2023GL105493. DOI:10.1029/2023GL105493 + .. _Healdetal2008: Heald, C.L., Henze, D.K., Horowitz, L.W., Feddema, J., Lamarque, J.-F., Guenther, A., Hess, P.G., Vitt, F., Seinfeld, J.H., Goldstein, A.H., and Fung, I. 2008. Predicted change in global secondary organic aerosol concentrations in response to future climate, emissions, and land use change. J. Geophys. Res. 113:D05211. DOI:10.1029/2007JD009092. @@ -559,6 +612,10 @@ Hou, Z., Huang, M., Leung, L.R., Lin, G., and Ricciuto, D.M. 2012. Sensitivity o Houlton, B.Z., Wang, Y.P., Vitousek, P.M. and Field, C.B., 2008. A unifying framework for dinitrogen fixation in the terrestrial biosphere. Nature, 454(7202), p.327. +.. _Houltonetal2015: + +Houlton, B., Marklein, A. & Bai, E. Representation of nitrogen in climate change forecasts. Nature Clim Change 5, 398–401 (2015). https://doi.org/10.1038/nclimate2538 + .. _HuangLiang2006: Huang, M., and Liang, X. 2006. On the assessment of the impact of reducing parameters and identification of parameter uncertainties for a hydrologic model with applications to ungauged basins. J. Hydrol. 320:37-61. @@ -611,6 +668,10 @@ Jenkinson, D. and Coleman, K. 2008. The turnover of organic carbon in subsoils. Jordan, R. 1991. A One-dimensional Temperature Model for a Snow Cover: Technical Documentation for SNTHERM.89. U.S. Army Cold Regions Research and Engineering Laboratory, Special Report 91-16. +.. _Kou-Giesbrechtetal2025: + +Kou-Giesbrecht, C.R. Reis Ely, S.S. Perakis, C.C. Cleveland, D.N.L. Menge, S.C. Reed, B.N. Taylor, S.A. Batterman, T.E. Crews, K.A. Dynarski, M. Gei, M.J. Gundale, D.F. Herridge, S.E. Jovan, M.B. Peoples, J. Piipponen, E. Rodríguez-Caballero, V.G. Salmon, F.M. Soper, A.P. Staccone, B. Weber, C.A. Williams, & N. Wurzburger, 2025. Overestimated natural biological nitrogen fixation translates to an exaggerated CO2 fertilization effect in Earth system models, Proc. Natl. Acad. Sci. U.S.A. 122 (48) e2514628122, DOI:10.1073/pnas.2514628122. + .. _KattgeKnorr2007: Kattge, J., and Knorr, W. 2007. Temperature acclimation in a biochemical model of photosynthesis: a reanalysis of data from 36 species. Plant Cell Environ. 30:1176-1190. DOI:10.1111/j.1365-3040.2007.01690.x. @@ -839,6 +900,10 @@ Li, H., L. Leung, A. Getirana, M. Huang, H. Wu, Y. Xu, J. Guo and N. Voisin. 201 Li, H., L. Leung, T. Tesfa, N. Voisin, M. Hejazi, L. Liu, Y. Liu, J. Rice, H. Wu, and X. Yang. 2015. Modeling stream temperature in the Anthropocene: An earth system modeling approach, J. Adv. Model. Earth Syst., 7, doi:10.1002/2015MS000471. +.. _Lietal2024: + +Li, X. "C", Zhao, L., Oleson, K., Zhou, Y., Qin, Y., Zhang, K., and Fang, B. 2024. Enhancing urban climate‐energy modeling in the Community Earth System Model (CESM) through explicit representation of urban air‐conditioning adoption. JAMES, 16, e2023MS004107. https://doi.org/10.1029/2023MS004107. + .. _Liangetal1994: Liang, X., Lettenmaier, D.P., Wood, E.F., and Burges, S.J. 1994. A simple hydrologically based model of land surface water and energy fluxes for GSMs. J. Geophys. Res. 99(D7):14,415–14,428. @@ -895,6 +960,14 @@ Magill, A.H. et al., 1997. Biogeochemical response of forest ecosystems to simul Mahowald, N.M., Muhs, D.R., Levis, S., Rasch, P.J., Yoshioka, M., Zender, C.S., and Luo, C. 2006. Change in atmospheric mineral aerosols in response to climate: last glacial period, pre-industrial, modern and doubled CO\ :sub:`2` climates. J. Geophys. Res\ *.* 111:D10202. DOI:10.1029/2005JD006653. +.. _Maireetal2012: + +Maire, V., Martre, P., Kattge, J., Gastal, F., Esser, G., Fontaine, S., and Soussana, F. 2012. The coordination of leaf photosynthesis links C and N fluxes in C3 plant species, PLos ONE, 7:e38245. doi:38310.31371/journal.pone.0038345. + +.. _MajasalmiBright2019: + +Majasalmi, T., and Bright, R.M. 2019. Evaluation of leaf-level optical properties employed in land surface models. Geosci. Model Dev. 12:3923-3938. https://doi.org/10.5194/gmd-12-3923-2019. + .. _Makela2002: Makela, A. 2002. Derivation of stem taper from the pipe model theory in a carbon balance framework. Tree Phys. 22:891-905. @@ -992,9 +1065,17 @@ Negron-Juarez, R. Koven, C.D., Riley, W.J., Knox, R.G., Chambers, J.Q. 2015. Env Nemani, R.R., and Running, S.W. 1996. Implementation of a hierarchical global vegetation classification in ecosystem function models. J. Veg. Sci. 7:337-346. +.. _Nevisonetal2022: + +Nevison, C., Hess, P., Goodale, C., Zhu Q., and Vira, J. 2022. Nitrification, Denitrification, and Competition for Soil N: Evaluation of Two Earth System Models against Observations. Ecological Applications 32(4): e2528. doi:10.1002/eap.2528 + .. _Niinemetstal1998: -Niinemets, U., Kull, O., and Tenhunen, J.D. 1998. An analysis of light effects on foliar morphology, physiology, and light interception in temperate deciduous woody species of contrasting shade tolerance. Tree Phys. 18:681-696. +Niinemets, Ü., Kull, O., and Tenhunen, J.D. 1998. An analysis of light effects on foliar morphology, physiology, and light interception in temperate deciduous woody species of contrasting shade tolerance. Tree Phys. 18:681-696. + +.. _NiinetmetsTenhunen1997: + +Niinemets, Ü. and Tenhunen, J.D. 1997. A model separating leaf structural and biphysiological effects on carbon gain along light gradients for the shade-tolerant species *Acer saccharum*. Plant Cell Environ., 20:845-86. .. _Niuetal2005: @@ -1018,7 +1099,7 @@ Oikawa, S., Hikosaka, K. and Hirose, T., 2005. Dynamics of leaf area and nitroge .. _Oke1987: -Oke, T. 1987. Boundary Layer Climates (2:math:`{}^{nd}` edition). Routledge, London and New York. +Oke, T. 1987. Boundary Layer Climates (2nd edition). Routledge, London and New York. .. _Okin2008: @@ -1056,9 +1137,9 @@ Oleson, K.W., Bonan, G.B., Feddema, J., Vertenstein, M., and Kluzek, E. 2010b. T Oleson, K.W., et al. 2013. Technical description of version 4.5 of the Community Land Model (CLM). NCAR Technical Note NCAR/TN-503+STR, National Center for Atmospheric Research, Boulder, CO, 420 pp. -.. _OlesonFeddema2018: +.. _OlesonFeddema2020: -Oleson, K.W., and Feddema, J. 2018. Parameterization and surface data improvements and new capabilities for the Community Land Model Urban (CLMU). JAMES, submitted. +Oleson, K.W., and Feddema, J. 2020. Parameterization and surface data improvements and new capabilities for the Community Land Model Urban (CLMU). JAMES, 12, e2018MS0001586, https://doi.org/10.1029/2018MS001596. .. _Olson1963: @@ -1356,10 +1437,19 @@ Smith, A.M.S., Wooster, M.J., Drake, N.A., Dipotso, F.M. and Perry, G.L.W., 2005 Smith, A.M. and M. Stitt, 2007. Coordination of carbon supply and plant growth. Plant, cell & environment 30.9, pp. 1126-1149. +.. _Smith1937: + +Smith, E. 1937. The influence of light and carbon dioxide on photosynthesis. General Physiology, 20:807-830. + .. _Sollins1982: Sollins, P., 1982. Input and decay of coarse woody debris in coniferous stands in western Oregon and Washington. Canadian Journal of Forest Research, 12: 18-28. + +.. _Songetal2013: + +Song, Y.H., Ito, S., and Imaizumi, T. 2013. Flowering time regulation: photoperiod- and temperature-sensing in leaves. Trends Plant Sci. 18:575–583. + .. _SonGower1991: Son, Y. and Gower, S.T., 1991. Aboveground nitrogen and phosphorus use by five plantation-grown trees with different leaf longevities. Biogeochemistry, 14: 167-191. @@ -1404,6 +1494,10 @@ Strahler, A.H., Muchoney, D., Borak, J., Friedl, M., Gopal, S., Lambin, E., and Stull, R.B. 1988. An Introduction to Boundary Layer Meteorology. Kluwer Academic Publishers, Dordrecht. +.. _Sturmetal1997: + +Sturm, M., Holmgren, J., Konig, M., and Morris, K. 1997. The thermal conductivity of seasonal snow. Journal of Glaciology 43:26-41. + .. _Subinetal2012a: Subin, Z.M., Riley, W.J. and Mironov, D. 2012a. Improved lake model for climate simulations, J. Adv. Model. Earth Syst., 4, M02001. DOI:10.1029/2011MS000072. @@ -1416,6 +1510,10 @@ Subin, Z.M., Murphy, L.N., Li, F., Bonfils, C. and Riley, W.J., 2012b. Boreal la Sun, Y., Gu, L., and Dickinson, R. E. 2012. A numerical issue in calculating the coupled carbon and water fluxes in a climate model, J. Geophys. Res., 117, D22103. DOI:10.1029/2012JD018059. +.. _Suzukietal2001: + +Suzuki, Y., Makino, A. and Mae, T. 2001. Changes in the turnover of Rubisco and levels of mRNAs of rbcL and rbcS in rice leaves from emergence to senescence. Plant, Cell & Environment, 24:1353-1360. DOI:10.1046/j.0016-8025.2001.00789.x + .. _Swensonetal2012: Swenson, S.C., Lawrence, D.M., and Lee, H. 2012. Improved Simulation of the Terrestrial Hydrological Cycle in Permafrost Regions by the Community Land Model. JAMES, 4, M08002. DOI:10.1029/2012MS000165. @@ -1564,6 +1662,10 @@ Viovy, N. 2011. CRUNCEP dataset. [Description available at http://dods.extra.cea Vitousek, P.M., and Howarth, R.W. 1991. Nitrogen limitation on land and in the sea: How can it occur? Biogeochem. 13:87-115. +.. _Walkeretal2014: + +Walker, A. P., Beckerman, A. P., Gu, L., Kattge, J., Cernusak, L. A., Domingues, T. F., Scales, J. C., Wohlfahrt, G., Wullschleger, S. D., and Woodward, F. I. 2014. The relationship of leaf photosynthetic traits - Vcmax and Jmax - to leaf nitrogen, leaf phosphorus, and specific leaf area: a meta-analysis and modeling study. Ecology and Evolution, 4:3218-3235. + .. _Walteretal2001: Walter, B.P., Heimann, M. and Matthews, E., 2001. Modeling modern methane emissions from natural wetlands 1. Model description and results. J. Geophys. Res. 106(D24):34189-34206. @@ -1596,6 +1698,14 @@ White, M.A., Thornton, P.E., Running, S.W., and Nemani, R.R. 2000. Parameterizat Wieder, W. R., Cleveland, C. C., Lawrence, D. M., and Bonan, G. B. 2015. Effects of model structural uncertainty on carbon cycle projections: biological nitrogen fixation as a case study. Environmental Research Letters, 10(4), 044016. +.. _Wiederetal2019: + +Wieder, W.R., Lawrence, D.M., Fisher, R.A., Bonan, G.B., Cheng, S.J., Goodale, C.L., Grandy, A.S., Koven, C.D., Lombardozzi, D.L., Oleson, K.W. and Thomas, R.Q., 2019. Beyond static benchmarking: Using experimental manipulations to evaluate land model assumptions. Global Biogeochemical Cycles, 33(10), 1289-1309. DOI:10.1029/2018GB006141 + +.. _Wiederetal2021: + +Wieder, W.R., Butterfield, Z., Lindsay, K., Lombardozzi, D.L., Keppel-Aleks, G. 2021. Interannual and seasonal drivers of carbon cycle variability represented by the Community Earth System Model (CESM2). Global Biogeochemical Cycles, 35, e2021GB007034. DOI:10.1029/2021GB007034 + .. _Williamsetal1996: Williams, M., Rastetter, E.B., Fernandes, D.N., Goulden, M.L., Wofsy, S.C., Shaver, G.R., Melillo, J.M., Munger, J.W., Fan, S.M. and Nadelhoffer, K.J. 1996. Modelling the soil-plant-atmosphere continuum in a Quercus–Acer stand at Harvard Forest: the regulation of stomatal conductance by light, nitrogen and soil/plant hydraulic properties. Plant, Cell & Environment, 19: 911–927. doi:10.1111/j.1365-3040.1996.tb00456.x @@ -1620,6 +1730,10 @@ Wu, H., J. S. Kimball, N. Mantua, and J. Stanford, 2011: Automated upscaling of Wu, H., J. S. Kimball, H. Li, M. Huang, L. R. Leung, and R. F. Adler, 2012. A New Global River Network Database for Macroscale Hydrologic modeling, Water Resour. Res., 48, W09701, doi:10.1029/2012WR012313. +.. _Wullschleger1993: + +Wullschleger, S.D. 1993. Biochemical limitations to carbon assimilation in C3 plants: a retrospective analysis of A/Ci curves from 109 species. J. Exp Bot. 44:907-920. + .. _xiaodong2005: Xiaodong, Y. and H.H. Shugart, 2005. FAREAST: a forest gap model to simulate dynamics and patterns of eastern Eurasian forests. Journal of Biogeography 32.9, pp. 1641-1658. @@ -1632,6 +1746,10 @@ Xu, C., R. Fisher, S. D. Wullschleger, C. J. Wilson, M. Cai, and N. G. McDowell, Yang, Z.-L. 1998. Technical note of a 10-layer soil moisture and temperature model. Unpublished manuscript. +.. _ZaehleandFriend2010: + +Zaehle, S. and A.D.Friend 2010. Carbon and nitrogen cycle dynamics in the O-CN land surface model: 1. Model description, site-scale evaluation, and sensitivity to parameter estimates, Global Biogeochem. Cycles, 24, GB1005, DOI:10.1029/2009GB003521. + .. _Zenderetal2003: Zender, C.S., Bian, H., and Newman, D. 2003. Mineral dust entrainment and deposition (DEAD) model: Description and 1990s dust climatology. ** J. Geophys. Res\ *.* 108(D14):4416. DOI:10.1029/2002JD002775. @@ -1660,6 +1778,8 @@ Zeng, X., Dickinson, R.E., Barlage, M., Dai, Y., Wang, G., and Oleson, K. 2005. Zeng, X., and Wang, A. 2007. Consistent parameterization of roughness length and displacement height for sparse and dense canopies in land models. J. Hydrometeor. 8:730-737. +.. _ZengandDecker2009: + Zeng, X., and Decker, M. 2009. Improving the numerical solution of soil moisture-based Richards equation for land models with a deep or shallow water table. J. Hydrometeor. 10:308-319. .. _Zengetal2008: diff --git a/doc/source/tech_note/Soil_Snow_Temperatures/CLM50_Tech_Note_Soil_Snow_Temperatures.rst b/doc/source/tech_note/Soil_Snow_Temperatures/CLM50_Tech_Note_Soil_Snow_Temperatures.rst index f5a2965f69..8fc3a14fec 100644 --- a/doc/source/tech_note/Soil_Snow_Temperatures/CLM50_Tech_Note_Soil_Snow_Temperatures.rst +++ b/doc/source/tech_note/Soil_Snow_Temperatures/CLM50_Tech_Note_Soil_Snow_Temperatures.rst @@ -723,38 +723,55 @@ where S_{r,\, i} =\left(\frac{w_{liq,\, i} }{\rho _{liq} \Delta z_{i} } +\frac{w_{ice,\, i} }{\rho _{ice} \Delta z_{i} } \right)\frac{1}{\theta _{sat,\, i} } =\frac{\theta _{liq,\, i} +\theta _{ice,\, i} }{\theta _{sat,\, i} } \le 1. -Thermal conductivity :math:`\lambda _{i}` (W m\ :sup:`-1` K\ :sup:`-1`) for snow is from :ref:`Jordan (1991) ` + +Thermal conductivity :math:`\lambda _{i}` (W m\ :sup:`-1` K\ :sup:`-1`) for snow in CLM6.0 is modified from :ref:`Sturm et al. (1997)`, as applied by :ref:`Dutch et al. (2022)` and :ref:`Damseaux et al. (2025)`. The Sturm function uses the bulk density of snow to determine the thermal conductivity of snow layer (:math:`_{i}`) as: .. math:: :label: 6.87 - \lambda _{i} =\lambda _{air} +\left(7.75\times 10^{-5} \rho _{sno,\, i} +1.105\times 10^{-6} \rho _{sno,\, i}^{2} \right)\left(\lambda _{ice} -\lambda _{air} \right) + \lambda _{i} = \left\{ + \begin{array}{lr} + 0.023 + 0.234(\rho _{sno,\, i} /1000) &\qquad \rho _{sno,\, i} <= 156 \\ + 0.138 - 1.01(\rho _{sno,\, i} /1000) + 3.233(\rho _{sno,\, i} /1000)^2 &\qquad \rho _{sno,\, i} > 156 + \end{array}\right\} -where :math:`\lambda _{air}` is the thermal conductivity of air (:numref:`Table Physical Constants`) and :math:`\rho _{sno,\, i}` is the bulk density of snow (kg m\ :sup:`-3`) + +with the bulk density of snow :math:`\rho _{sno,\, i}` (kg m\ :sup:`-3`) calculated as the mass of ice and liquid water per unit volume of snow layer .. math:: :label: 6.88 \rho _{sno,\, i} =\frac{w_{ice,\, i} +w_{liq,\, i} }{\Delta z_{i} } . + +Previous versions of CLM used the :ref:`Jordan (1991) ` parameterization for snow thermal conductivity, which uses the thermal conductivity of air and the bulk density of snow as: + +.. math:: + :label: 6.89 + + \lambda _{i} =\lambda _{air} +\left(7.75\times 10^{-5} \rho _{sno,\, i} +1.105\times 10^{-6} \rho _{sno,\, i}^{2} \right)\left(\lambda _{ice} -\lambda _{air} \right) + +where :math:`\lambda _{air}` is the thermal conductivity of air (:numref:`Table Physical Constants`) and :math:`\rho _{sno,\, i}` calculated, as in :eq:`6.88`. + +The :ref:`Sturm et al. (1997)` parameterization is used in CLM6 over vegetated, glacier, and lake land units, but users can choose to use the Jordan (1991) parameterization over any of these land units. This can be accomplished through a change to the lnd_in namelist by using user_nl_clm. The volumetric heat capacity :math:`c_{i}` (J m\ :sup:`-3` K\ :sup:`-1`) for soil is from :ref:`de Vries (1963) ` and depends on the heat capacities of the soil solid, liquid water, and ice constituents .. math:: - :label: 6.89 + :label: 6.90 c_{i} =c_{s,\, i} \left(1-\theta _{sat,\, i} \right)+\frac{w_{ice,\, i} }{\Delta z_{i} } C_{ice} +\frac{w_{liq,\, i} }{\Delta z_{i} } C_{liq} where :math:`C_{liq}` and :math:`C_{ice}` are the specific heat capacities (J kg\ :sup:`-1` K\ :sup:`-1`) of liquid water and ice, respectively (:numref:`Table Physical Constants`). The heat capacity of soil solids :math:`c_{s,i}` \ (J m\ :sup:`-3` K\ :sup:`-1`) is .. math:: - :label: 6.90 + :label: 6.91 c_{s,i} =(1-f_{om,i} )c_{s,\min ,i} +f_{om,i} c_{s,om} where the heat capacity of mineral soil solids :math:`c_{s,\min,\, i}` (J m\ :sup:`-3` K\ :sup:`-1`) is .. math:: - :label: 6.91 + :label: 6.92 \begin{array}{lr} c_{s,\min ,\, i} =\left(\frac{2.128{\rm \; }\left(\% sand\right)_{i} +{\rm 2.385\; }\left(\% clay\right)_{i} }{\left(\% sand\right)_{i} +\left(\% clay\right)_{i} } \right)\times 10^{6} &\qquad i=1,\ldots ,N_{levsoi} \\ @@ -764,18 +781,18 @@ where the heat capacity of mineral soil solids :math:`c_{s,\min,\, i}` (J m\ :su where :math:`c_{s,bedrock} =2\times 10^{6}` J m\ :sup:`-3` K\ :sup:`-1` is the heat capacity of bedrock and :math:`c_{s,om} =2.5\times 10^{6}` \ J m\ :sup:`-3` K\ :sup:`-1` (:ref:`Farouki 1981 `) is the heat capacity of organic matter. For glaciers and snow .. math:: - :label: 6.92 + :label: 6.93 c_{i} =\frac{w_{ice,\, i} }{\Delta z_{i} } C_{ice} +\frac{w_{liq,\, i} }{\Delta z_{i} } C_{liq} . For the special case when snow is present (:math:`W_{sno} >0`) but there are no explicit snow layers (:math:`snl=0`), the heat capacity of the top layer is a blend of ice and soil heat capacity .. math:: - :label: 6.93 + :label: 6.94 c_{1} =c_{1}^{*} +\frac{C_{ice} W_{sno} }{\Delta z_{1} } -where :math:`c_{1}^{*}` is calculated from :eq:`6.89` or :eq:`6.92`. +where :math:`c_{1}^{*}` is calculated from :eq:`6.90` or :eq:`6.93`. .. _Excess Ground Ice: @@ -785,14 +802,14 @@ Excess Ground Ice An optional parameterization of excess ground ice melt and respective subsidence based on (:ref:`Lee et al., (2014) `). Initial excess ground ice concentrations for soil columns are derived from (:ref:`Brown et al., (1997) `). When the excess ground ice is present in the soil column, soil depth for a given layer (:math:`z_{i}`) is adjusted by the amount of excess ice in the column: .. math:: - :label: 6.94 + :label: 6.95 z_{i}^{'}=\Sigma_{j=1}^{i} \ z_{j}^{'}+\frac{w_{exice,\, j}}{\rho_{ice} } where :math:`w_{exice,\,j}` is excess ground ice amount (kg m :sup:`-2`) in layer :math:`j` and :math:`\rho_{ice}` is the density of ice (kg m :sup:`-3`). After adjustment of layer depths have been made, all of the soil temperature equations (from :eq:`6.80` to :eq:`6.89`) are calculted based on the adjusted depths. Thermal properties are additionally adjusted (:eq:`6.8` and :eq:`6.8`) in the following way: .. math:: - :label: 6.95 + :label: 6.96 \begin{array}{lr} \theta_{sat}^{'} =\frac{\theta _{liq} }{\theta _{liq} +\theta _{ice} +\theta_{exice}}{\theta_{sat}} \\ @@ -803,7 +820,7 @@ where :math:`w_{exice,\,j}` is excess ground ice amount (kg m :sup:`-2`) in laye Soil subsidence at the timestep :math:`n+1` (:math:`z_{exice}^{n+1}`, m) is then calculated as: .. math:: - :label: 6.96 + :label: 6.97 z_{exice}^{n+1}=\Sigma_{i=1}^{N_{levgrnd}} \ z_{j}^{',\ ,n+1}-z_{j}^{',\ ,n } diff --git a/doc/source/tech_note/Surface_Albedos/CLM50_Tech_Note_Surface_Albedos.rst b/doc/source/tech_note/Surface_Albedos/CLM50_Tech_Note_Surface_Albedos.rst index f28d5583f1..e1dd5e0dd2 100644 --- a/doc/source/tech_note/Surface_Albedos/CLM50_Tech_Note_Surface_Albedos.rst +++ b/doc/source/tech_note/Surface_Albedos/CLM50_Tech_Note_Surface_Albedos.rst @@ -8,7 +8,7 @@ Surface Albedos Canopy Radiative Transfer ----------------------------- -Radiative transfer within vegetative canopies is calculated from the two-stream approximation of :ref:`Dickinson (1983) ` and :ref:`Sellers (1985) ` as described by :ref:`Bonan (1996) ` +Radiative transfer within vegetated canopies is calculated from the two-stream approximation of :ref:`Dickinson (1983) ` and :ref:`Sellers (1985) ` as described by :ref:`Bonan (1996) ` .. math:: :label: 3.1 @@ -82,14 +82,14 @@ For vegetation, :math:`\omega _{\Lambda }^{veg} =\alpha _{\Lambda } +\tau _{\Lam .. math:: :label: 3.11 - \alpha _{\Lambda } =\alpha _{\Lambda }^{leaf} w_{leaf} +\alpha _{\Lambda }^{stem} w_{stem} + \alpha _{\Lambda } =\max(\alpha _{\Lambda }^{leaf} w_{leaf} +\alpha _{\Lambda }^{stem} w_{stem},1e-6) -where :math:`w_{leaf} ={L\mathord{\left/ {\vphantom {L \left(L+S\right)}} \right.} \left(L+S\right)}` and :math:`w_{stem} ={S\mathord{\left/ {\vphantom {S \left(L+S\right)}} \right.} \left(L+S\right)}`. :math:`\tau _{\Lambda }` is a weighted combination of the leaf and stem transmittances (:math:`\tau _{\Lambda }^{leaf}, \tau _{\Lambda }^{stem}`) +where :math:`w_{leaf} =\max({L\mathord{\left/ {\vphantom {L \left(L+S\right)}} \right.} \left(L+S\right)},1e-6)` and :math:`w_{stem} =\max({S\mathord{\left/ {\vphantom {S \left(L+S\right)}} \right.} \left(L+S\right)},1e-6)`. :math:`\tau _{\Lambda }` is a weighted combination of the leaf and stem transmittances (:math:`\tau _{\Lambda }^{leaf}, \tau _{\Lambda }^{stem}`) .. math:: :label: 3.12 - \tau _{\Lambda } =\tau _{\Lambda }^{leaf} w_{leaf} +\tau _{\Lambda }^{stem} w_{stem} . + \tau _{\Lambda } =\max(\tau _{\Lambda }^{leaf} w_{leaf} +\tau _{\Lambda }^{stem} w_{stem},1e-6) . The upscatter for diffuse radiation is @@ -121,6 +121,8 @@ where the single scattering albedo is Note here the restriction on :math:`\mu \phi _{2} +G\left(\mu \right)`. We have seen cases where small values can cause unrealistic single scattering albedo associated with the log calculation, thereby eventually causing a negative soil albedo. +Note that the parameters :math:`h_{1}` –:math:`h_{10}`, :math:`\sigma`, :math:`h`, :math:`s_{1}`, and :math:`s_{2}` in the following equations [:eq:`3.17` - :eq:`3.30`] are defined in :eq:`3.31` - :eq:`3.57`. + The upward diffuse fluxes per unit incident direct beam and diffuse flux (i.e., the surface albedos) are .. math:: @@ -138,7 +140,7 @@ The downward diffuse fluxes per unit incident direct beam and diffuse radiation, .. math:: :label: 3.19 - I\, \downarrow _{\Lambda }^{\mu } =\frac{h_{4} }{\sigma } e^{-K\left(L+S\right)} +h_{5} s_{1} +\frac{h_{6} }{s_{1} } + I\, \downarrow _{\Lambda }^{\mu } =\frac{h_{4} }{\sigma } s_{2} +h_{5} s_{1} +\frac{h_{6} }{s_{1} } .. math:: :label: 3.20 @@ -150,7 +152,7 @@ With reference to :numref:`Figure Radiation Schematic`, the direct beam flux tra .. math:: :label: 3.21 - \vec{I}_{\Lambda }^{\mu } =1-I\, \uparrow _{\Lambda }^{\mu } -\left(1-\alpha _{g,\, \Lambda } \right)I\, \downarrow _{\Lambda }^{\mu } -\left(1-\alpha _{g,\, \Lambda }^{\mu } \right)e^{-K\left(L+S\right)} + \vec{I}_{\Lambda }^{\mu } =1-I\, \uparrow _{\Lambda }^{\mu } -\left(1-\alpha _{g,\, \Lambda } \right)I\, \downarrow _{\Lambda }^{\mu } -\left(1-\alpha _{g,\, \Lambda }^{\mu }\right) s_{2} .. math:: :label: 3.22 @@ -346,7 +348,7 @@ The parameters :math:`h_{1}` –:math:`h_{10}`, :math:`\sigma`, :math:`h`, :math h_{10} =\frac{-s_{1} \left(u_{2} -\bar{\mu }h\right)}{d_{2} } . -Plant functional type optical properties (:numref:`Table Plant functional type optical properties`) for trees and shrubs are from :ref:`Dorman and Sellers (1989) `. Leaf and stem optical properties (VIS and NIR reflectance and transmittance) were derived for grasslands and crops from full optical range spectra of measured optical properties (:ref:`Asner et al. 1998 `). Optical properties for intercepted snow (:numref:`Table Intercepted snow optical properties`) are from :ref:`Sellers et al. (1986) `. +Plant functional type optical properties (:numref:`Table Plant functional type optical properties`) for :math:`\chi _{L}`, :math:`\alpha _{vis}^{leaf}`, :math:`\alpha _{nir}^{leaf}`, :math:`\alpha _{vis}^{stem}`, :math:`\alpha _{nir}^{stem}`, :math:`\tau _{vis}^{leaf}`, and :math:`\tau _{nir}^{leaf}` are from :ref:`Majasalmi and Bright (2019) `. One of these parameter values was tuned based on a Perturbed Parameter Ensemble. Specifically, :math:`\chi _{L}` for BET Tropical was changed from 0.32 to 0.45. :math:`\tau _{vis}^{stem}` and :math:`\tau _{nir}^{stem}` for trees and shrubs are from :ref:`Dorman and Sellers (1989) `. :math:`\tau _{vis}^{stem}` and :math:`\tau _{nir}^{stem}` for grassland and crops were derived from full optical range spectra of measured optical properties (:ref:`Asner et al. 1998 `). Optical properties for intercepted snow (:numref:`Table Intercepted snow optical properties`) are from :ref:`Sellers et al. (1986) `. .. _Table Plant functional type optical properties: @@ -355,55 +357,55 @@ Plant functional type optical properties (:numref:`Table Plant functional type o +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ | Plant Functional Type | :math:`\chi _{L}` | :math:`\alpha _{vis}^{leaf}` | :math:`\alpha _{nir}^{leaf}` | :math:`\alpha _{vis}^{stem}` | :math:`\alpha _{nir}^{stem}` | :math:`\tau _{vis}^{leaf}` | :math:`\tau _{nir}^{leaf}` | :math:`\tau _{vis}^{stem}` | :math:`\tau _{nir}^{stem}` | +==================================+======================+=================================+=================================+=================================+=================================+===============================+===============================+===============================+===============================+ - | NET Temperate | 0.01 | 0.07 | 0.35 | 0.16 | 0.39 | 0.05 | 0.10 | 0.001 | 0.001 | + | NET Temperate | 0.01 | 0.09 | 0.41 | 0.12 | 0.36 | 0.04 | 0.32 | 0.001 | 0.001 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | NET Boreal | 0.01 | 0.07 | 0.35 | 0.16 | 0.39 | 0.05 | 0.10 | 0.001 | 0.001 | + | NET Boreal | 0.01 | 0.09 | 0.41 | 0.12 | 0.36 | 0.04 | 0.32 | 0.001 | 0.001 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | NDT Boreal | 0.01 | 0.07 | 0.35 | 0.16 | 0.39 | 0.05 | 0.10 | 0.001 | 0.001 | + | NDT Boreal | 0.01 | 0.08 | 0.39 | 0.12 | 0.36 | 0.06 | 0.42 | 0.001 | 0.001 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | BET Tropical | 0.10 | 0.10 | 0.45 | 0.16 | 0.39 | 0.05 | 0.25 | 0.001 | 0.001 | + | BET Tropical | 0.45 | 0.11 | 0.46 | 0.21 | 0.49 | 0.06 | 0.33 | 0.001 | 0.001 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | BET temperate | 0.10 | 0.10 | 0.45 | 0.16 | 0.39 | 0.05 | 0.25 | 0.001 | 0.001 | + | BET temperate | 0.32 | 0.11 | 0.46 | 0.21 | 0.49 | 0.06 | 0.33 | 0.001 | 0.001 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | BDT tropical | 0.01 | 0.10 | 0.45 | 0.16 | 0.39 | 0.05 | 0.25 | 0.001 | 0.001 | + | BDT tropical | 0.20 | 0.08 | 0.41 | 0.21 | 0.49 | 0.06 | 0.43 | 0.001 | 0.001 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | BDT temperate | 0.25 | 0.10 | 0.45 | 0.16 | 0.39 | 0.05 | 0.25 | 0.001 | 0.001 | + | BDT temperate | 0.59 | 0.08 | 0.41 | 0.21 | 0.49 | 0.06 | 0.43 | 0.001 | 0.001 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | BDT boreal | 0.25 | 0.10 | 0.45 | 0.16 | 0.39 | 0.05 | 0.25 | 0.001 | 0.001 | + | BDT boreal | 0.59 | 0.08 | 0.41 | 0.21 | 0.49 | 0.06 | 0.43 | 0.001 | 0.001 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | BES temperate | 0.01 | 0.07 | 0.35 | 0.16 | 0.39 | 0.05 | 0.10 | 0.001 | 0.001 | + | BES temperate | 0.32 | 0.11 | 0.46 | 0.21 | 0.49 | 0.06 | 0.33 | 0.001 | 0.001 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | BDS temperate | 0.25 | 0.10 | 0.45 | 0.16 | 0.39 | 0.05 | 0.25 | 0.001 | 0.001 | + | BDS temperate | 0.59 | 0.08 | 0.41 | 0.21 | 0.49 | 0.06 | 0.43 | 0.001 | 0.001 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | BDS boreal | 0.25 | 0.10 | 0.45 | 0.16 | 0.39 | 0.05 | 0.25 | 0.001 | 0.001 | + | BDS boreal | 0.59 | 0.08 | 0.41 | 0.21 | 0.49 | 0.06 | 0.43 | 0.001 | 0.001 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | C\ :sub:`3` arctic grass | -0.30 | 0.11 | 0.35 | 0.31 | 0.53 | 0.05 | 0.34 | 0.120 | 0.250 | + | C\ :sub:`3` arctic grass | -0.23 | 0.05 | 0.28 | 0.31 | 0.53 | 0.05 | 0.40 | 0.120 | 0.250 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | C\ :sub:`3` grass | -0.30 | 0.11 | 0.35 | 0.31 | 0.53 | 0.05 | 0.34 | 0.120 | 0.250 | + | C\ :sub:`3` grass | -0.23 | 0.05 | 0.28 | 0.31 | 0.53 | 0.05 | 0.40 | 0.120 | 0.250 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | C\ :sub:`4` grass | -0.30 | 0.11 | 0.35 | 0.31 | 0.53 | 0.05 | 0.34 | 0.120 | 0.250 | + | C\ :sub:`4` grass | -0.23 | 0.05 | 0.28 | 0.31 | 0.53 | 0.05 | 0.40 | 0.120 | 0.250 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | C\ :sub:`3` Crop | -0.30 | 0.11 | 0.35 | 0.31 | 0.53 | 0.05 | 0.34 | 0.120 | 0.250 | + | C\ :sub:`3` Crop | 0.30 | 0.08 | 0.42 | 0.31 | 0.53 | 0.05 | 0.40 | 0.120 | 0.250 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | Temp Corn | -0.50 | 0.11 | 0.35 | 0.31 | 0.53 | 0.05 | 0.34 | 0.120 | 0.250 | + | Temp Corn | 0.30 | 0.08 | 0.42 | 0.31 | 0.53 | 0.05 | 0.40 | 0.120 | 0.250 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | Spring Wheat | -0.50 | 0.11 | 0.35 | 0.31 | 0.53 | 0.05 | 0.34 | 0.120 | 0.250 | + | Spring Wheat | 0.30 | 0.08 | 0.42 | 0.31 | 0.53 | 0.05 | 0.40 | 0.120 | 0.250 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | Temp Soybean | -0.50 | 0.11 | 0.35 | 0.31 | 0.53 | 0.05 | 0.34 | 0.120 | 0.250 | + | Temp Soybean | 0.30 | 0.08 | 0.42 | 0.31 | 0.53 | 0.05 | 0.40 | 0.120 | 0.250 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | Cotton | -0.50 | 0.11 | 0.35 | 0.31 | 0.53 | 0.05 | 0.34 | 0.120 | 0.250 | + | Cotton | 0.30 | 0.08 | 0.42 | 0.31 | 0.53 | 0.05 | 0.40 | 0.120 | 0.250 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | Rice | -0.50 | 0.11 | 0.35 | 0.31 | 0.53 | 0.05 | 0.34 | 0.120 | 0.250 | + | Rice | 0.30 | 0.08 | 0.42 | 0.31 | 0.53 | 0.05 | 0.40 | 0.120 | 0.250 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | Sugarcane | -0.50 | 0.11 | 0.35 | 0.31 | 0.53 | 0.05 | 0.34 | 0.120 | 0.250 | + | Sugarcane | 0.30 | 0.08 | 0.42 | 0.31 | 0.53 | 0.05 | 0.40 | 0.120 | 0.250 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | Tropical Corn | -0.50 | 0.11 | 0.35 | 0.31 | 0.53 | 0.05 | 0.34 | 0.120 | 0.250 | + | Tropical Corn | 0.30 | 0.08 | 0.42 | 0.31 | 0.53 | 0.05 | 0.40 | 0.120 | 0.250 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | Tropical Soybean | -0.50 | 0.11 | 0.35 | 0.31 | 0.53 | 0.05 | 0.34 | 0.120 | 0.250 | + | Tropical Soybean | 0.30 | 0.08 | 0.42 | 0.31 | 0.53 | 0.05 | 0.40 | 0.120 | 0.250 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | Miscanthus | -0.50 | 0.11 | 0.35 | 0.31 | 0.53 | 0.05 | 0.34 | 0.120 | 0.250 | + | Miscanthus | 0.30 | 0.08 | 0.42 | 0.31 | 0.53 | 0.05 | 0.40 | 0.120 | 0.250 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ - | Switchgrass | -0.50 | 0.11 | 0.35 | 0.31 | 0.53 | 0.05 | 0.34 | 0.120 | 0.250 | + | Switchgrass | 0.30 | 0.08 | 0.42 | 0.31 | 0.53 | 0.05 | 0.40 | 0.120 | 0.250 | +----------------------------------+----------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+ .. _Table Intercepted snow optical properties: @@ -439,24 +441,38 @@ The overall direct beam :math:`\alpha _{g,\, \Lambda }^{\mu }` and diffuse :math where :math:`f_{sno}` is the fraction of the ground covered with snow (section :numref:`Snow Covered Area Fraction`). -:math:`\alpha _{soi,\, \Lambda }^{\mu }` and :math:`\alpha _{soi,\, \Lambda }` vary with glacier, lake, and soil surfaces. Glacier albedos are from :ref:`Paterson (1994) ` +:math:`\alpha _{soi,\, \Lambda }^{\mu }` and :math:`\alpha _{soi,\, \Lambda }` vary with glacier, lake, and soil surfaces. Glacier albedos were originally from :ref:`Paterson (1994) ` but were adjusted to the following values agreed upon by the Land Ice Working Group leadership team + +.. math:: \alpha _{soi,\, vis}^{\mu } =\alpha _{soi,\, vis} =0.5 -.. math:: \alpha _{soi,\, vis}^{\mu } =\alpha _{soi,\, vis} =0.6 +.. math:: \alpha _{soi,\, nir}^{\mu } =\alpha _{soi,\, nir} =0.3. -.. math:: \alpha _{soi,\, nir}^{\mu } =\alpha _{soi,\, nir} =0.4. +Note that these are read in from the ``clm_inparm`` namelist group (variable ``albice``). -Unfrozen lake albedos depend on the cosine of the solar zenith angle :math:`\mu` +Unfrozen lake direct albedos depend on the cosine of the solar zenith angle :math:`\mu` .. math:: :label: 3.60 - \alpha _{soi,\, \Lambda }^{\mu } =\alpha _{soi,\, \Lambda } =0.05\left(\mu +0.15\right)^{-1} . + \alpha _{soi,\, \Lambda }^{\mu } =0.05\left(\max (0.001,\mu +0.15\right))^{-1} . + +For diffuse radiation the expression in equation :eq:`3.60` is integrated over the full sky to yield :math:`\alpha _{soi,\, \Lambda } =0.10`. + +For frozen lakes without resolved snow layers (:math:`snl=0`), the albedo at cold temperatures :math:`a_0` is 0.60 for visible and 0.40 for near infrared radiation. As the temperature at the ice surface, :math:`{T}_{g}`, approaches freezing [ :math:`{T}_{f}` (K) (:numref:`Table Physical Constants`)], the albedo is relaxed towards 0.10 based on :ref:`Mironov et al. (2010)`: + +.. math:: + :label: AlbFrozenLakeSnl0Dir + + \alpha _{soi,\, \Lambda }^{\mu }=a_{0} \left(1-x\right)+\max(0.10,\alpha _{soi,\, \Lambda }^{\mu })x,x=\exp \left(-95\frac{T_{f} -T_{g} }{T_{f} } \right) + +.. math:: + :label: AlbFrozenLakeSnl0Dif -Frozen lake albedos are from NCAR LSM (:ref:`Bonan 1996 `) + \alpha _{soi,\, \Lambda }=a_{0} \left(1-x\right)+0.10x,x=\exp \left(-95\frac{T_{f} -T_{g} }{T_{f} } \right) -.. math:: \alpha _{soi,\, vis}^{\mu } =\alpha _{soi,\, vis} =0.60 +where :math:`\alpha _{soi,\, \Lambda }^{\mu }` is calculated from :eq:`3.60` for direct radiation. -.. math:: \alpha _{soi,\, nir}^{\mu } =\alpha _{soi,\, nir} =0.40. +For frozen lakes with resolved snow layers, the reflectance of the ice surface is fixed at :math:`a_0`, and the snow reflectance is calculated as over non-vegetated surfaces (Chapter :numref:`rst_Surface Albedos`). These two reflectances are combined to obtain the snow-fraction-weighted albedo as in over non-vegetated surfaces (Chapter :numref:`rst_Surface Albedos`). As in NCAR LSM (:ref:`Bonan 1996 `), soil albedos vary with color class @@ -467,7 +483,7 @@ As in NCAR LSM (:ref:`Bonan 1996 `), soil albedos vary with color cla where :math:`\Delta` depends on the volumetric water content of the first soil layer :math:`\theta _{1}` (section :numref:`Soil Water`) as :math:`\Delta =0.11-0.40\theta _{1} >0`, and :math:`\alpha _{sat,\, \Lambda }` and :math:`\alpha _{dry,\, \Lambda }` are albedos for saturated and dry soil color classes (:numref:`Table Dry and saturated soil albedos`). -CLM soil colors are prescribed so that they best reproduce observed MODIS local solar noon surface albedo values at the CLM grid cell following the methods of :ref:`Lawrence and Chase (2007) `. The soil colors are fitted over the range of 20 soil classes shown in :numref:`Table Dry and saturated soil albedos` and compared to the MODIS monthly local solar noon all-sky surface albedo as described in :ref:`Strahler et al. (1999) ` and :ref:`Schaaf et al. (2002) `. The CLM two-stream radiation model was used to calculate the model equivalent surface albedo using climatological monthly soil moisture along with the vegetation parameters of PFT fraction, LAI, and SAI. The soil color that produced the closest all-sky albedo in the two-stream radiation model was selected as the best fit for the month. The fitted monthly soil colors were averaged over all snow-free months to specify a representative soil color for the grid cell. In cases where there was no snow-free surface albedo for the year, the soil color derived from snow-affected albedo was used to give a representative soil color that included the effects of the minimum permanent snow cover. +Albedos associated with CLM soil colors were updated for CLM4 using the procedure described below (:ref:`Lawrence et al. (2011) `) but have not been updated since then. CLM soil colors are prescribed so that they best reproduce observed MODIS local solar noon surface albedo values at the CLM grid cell following the methods of :ref:`Lawrence and Chase (2007) `. The soil colors are fitted over the range of 20 soil classes shown in :numref:`Table Dry and saturated soil albedos` and compared to the MODIS monthly local solar noon all-sky surface albedo as described in :ref:`Strahler et al. (1999) ` and :ref:`Schaaf et al. (2002) `. The CLM two-stream radiation model was used to calculate the model equivalent surface albedo using climatological monthly soil moisture along with the vegetation parameters of PFT fraction, LAI, and SAI. The soil color that produced the closest all-sky albedo in the two-stream radiation model was selected as the best fit for the month. The fitted monthly soil colors were averaged over all snow-free months to specify a representative soil color for the grid cell. In cases where there was no snow-free surface albedo for the year, the soil color derived from snow-affected albedo was used to give a representative soil color that included the effects of the minimum permanent snow cover. .. _Table Dry and saturated soil albedos: @@ -767,9 +783,9 @@ The obliquity of the Earth :math:`\varepsilon` (degrees) is .. math:: :label: 3.79 - \varepsilon =\varepsilon *+\sum _{i=1}^{i=47}A_{i} \cos \left(f_{i} t+\delta _{i} \right) + \varepsilon =\varepsilon^{*}+\sum _{i=1}^{i=47}A_{i} \cos \left(f_{i} t+\delta _{i} \right) -where :math:`\varepsilon *` is a constant of integration (:numref:`Table Orbital parameters`), :math:`A_{i}`, :math:`f_{i}`, and :math:`\delta _{i}` are amplitude, mean rate, and phase terms in the cosine series expansion (:ref:`Berger (1978a,b) `, and :math:`t=t_{0} -1950` where :math:`t_{0}` is the year. The series expansion terms are not shown here but can be found in the source code file shr\_orb\_mod.F90. +where :math:`\varepsilon^{*}` is a constant of integration (:numref:`Table Orbital parameters`), :math:`A_{i}`, :math:`f_{i}`, and :math:`\delta _{i}` are amplitude, mean rate, and phase terms in the cosine series expansion (:ref:`Berger (1978a,b) `, and :math:`t=t_{0} -1950` where :math:`t_{0}` is the year. The series expansion terms are not shown here but can be found in the source code file ``shr_orb_mod.F90``. The true longitude of the Earth :math:`\lambda` (radians) is counted counterclockwise from the vernal equinox (:math:`\lambda =0` at the vernal equinox) @@ -806,7 +822,7 @@ where \begin{array}{l} {e^{\cos } =\sum _{j=1}^{19}M_{j} \cos \left(g_{j} t+B_{j} \right) ,} \\ {e^{\sin } =\sum _{j=1}^{19}M_{j} \sin \left(g_{j} t+B_{j} \right) } \end{array} -are the cosine and sine series expansions for :math:`e`, and :math:`M_{j}`, :math:`g_{j}`, and :math:`B_{j}` are amplitude, mean rate, and phase terms in the series expansions (:ref:`Berger (1978a,b) `). The longitude of the perihelion relative to the moving vernal equinox :math:`\tilde{\omega }` (degrees) is +are the cosine and sine series expansions for :math:`e`, and :math:`M_{j}`, :math:`g_{j}`, and :math:`B_{j}` are amplitude, mean rate, and phase terms in the series expansions (:ref:`Berger (1978a,b) `) (series expansion terms not shown but can be found in the source code file ``shr_orb_mod.F90``). The longitude of the perihelion relative to the moving vernal equinox :math:`\tilde{\omega }` (degrees) is .. math:: :label: 3.85 @@ -820,7 +836,7 @@ where :math:`\Pi` is the longitude of the perihelion measured from the reference \psi =\frac{\tilde{\psi }t}{3600} +\zeta +\sum _{i=1}^{78}F_{i} \sin \left(f_{i} ^{{'} } t+\delta _{i} ^{{'} } \right) -where :math:`\tilde{\psi }` (arcseconds) and :math:`\zeta` (degrees) are constants (:numref:`Table Orbital parameters`), and :math:`F_{i}`, :math:`f_{i} ^{{'} }`, and :math:`\delta _{i} ^{{'} }` are amplitude, mean rate, and phase terms in the sine series expansion (:ref:`Berger (1978a,b) `)). The longitude of the perihelion :math:`\Pi` (radians) depends on the sine and cosine series expansions for the eccentricity :math:`e`\ as follows: +where :math:`\tilde{\psi }` (arcseconds) and :math:`\zeta` (degrees) are constants (:numref:`Table Orbital parameters`), and :math:`F_{i}`, :math:`f_{i} ^{{'} }`, and :math:`\delta _{i} ^{{'} }` are amplitude, mean rate, and phase terms in the sine series expansion (:ref:`Berger (1978a,b) `) (series expansion terms not shown but can be found in the source code file ``shr_orb_mod.F90``). The longitude of the perihelion :math:`\Pi` (radians) depends on the sine and cosine series expansions for the eccentricity :math:`e` as follows: .. math:: :label: 3.87 @@ -834,7 +850,7 @@ where :math:`\tilde{\psi }` (arcseconds) and :math:`\zeta` (degrees) are constan \tan ^{-1} \left[\frac{e^{\sin } }{e^{\cos } } \right] & \qquad {\rm for\; }e^{\cos } >{\rm 1}\times {\rm 10}^{{\rm -8}} {\rm \; and\; }e^{\sin } \ge 0 \end{array}\right\}. -The numerical solution for the longitude of the perihelion :math:`\tilde{\omega }` is constrained to be between 0 and 360 degrees (measured from the autumn equinox). A constant 180 degrees is then added to :math:`\tilde{\omega }` because the Sun is considered as revolving around the Earth (geocentric coordinate system) (:ref:`Berger et al. 1993 `)). +The numerical solution for the longitude of the perihelion :math:`\tilde{\omega }` is constrained to be between 0 and 360 degrees (measured from the autumn equinox). A constant 180 degrees is then added to :math:`\tilde{\omega }` because the Sun is considered as revolving around the Earth (geocentric coordinate system) (:ref:`Berger et al. 1993 `). .. _Table Orbital parameters: @@ -843,7 +859,7 @@ The numerical solution for the longitude of the perihelion :math:`\tilde{\omega +--------------------------------------+-------------+ | Parameter | | +======================================+=============+ - | :math:`\varepsilon *` | 23.320556 | + | :math:`\varepsilon^{*}` | 23.320556 | +--------------------------------------+-------------+ | :math:`\tilde{\psi }` (arcseconds) | 50.439273 | +--------------------------------------+-------------+ diff --git a/doc/source/tech_note/Urban/CLM50_Tech_Note_Urban.rst b/doc/source/tech_note/Urban/CLM50_Tech_Note_Urban.rst index 8777c7be74..695281556f 100644 --- a/doc/source/tech_note/Urban/CLM50_Tech_Note_Urban.rst +++ b/doc/source/tech_note/Urban/CLM50_Tech_Note_Urban.rst @@ -3,23 +3,35 @@ Urban Model (CLMU) ====================== -At the global scale, and at the coarse spatial resolution of current climate models, urbanization has negligible impact on climate. However, the urban parameterization (CLMU; :ref:`Oleson et al. (2008b) `; :ref:`Oleson et al. (2008c) `) allows simulation of the urban environment within a climate model, and particularly the temperature where people live. As such, the urban model allows scientific study of how climate change affects the urban heat island and possible urban planning and design strategies to mitigate warming (e.g., white roofs). +The urban parameterization (CLMU; :ref:`Oleson et al. (2008b) `; :ref:`Oleson et al. (2008c) `; :ref:`Oleson and Feddema (2020) `) allows simulation of the urban environment within a climate model, and particularly the temperature/humidity where people live. As such, the urban model allows scientific study of how climate change affects the urban heat island and possible urban planning and design strategies to mitigate warming (e.g., white roofs). Urban areas in CLM are represented by up to three urban landunits per gridcell according to density class. The urban landunit is based on the "urban canyon" concept of :ref:`Oke (1987) ` in which the canyon geometry is described by building height (:math:`H`) and street width (:math:`W`) (:numref:`Figure schematic representation of the urban landunit`). The canyon system consists of roofs, walls, and canyon floor. Walls are further divided into shaded and sunlit components. The canyon floor is divided into pervious (e.g., to represent residential lawns, parks) and impervious (e.g., to represent roads, parking lots, sidewalks) fractions. Vegetation is not explicitly modeled for the pervious fraction; instead evaporation is parameterized by a simplified bulk scheme. -Each of the five urban surfaces is treated as a column within the landunit (:numref:`Figure schematic representation of the urban landunit`). Radiation parameterizations account for trapping of solar and longwave radiation inside the canyon. Momentum fluxes are determined for the urban landunit using a roughness length and displacement height appropriate for the urban canyon and stability formulations from CLM. A one-dimensional heat conduction equation is solved numerically for a multiple-layer (:math:`N_{levurb} =10`) column to determine conduction fluxes into and out of canyon surfaces. - -A new building energy model has been developed for CLM5.0. It accounts for the conduction of heat through interior surfaces (roof, sunlit and shaded walls, and floors), convection (sensible heat exchange) between interior surfaces and building air, longwave radiation exchange between interior surfaces, and ventilation (natural infiltration and exfiltration). Idealized HAC systems are assumed where the system capacity is infinite and the system supplies the amount of energy needed to keep the indoor air temperature (:math:`T_{iB}`) within maximum and minimum emperatures (:math:`T_{iB,\, \max },\, T_{iB,\, \min }` ), thus explicitly resolving space heating and air conditioning fluxes. Anthropogenic sources of waste heat (:math:`Q_{H,\, waste}` ) from HAC that account for inefficiencies in the heating and air conditioning equipment and from energy lost in the conversion of primary energy sources to end use energy are derived from :ref:`Sivak (2013) `. These sources of waste heat are incorporated as modifications to the canyon energy budget. +Each of the five urban surfaces is treated as a column within the landunit (:numref:`Figure schematic representation of the urban landunit`). Radiation parameterizations account for trapping of solar and longwave radiation inside the canyon. Momentum fluxes are determined for the urban landunit using a roughness length and displacement height appropriate for the urban canyon and stability formulations adopted from CLM. A one-dimensional heat conduction equation is solved numerically for a multiple-layer (:math:`N_{levurb} =10`) column to determine conduction fluxes into and out of canyon surfaces. Turbulent [sensible heat (:math:`Q_{H,\, u}` ) and latent heat (:math:`Q_{E,\, u}` )] and storage (:math:`Q_{S,\, u}` ) heat fluxes and surface (:math:`T_{u,\, s}` ) and internal (:math:`T_{u,\, i=1,\, N_{levgrnd} }` ) temperatures are determined for each urban surface :math:`u`. Hydrology on the roof and canyon floor is simulated and walls are hydrologically inactive. A snowpack can form on the active surfaces. A certain amount of liquid water is allowed to pond on these surfaces which supports evaporation. Water in excess of the maximum ponding depth runs off (:math:`R_{roof},\, R_{imprvrd},\, R_{prvrd}` ). The heat and moisture fluxes from each surface interact with each other through a bulk air mass that represents air in the urban canopy layer for which specific humidity (:math:`q_{ac}` ) and temperature (:math:`T_{ac}` ) are prognosed (:numref:`Figure schematic of urban and atmospheric model coupling`). The air temperature can be compared with that from surrounding vegetated/soil (rural) surfaces in the model to ascertain heat island characteristics. As with other landunits, the CLMU is forced either with output from a host atmospheric model (e.g., the Community Atmosphere Model (CAM)) or observed forcing (e.g., reanalysis or field observations). The urban model produces sensible, latent heat, and momentum fluxes, emitted longwave, and reflected solar radiation, which are area-averaged with fluxes from non-urban "landunits" (e.g., vegetation, lakes) to supply grid cell averaged fluxes to the atmospheric model. -Present day global urban extent and urban properties were developed by :ref:`Jackson et al. (2010) `. Urban extent, defined for four classes [tall building district (TBD), and high, medium, and low density (HD, MD, LD)], was derived from LandScan 2004, a population density dataset derived from census data, nighttime lights satellite observations, road proximity, and slope (:ref:`Dobson et al. 2000 `). The urban extent data for TBD, HD, and MD classes are aggregated from the original 1 km resolution to both a 0.05° by 0.05° global grid for high-resolution studies or a 0.5° by 0.5° grid. For the current implementation, the LD class is not used because it is highly rural and better modeled as a vegetated/soil surface. Although the TBD, HD, and MD classes are represented as individual urban landunits, urban model history output is currently a weighted average of the output for individual classes. +The version of the urban model that was first released as a component of CLM4.0 is separately described in the urban technical note (:ref:`Oleson et al. (2010b) `). The main changes in the urban model from CLM4.0 to CLM4.5 were 1) an expansion of the single urban landunit to up to three landunits per grid cell stratified by urban density types, 2) the number of urban layers for roofs and walls was no longer constrained to be equal to the number of ground layers, 3) space heating and air conditioning (AC) wasteheat factors were set to zero by default so that the user could customize these factors for their own application, 4) the elevation threshold used to eliminate urban areas in the surface dataset creation routines was increased from 2200 meters to 2600 meters, 5) hydrologic and thermal calculations for the pervious road followed CLM4.5 parameterizations. + +The main changes in the urban model from CLM4.5 to CLM5.0 were 1) a more sophisticated and realistic building space heating and AC submodel (described below) that prognoses interior building air temperature and includes more realistic space heating and AC wasteheat factors (see above), 2) the maximum building temperature (which determines AC demand) was now read in from a file specified from the ``urbantv_streams`` namelist group instead of the surface dataset which allowed for dynamic control of this input variable. The maximum building temperatures that were defined in :ref:`Jackson et al. (2010) ` are only implemented beginning in year 1950 (thus AC is off in prior years) and AC is turned off in year 2100 (because the buildings are not suitable for AC in some extreme global warming scenarios), 3) the inclusion of an optional updated urban properties dataset and new scenario tool. These features are described in more detail in :ref:`Oleson and Feddema (2020) `. In addition, a module of heat stress indices calculated online in the model that can be used to assess human thermal comfort for rural and urban areas was added. This last development is described and evaluated by :ref:`Buzan et al. (2015) `. + +The main changes in the urban model from CLM5.0 to CLM6.0 are (see below) 1) an explicit AC scheme for the building energy model (BEM) that better captures AC energy flux, 2) the addition of transient urban capability (annual changes in urban fraction over the course of a simulation), 3) a slightly modified set of urban properties that were an option in CLM5.0 and are now used by default, 4) new datasets of urban extent (urban fraction of the grid cell) for 1700-2023 (2024- data expected soon also) based on CMIP7 LUH3 data. + +The building energy model introduced in :ref:`Oleson and Feddema (2020) ` accounts for the conduction of heat through interior surfaces (roof, sunlit and shaded walls, and floors), convection (sensible heat exchange) between interior surfaces and building air, longwave radiation exchange between interior surfaces, and ventilation (natural infiltration and exfiltration). Idealized HAC systems are assumed where the system capacity is infinite and the system supplies the amount of energy needed to keep the indoor air temperature (:math:`T_{iB}`) within maximum and minimum emperatures (:math:`T_{iB,\, \max },\, T_{iB,\, \min }` ), thus explicitly resolving space heating and AC fluxes. Anthropogenic sources of waste heat (:math:`Q_{H,\, waste}` ) from HAC that account for inefficiencies in the heating and AC equipment and from energy lost in the conversion of primary energy sources to end use energy are derived from :ref:`Sivak (2013) `. These sources of waste heat are incorporated as modifications to the canyon energy budget. + +An explicit AC adoption parameterization for the BEM was developed for CLM6.0 (:ref:`Li et al. (2024) `). An AC adoption parameter is introduced (:math:`p_{AC}` ). The AC flux is first calculated under saturated AC adoption (i.e., :math:`p_{AC}=100%` ). The actual AC flux removed from the indoor air is then scaled based on :math:`p_{AC}` and the waste heat added to the urban canyon due to AC energy use is also scaled by :math:`p_{AC}`. A global, spatially explicit dataset for the AC adoption rate was developed at country- and sub-country-level from sources such as the International Energy Agency (IEA), national surveys, scientific literature, and others. For use with CLM, the AC adoption parameter was regridded to 0.9° latitude by 1.25° longitude and is read in for each of the three urban density classes using the file specified by the ``urbantv_streams`` namelist group (variables ``p_ac_MD``, ``p_ac_HD``, ``p_ac_TBD``). The maximum building interior temperature is also specified by the file in the ``urbantv_streams`` namelist group and is now considered to be the AC proxy setpoint in the parameterization and is set to 300K for all urban density classes (variables ``tbuildmax_MD``', ``tbuildmax_HD``, ``tbuildmax_TBD``). The explicit AC adoption parameterization in combination with the AC adoption rate dataset significantly improve CLM's performance in model building AC energy flux, both in magnitude and spatial variability (:ref:`Li et al. (2024) `). + +Global urban properties were originally developed by :ref:`Jackson et al. (2010) `. For each of 33 distinct regions across the globe and four urban density classes [tall building district (TBD), and high, medium, and low density (HD, MD, LD)], thermal (e.g., heat capacity and thermal conductivity), radiative (e.g., albedo and emissivity) and morphological (e.g., height to width ratio, roof fraction, average building height, and pervious fraction of the canyon floor) properties, are provided for each of the density classes. Building interior minimum and maximum temperatures are prescribed based on climate and socioeconomic considerations. As described in :ref:`Oleson and Feddema (2020) ` the urban properties dataset in :ref:`Jackson et al. (2010) ` was modified with respect to wall and roof thermal properties to correct for biases in heat transfer due to layer and building type averaging. Further changes to the dataset reflect the need for scenario development, thus allowing for the creation of hypothetical wall types, and the easier interchange of wall facets. This slightly modified dataset was an option in CLM5.0. + +The "raw" urban properties dataset used by the model is created from the urban properties tool which is available as part of the Toolbox for Human-Earth System Integration & Scaling (THESIS) tool set (https://github.com/NCAR/THESISUrbanPropertiesTool; :ref:`Oleson and Feddema (2020) `). The driver script (``urban_prop.csh``) specifies three input csv files (by default, ``mat_prop.csv``, ``lam_spec.csv``, and ``city_spec.csv``; (:numref:`Figure schematic of THESIS urban properties tool`)) that describe the morphological, radiative, and thermal properties of urban areas, plus the minimum building interior temperature, and generates a global dataset at 0.05° latitude by longitude in NetCDF format. This dataset, when combined with the urban extent data described below, is then ingested into the ``mksurfdata_esmf`` tool to create surface datasets at the desired spatial and temporal resolutions. + +Urban extent (circa-year 2000), defined for the four density classes, was originally provided by :ref:`Jackson et al. (2010) ` and derived from LandScan 2004, a population density dataset derived from census data, nighttime lights satellite observations, road proximity, and slope (:ref:`Dobson et al. 2000 `). Note that the LD class is not used in CLM because it is highly rural (dominated by vegetation) and better modeled as a vegetated/soil surface. This dataset was used for model versions CLM5.0 and earlier. A more up to date urban extent dataset was derived for use with CLM6.0 from a 0.05° urban landcover projection dataset (:ref:`Gao and O'Neill (2020) `) as described in :ref:`Fang et al. (2026) ` (code and auxiliary datasets available at https://figshare.com/s/4a890655b34498c1d082). The :ref:`Gao and O'Neill (2020) ` dataset provides global urban land cover for 2000-2100 in decadal intervals for a historical baseline (year 2000) and five CMIP6 ScenarioMIP Shared Socioeconomic Pathways (SSPs) at 0.05° resolution (2010-2100). Briefly, because the :ref:`Gao and O'Neill (2020) ` dataset only provides the data as a single urban class, the urban area in each grid cell is partitioned according to the ratio of the density types in that grid cell in the :ref:`Jackson et al. (2010) ` dataset. The decadal urban data are then linearly interpolated to generate annual urban data from 2015-2100. To provide data prior to 2015, the average urban fraction of the five SSP scenarios was calculated in 2010 and 2015. Then annual urban fraction from 2000 to 2014 were obtained by interpolating betwen urban fraction in the historical baseline year 2000, and average SSP years 2010 and 2015. Finally, due to a lack of historical data, data for 1850-1999 were simply copied from year 2000 data. The yearly :ref:`Gao and O'Neill (2020) ` historical and SSP datasets are available for an intermediate model version (CTSM5.3) at 0.05° resolution. -For each of 33 distinct regions across the globe, thermal (e.g., heat capacity and thermal conductivity), radiative (e.g., albedo and emissivity) and morphological (e.g., height to width ratio, roof fraction, average building height, and pervious fraction of the canyon floor) properties are provided for each of the density classes. Building interior minimum and maximum temperatures are prescribed based on climate and socioeconomic considerations. The surface dataset creation routines (see CLM5.0 User's Guide) aggregate the data to the desired resolution. +However, it was deemed desirable to create a dataset consistent with CMIP7 landcover change protocols. CMIP7 provides urban fraction at 0.25° resolution for 1700-2023. Again, since the dataset only provides the data as a single urban class, the urban area in each grid cell is partitioned according to the ratio of the density types in that grid cell in a year 2023 0.25° resolution version of the :ref:`Gao and O'Neill (2020) ` dataset created as described above. An exception is that the TBD class is not allowed before year 1900 as skyscrapers, etc. had not yet begun to be built. In that case, the urban fraction was split proportionally between the HD and MD classes. Datasets for future scenarios, i.e., 2024-, will be created similarly when CMIP7 data is available. -An optional urban properties dataset, including a tool that allows for generating future urban development scenarios is also available (:ref:`Oleson and Feddema (2018) `). This will become the default dataset in future model versions. As described in :ref:`Oleson and Feddema (2018) ` the urban properties dataset in :ref:`Jackson et al. (2010) ` was modified with respect to wall and roof thermal properties to correct for biases in heat transfer due to layer and building type averaging. Further changes to the dataset reflect the need for scenario development, thus allowing for the creation of hypothetical wall types, and the easier interchange of wall facets. The new urban properties tool is available as part of the Toolbox for Human-Earth System Integration & Scaling (THESIS) tool set (http://www.cgd.ucar.edu/iam/projects/thesis/thesis-urbanproperties-tool.html; :ref:`Feddema and Kauffman (2016) `). The driver script (urban_prop.csh) specifies three input csv files (by default, mat_prop.csv, lam_spec.csv, and city_spec.csv; (:numref:`Figure schematic of THESIS urban properties tool`)) that describe the morphological, radiative, and thermal properties of urban areas, and generates a global dataset at 0.05° latitude by longitude in NetCDF format (urban_properties_data.05deg.nc). A standalone NCL routine (gen_data_clm.ncl) can be run separately after the mksurfdata_esmf tool creates the CLM surface dataset. This creates a supplementary streams file of setpoints for the maximum interior building temperature at yearly time resolution. +To accomodate the transient urban datasets developed above, dynamic urban capability was implemented into the model as described in :ref:`Fang et al. (2026) ` in a manner similar to the implementation of other land cover transient datasets including ensuring conservation for total gridcell water and energy content. See Chapter :numref:`rst_Transient Landcover Change` for further details. .. Figure 12.1. Schematic representation of the urban land unit @@ -45,6 +57,4 @@ An optional urban properties dataset, including a tool that allows for generatin Schematic of THESIS urban properties tool. Executable scripts are in orange, input files are blue, and output files are green. Items within the black box outline are either read in as input, executed, or output by the driver script (urban_prop.csh). -The urban model that was first released as a component of CLM4.0 is separately described in the urban technical note (:ref:`Oleson et al. (2010b) `). The main changes in the urban model from CLM4.0 to CLM4.5 were 1) an expansion of the single urban landunit to up to three landunits per grid cell stratified by urban density types, 2) the number of urban layers for roofs and walls was no longer constrained to be equal to the number of ground layers, 3) space heating and air conditioning wasteheat factors were set to zero by default so that the user could customize these factors for their own application, 4) the elevation threshold used to eliminate urban areas in the surface dataset creation routines was increased from 2200 meters to 2600 meters, 5) hydrologic and thermal calculations for the pervious road followed CLM4.5 parameterizations. -The main changes in the urban model from CLM4.5 to CLM5.0 are 1) a more sophisticated and realistic building space heating and air conditioning submodel that prognoses interior building air temperature and includes more realistic space heating and air conditioning wasteheat factors (see above), 2) the maximum building temperature (which determines air conditioning demand) is now read in from a namelist-defined file which allows for dynamic control of this input variable. The maximum building temperatures that are defined in :ref:`Jackson et al. (2010) ` are implemented in year 1950 (thus air conditioning is off in prior years) and air conditioning is turned off in year 2100 (because the buildings are not suitable for air conditioning in some extreme global warming scenarios), 3) an optional updated urban properties dataset and new scenario tool. These features are described in more detail in :ref:`Oleson and Feddema (2018) `. In addition, a module of heat stress indices calculated online in the model that can be used to assess human thermal comfort for rural and urban areas has been added. This last development is described and evaluated by :ref:`Buzan et al. (2015) `. diff --git a/doc/source/tech_note/Vegetation_Phenology_Turnover/CLM50_Tech_Note_Vegetation_Phenology_Turnover.rst b/doc/source/tech_note/Vegetation_Phenology_Turnover/CLM50_Tech_Note_Vegetation_Phenology_Turnover.rst index 5bb4dc9e40..2178baa32f 100644 --- a/doc/source/tech_note/Vegetation_Phenology_Turnover/CLM50_Tech_Note_Vegetation_Phenology_Turnover.rst +++ b/doc/source/tech_note/Vegetation_Phenology_Turnover/CLM50_Tech_Note_Vegetation_Phenology_Turnover.rst @@ -18,89 +18,89 @@ Fluxes of carbon and nitrogen from storage pools and into displayed tissue pools Example of annual phenology cycle for seasonal deciduous. -14.1.1 Onset Periods +Onset Periods ^^^^^^^^^^^^^^^^^^^^ -The deciduous phenology algorithms specify the occurrence of onset growth periods (Figure 14.1). Carbon fluxes from the transfer pools into displayed growth are calculated during these periods as: +The deciduous phenology algorithms specify the occurrence of onset growth periods (:numref:`Figure annual phenology cycle`). Carbon fluxes from the transfer pools into displayed growth are calculated during these periods as: .. math:: - :label: 20.1) + :label: C_transfer_leaf CF_{leaf\_ xfer,leaf} =r_{xfer\_ on} CS_{leaf\_ xfer} .. math:: - :label: 20.2) + :label: C_transfer_froot CF_{froot\_ xfer,froot} =r_{xfer\_ on} CS_{froot\_ xfer} .. math:: - :label: 20.3) + :label: C_transfer_livestem CF_{livestem\_ xfer,livestem} =r_{xfer\_ on} CS_{livestem\_ xfer} .. math:: - :label: 20.4) + :label: C_transfer_deadstem CF_{deadstem\_ xfer,deadstem} =r_{xfer\_ on} CS_{deadstem\_ xfer} .. math:: - :label: 20.5) + :label: C_transfer_livecroot CF_{livecroot\_ xfer,livecroot} =r_{xfer\_ on} CS_{livecroot\_ xfer} .. math:: - :label: 20.6) + :label: C_transfer_deadcroot CF_{deadcroot\_ xfer,deadcroot} =r_{xfer\_ on} CS_{deadcroot\_ xfer} , with corresponding nitrogen fluxes: .. math:: - :label: 20.7) + :label: N_transfer_leaf NF_{leaf\_ xfer,leaf} =r_{xfer\_ on} NS_{leaf\_ xfer} .. math:: - :label: 20.8) + :label: N_transfer_froot NF_{froot\_ xfer,froot} =r_{xfer\_ on} NS_{froot\_ xfer} .. math:: - :label: 20.9) + :label: N_transfer_livestem NF_{livestem\_ xfer,livestem} =r_{xfer\_ on} NS_{livestem\_ xfer} .. math:: - :label: 20.10) + :label: N_transfer_deadstem NF_{deadstem\_ xfer,deadstem} =r_{xfer\_ on} NS_{deadstem\_ xfer} .. math:: - :label: 20.11) + :label: N_transfer_livecroot NF_{livecroot\_ xfer,livecroot} =r_{xfer\_ on} NS_{livecroot\_ xfer} .. math:: - :label: 20.12) + :label: N_transfer_deadcroot NF_{deadcroot\_ xfer,deadcroot} =r_{xfer\_ on} NS_{deadcroot\_ xfer} , where CF is the carbon flux, CS is stored carbon, NF is the nitrogen flux, NS is stored nitrogen, :math:`{r}_{xfer\_on}` (s\ :sup:`-1`) is a time-varying rate coefficient controlling flux out of the transfer pool: .. math:: - :label: ZEqnNum852972 + :label: onset_rate_coeff r_{xfer\_ on} =\left\{\begin{array}{l} {{2\mathord{\left/ {\vphantom {2 t_{onset} }} \right.} t_{onset} } \qquad {\rm for\; }t_{onset} \ne \Delta t} \\ {{1\mathord{\left/ {\vphantom {1 \Delta t}} \right.} \Delta t} \qquad {\rm for\; }t_{onset} =\Delta t} \end{array}\right. -and *t*\ :sub:`onset` (s) is the number of seconds remaining in the current phenology onset growth period (Figure 14.1). The form of Eq. :eq:`ZEqnNum852972` produces a flux from the transfer pool which declines linearly over the onset growth period, approaching zero flux in the final timestep. +and *t*\ :sub:`onset` (s) is the number of seconds remaining in the current phenology onset growth period (:numref:`Figure annual phenology cycle`). The form of Eq. :eq:`onset_rate_coeff` produces a flux from the transfer pool which declines linearly over the onset growth period, approaching zero flux in the final timestep. -14.1.2 Offset Periods +Offset Periods ^^^^^^^^^^^^^^^^^^^^^ The deciduous phenology algorithms also specify the occurrence of litterfall during offset periods. In contrast to the onset periods, only leaf and fine root state variables are subject to litterfall fluxes. Carbon fluxes from display pools into litter are calculated during these periods as: .. math:: - :label: 20.14) + :label: C_litterfall_leaf CF_{leaf,litter}^{n} =\left\{\begin{array}{l} {CF_{leaf,litter}^{n-1} + r_{xfer\_ off} \left(CS_{leaf} -CF_{leaf,litter}^{n-1} {\kern 1pt} t_{offset} \right)\qquad {\rm for\; }t_{offset} \ne \Delta t} \\ {\left({CS_{leaf} \mathord{\left/ {\vphantom {CS_{leaf} \Delta t}} \right.} \Delta t} \right) @@ -108,137 +108,137 @@ The deciduous phenology algorithms also specify the occurrence of litterfall dur +CF_{alloc,leaf} \qquad {\rm for\; }t_{offset} =\Delta t} \end{array}\right. .. math:: - :label: 20.15) + :label: C_litterfall_froot CF_{froot,litter}^{n} =\left\{\begin{array}{l} {CF_{froot,litter}^{n-1} + r_{xfer\_ off} \left(CS_{froot} -CF_{froot,litter}^{n-1} {\kern 1pt} t_{offset} \right)\qquad {\rm for\; }t_{offset} \ne \Delta t} \\ {\left({CS_{froot} \mathord{\left/ {\vphantom {CS_{froot} \Delta t}} \right.} \Delta t} \right)+CF_{alloc,\, froot} \qquad \qquad \qquad {\rm for\; }t_{offset} =\Delta t} \end{array}\right. .. math:: - :label: 20.16) + :label: rate_coeff_offset r_{xfer\_ off} =\frac{2\Delta t}{t_{offset} ^{2} } -where superscripts *n* and *n-1* refer to fluxes on the current and previous timesteps, respectively. The rate coefficient :math:`{r}_{xfer\_off}` varies with time to produce a linearly increasing litterfall rate throughout the offset period. The :math:`biofuel\_harvfrac` (:numref:`Harvest to food and seed`) is the harvested fraction of aboveground biomass (leaf & livestem) for bioenergy crops. The special case for fluxes in the final litterfall timestep (:math:`{t}_{offset}` = :math:`\Delta t`\ ) ensures that all of the displayed growth is sent to the litter pools or biofuel feedstock pools. The fraction (:math:`biofuel\_harvfrac`) of leaf biomass going to the biofuel feedstock pools (Equation :eq:`25.9`) is defined in Table 26.3 and is only non-zero for prognostic crops. The remaining fraction of leaf biomass (:math:`1-biofuel\_harvfrac`) for deciduous plant types is sent to the litter pools. Similar modifications made for livestem carbon pools for prognostic crops can be found in section :numref:`Harvest to food and seed` in Equations :eq:`25.9`-:eq:`25.14`. +where superscripts *n* and *n-1* refer to fluxes on the current and previous timesteps, respectively. The rate coefficient :math:`{r}_{xfer\_off}` varies with time to produce a linearly increasing litterfall rate throughout the offset period. The *biofuel_harvfrac* (:numref:`Harvest to food and seed`) is the harvested fraction of aboveground biomass (leaf & livestem) for bioenergy crops. The special case for fluxes in the final litterfall timestep (:math:`{t}_{offset}` = :math:`\Delta t`\ ) ensures that all of the displayed growth is sent to the litter pools or biofuel feedstock pools. The fraction (*biofuel_harvfrac*) of leaf biomass going to the biofuel feedstock pools is an adjustable parameter and is only non-zero for prognostic crops (Equation :eq:`25.9`). The remaining fraction of leaf biomass (*1-biofuel_harvfrac*) for deciduous plant types is sent to the litter pools. Similar modifications made for livestem carbon pools for prognostic crops can be found in section :numref:`Harvest to food and seed` in Equations :eq:`25.9`-:eq:`25.14`. Corresponding nitrogen fluxes during litterfall take into account retranslocation of nitrogen out of the displayed leaf pool prior to litterfall (:math:`{NF}_{leaf,retrans}`, gN m\ :sup:`-2` s\ :sup:`-1`). Retranslocation of nitrogen out of fine roots is assumed to be negligible. The fluxes are: .. math:: - :label: 20.17) + :label: N_litterfall_leaf NF_{leaf,litter} ={CF_{leaf,litter} \mathord{\left/ {\vphantom {CF_{leaf,litter} CN_{leaf\_ litter} }} \right.} CN_{leaf\_ litter} } .. math:: - :label: 20.18) + :label: N_litterfall_froot NF_{froot,litter} ={CF_{leaf,litter} \mathord{\left/ {\vphantom {CF_{leaf,litter} CN_{froot} }} \right.} CN_{froot} } .. math:: - :label: 20.19) + :label: N_retranslocation_leaf NF_{leaf,retrans} =\left({CF_{leaf,litter} \mathord{\left/ {\vphantom {CF_{leaf,litter} CN_{leaf} }} \right.} CN_{leaf} } \right)-NF_{leaf,litter} . where CN is C:N. -14.1.3 Background Onset Growth +Background Onset Growth ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The stress-deciduous phenology algorithm includes a provision for the case when stress signals are absent, and the vegetation shifts from a deciduous habit to an evergreen habit, until the next occurrence of an offset stress trigger. In that case, the regular onset flux mechanism is switched off and a background onset growth algorithm is invoked (:math:`{r}_{bgtr} > 0`). During this period, small fluxes of carbon and nitrogen from the storage pools into the associated transfer pools are calculated on each time step, and the entire contents of the transfer pool are added to the associated displayed growth pool on each time step. The carbon fluxes from transfer to display pools under these conditions are: .. math:: - :label: 20.20) + :label: C_transfer_leaf_BGonset CF_{leaf\_ xfer,leaf} ={CS_{leaf\_ xfer} \mathord{\left/ {\vphantom {CS_{leaf\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.21) + :label: C_transfer_froot_BGonset CF_{froot\_ xfer,froot} ={CS_{froot\_ xfer} \mathord{\left/ {\vphantom {CS_{froot\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.22) + :label: C_transfer_livestem_BGonset CF_{livestem\_ xfer,livestem} ={CS_{livestem\_ xfer} \mathord{\left/ {\vphantom {CS_{livestem\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.23) + :label: C_transfer_deadstem_BGonset CF_{deadstem\_ xfer,deadstem} ={CS_{deadstem\_ xfer} \mathord{\left/ {\vphantom {CS_{deadstem\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.24) + :label: C_transfer_livecroot_BGonset CF_{livecroot\_ xfer,livecroot} ={CS_{livecroot\_ xfer} \mathord{\left/ {\vphantom {CS_{livecroot\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.25) + :label: C_transfer_deadcroot_BGonset CF_{deadcroot\_ xfer,deadcroot} ={CS_{deadcroot\_ xfer} \mathord{\left/ {\vphantom {CS_{deadcroot\_ xfer} \Delta t}} \right.} \Delta t} , and the corresponding nitrogen fluxes are: .. math:: - :label: 20.26) + :label: N_transfer_leaf_BGonset NF_{leaf\_ xfer,leaf} ={NS_{leaf\_ xfer} \mathord{\left/ {\vphantom {NS_{leaf\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.27) + :label: N_transfer_froot_BGonset NF_{froot\_ xfer,froot} ={NS_{froot\_ xfer} \mathord{\left/ {\vphantom {NS_{froot\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.28) + :label: N_transfer_livestem_BGonset NF_{livestem\_ xfer,livestem} ={NS_{livestem\_ xfer} \mathord{\left/ {\vphantom {NS_{livestem\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.29) + :label: N_transfer_deadstem_BGonset NF_{deadstem\_ xfer,deadstem} ={NS_{deadstem\_ xfer} \mathord{\left/ {\vphantom {NS_{deadstem\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.30) + :label: N_transfer_livecroot_BGonset NF_{livecroot\_ xfer,livecroot} ={NS_{livecroot\_ xfer} \mathord{\left/ {\vphantom {NS_{livecroot\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.31) + :label: N_transfer_deadcroot_BGonset NF_{deadcroot\_ xfer,deadcroot} ={NS_{deadcroot\_ xfer} \mathord{\left/ {\vphantom {NS_{deadcroot\_ xfer} \Delta t}} \right.} \Delta t} . -14.1.4 Background Litterfall +Background Litterfall ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Both evergreen and stress-deciduous phenology algorithms can specify a litterfall flux that is not associated with a specific offset period, but which occurs instead at a slow rate over an extended period of time, referred to as background litterfall. For evergreen types the background litterfall is the only litterfall flux. For stress-deciduous types either the offset period litterfall or the background litterfall mechanism may be active, but not both at once. Given a specification of the background litterfall rate (:math:`{r}_{bglf}`, s\ :sup:`-1`), litterfall carbon fluxes are calculated as .. math:: - :label: 20.32) + :label: C_BGlitter_leaf CF_{leaf,litter} =r_{bglf} CS_{leaf} .. math:: - :label: 20.33) + :label: C_BGlitter_froot CS_{froot,litter} =r_{bglf} CS_{froot} , with corresponding nitrogen litterfall and retranslocation fluxes: .. math:: - :label: 20.34) + :label: N_BGlitter_leaf NF_{leaf,litter} ={CF_{leaf,litter} \mathord{\left/ {\vphantom {CF_{leaf,litter} CN_{leaf\_ litter} }} \right.} CN_{leaf\_ litter} } .. math:: - :label: 20.35) + :label: N_BGlitter_froot NF_{froot,litter} ={CF_{froot,litter} \mathord{\left/ {\vphantom {CF_{froot,litter} CN_{froot} }} \right.} CN_{froot} } .. math:: - :label: 20.36) + :label: N_BGretranslocation_leaf NF_{leaf,retrans} =\left({CF_{leaf,litter} \mathord{\left/ {\vphantom {CF_{leaf,litter} CN_{leaf} }} \right.} CN_{leaf} } \right)-NF_{leaf,litter} . -14.1.5 Livewood Turnover +Livewood Turnover ^^^^^^^^^^^^^^^^^^^^^^^^ The conceptualization of live wood vs. dead wood fractions for stem and coarse root pools is intended to capture the difference in maintenance respiration rates between these two physiologically distinct tissue types. Unlike displayed pools for leaf and fine root, which are lost to litterfall, live wood cells reaching the end of their lifespan are retained as a part of the dead woody structure of stems and coarse roots. A mechanism is therefore included in the phenology routine to effect the transfer of live wood to dead wood pools, which also takes into account the different nitrogen concentrations typical of these tissue types. @@ -246,225 +246,231 @@ The conceptualization of live wood vs. dead wood fractions for stem and coarse r A live wood turnover rate (:math:`{r}_{lwt}`, s\ :sup:`-1`) is defined as .. math:: - :label: 20.37) + :label: live_wood_turnover_rate r_{lwt} ={p_{lwt} \mathord{\left/ {\vphantom {p_{lwt} \left(365\cdot 86400\right)}} \right.} \left(365\cdot 86400\right)} where :math:`{p}_{lwt} = 0.7` is the assumed annual live wood turnover fraction. Carbon fluxes from live to dead wood pools are: .. math:: - :label: 20.38) + :label: Cflux_live2dead_stem CF_{livestem,deadstem} =CS_{livestem} r_{lwt} .. math:: - :label: 20.39) + :label: Cflux_live2dead_croot CF_{livecroot,deadcroot} =CS_{livecroot} r_{lwt} , and the associated nitrogen fluxes, including retranslocation of nitrogen out of live wood during turnover, are: .. math:: - :label: 20.40) + :label: Nflux_live2dead_stem NF_{livestem,deadstem} ={CF_{livestem,deadstem} \mathord{\left/ {\vphantom {CF_{livestem,deadstem} CN_{dw} }} \right.} CN_{dw} } .. math:: - :label: 20.41) + :label: Nflux_livestem_retranslocation NF_{livestem,retrans} =\left({CF_{livestem,deadstem} \mathord{\left/ {\vphantom {CF_{livestem,deadstem} CN_{lw} }} \right.} CN_{lw} } \right)-NF_{livestem,deadstem} .. math:: - :label: 20.42) + :label: Nflux_live2dead_croot NF_{livecroot,deadcroot} ={CF_{livecroot,deadcroot} \mathord{\left/ {\vphantom {CF_{livecroot,deadcroot} CN_{dw} }} \right.} CN_{dw} } .. math:: - :label: 20.43) + :label: Nflux_livecroot_retranslocation NF_{livecroot,retrans} =\left({CF_{livecroot,deadcroot} \mathord{\left/ {\vphantom {CF_{livecroot,deadcroot} CN_{lw} }} \right.} CN_{lw} } \right)-NF_{livecroot,deadcroot} . Evergreen Phenology ------------------------ -The evergreen phenology algorithm is by far the simplest of the three possible types. It is assumed for all evergreen types that all carbon and nitrogen allocated for new growth in the current timestep goes immediately to the displayed growth pools (i.e. f\ :math:`{f}_{cur} = 1.0` (Chapter 13)). As such, there is never an accumulation of carbon or nitrogen in the storage or transfer pools, and so the onset growth and background onset growth mechanisms are never invoked for this type. Litterfall is specified to occur only through the background litterfall mechanism – there are no distinct periods of litterfall for evergreen types, but rather a continuous (slow) shedding of foliage and fine roots. This is an obvious area for potential improvements in the model, since it is known, at least for evergreen needleleaf trees in the temperate and boreal zones, that there are distinct periods of higher and lower leaf litterfall (Ferrari, 1999; Gholz et al., 1985). The rate of background litterfall (:math:`{r}_{bglf}`, section 14.1.4) depends on the specified leaf longevity (:math:`\tau_{leaf}`\, y), as +The evergreen phenology algorithm is by far the simplest of the three possible types. It is assumed for all evergreen types that all carbon and nitrogen allocated for new growth in the current timestep goes immediately to the displayed growth pools (i.e. :math:`{f}_{cur} = 1.0`). As such, there is never an accumulation of carbon or nitrogen in the storage or transfer pools, and so the onset growth and background onset growth mechanisms are never invoked for this type. Litterfall is specified to occur only through the background litterfall mechanism – there are no distinct periods of litterfall for evergreen types, but rather a continuous (slow) shedding of foliage and fine roots. This is an obvious area for potential improvements in the model, since it is known, at least for evergreen needleleaf trees in the temperate and boreal zones, that there are distinct periods of higher and lower leaf litterfall (:ref:`Ferrari, 1999`; :ref:`Gholz et al., 1985)`. The rate of background litterfall (:math:`{r}_{bglf}`) depends on the specified leaf longevity (:math:`\tau_{leaf}`\, y), as .. math:: - :label: 20.44) + :label: BG_litterfall_rate r_{bglf} =\frac{1}{\tau _{leaf} \cdot 365\cdot 86400} . Seasonal-Deciduous Phenology --------------------------------- -The seasonal-deciduous phenology algorithm derives directly from the treatment used in the offline model Biome-BGC v. 4.1.2, (Thornton et al., 2002), which in turn is based on the parameterizations for leaf onset and offset for temperate deciduous broadleaf forest from White et al. (1997). Initiation of leaf onset is triggered when a common degree-day summation exceeds a critical value, and leaf litterfall is initiated when daylength is shorter than a critical value. Because of the dependence on daylength, the seasonal deciduous phenology algorithm is only valid for latitudes outside of the tropical zone, defined here as :math:`\left|{\rm latitude}\right|>19.5{\rm {}^\circ }`. Neither the background onset nor background litterfall mechanism is invoked for the seasonal-deciduous phenology algorithm. The algorithm allows a maximum of one onset period and one offset period each year. +The seasonal-deciduous phenology algorithm derives directly from the treatment used in Biome-BGC v. 4.1.2, :ref:`(Thornton et al., 2002)`, which in turn is based on the parameterizations for leaf onset and offset for temperate deciduous broadleaf forest from :ref:`(White et al., 1997)`. Initiation of leaf onset is triggered when a common degree-day summation exceeds a critical value, and leaf litterfall is initiated when daylength is shorter than a critical value. Because of the dependence on daylength, the seasonal deciduous phenology algorithm is only valid for latitudes outside of the tropical zone, defined here as :math:`\left|{\rm latitude}\right|>19.5{\rm {}^\circ }`. For high latitudes, onset and offset are modified following :ref:`Birch et al. (2021)` where onset is governed by more mechanistic environmental thresholds (soil temperature, air temperature, and snowpack) and the photoperiod threshold for offset is increased. Neither the background onset nor background litterfall mechanism is invoked for the seasonal-deciduous phenology algorithm. The algorithm allows a maximum of one onset period and one offset period each year. The algorithms for initiation of onset and offset periods use the winter and summer solstices as coordination signals. The period between winter and summer solstice is identified as :math:`{dayl}_{n} > {dayl}_{n-1}`, and the period between summer and winter solstice is identified as :math:`{dayl}_{n} < {dayl}_{n-1}`, where :math:`{dayl}_{n}` and :math:`{dayl}_{n-1}` are the day length(s) calculated for the current and previous timesteps, respectively, using .. math:: - :label: 20.45) + :label: day_length dayl=2\cdot 13750.9871\cdot acos\left(\frac{-\sin (lat)\sin (decl)}{\cos (lat)\cos (decl)} \right), where *lat* and *decl* are the latitude and solar declination (radians), respectively, and the factor 13750.9871 is the number of seconds per radian of hour-angle. -14.3.1 Seasonal-Deciduous Onset Trigger +Seasonal-Deciduous Onset Trigger ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The onset trigger for the seasonal-deciduous phenology algorithm is based on an accumulated growing-degree-day approach (White et al., 1997). The growing-degree-day summation (:math:`{GDD}_{sum}`) is initiated ( :math:`{GDD}_{sum} = 0`) when the phenological state is dormant and the model timestep crosses the winter solstice. Once these conditions are met, :math:`{GDD}_{sum}` is updated on each timestep as +The onset trigger for the seasonal-deciduous phenology algorithm is based on an accumulated growing-degree-day approach :ref:`(White et al., 1997)` with modifications for boreal and arctic plants :ref:`(Birch et al. 2021)`. The growing-degree-day summation (:math:`{GDD}_{sum}`) is initiated ( :math:`{GDD}_{sum} = 0`) when the phenological state is dormant and the model timestep crosses the winter solstice. Once these conditions are met, :math:`{GDD}_{sum}` is updated on each timestep as .. math:: - :label: ZEqnNum510730 + :label: GDDsum_update - GDD_{sum}^{n} =\left\{\begin{array}{l} {GDD_{sum}^{n-1} +\left(T_{s,3} -TKFRZ\right)f_{day} \qquad {\rm for\; }T_{s,3} >TKFRZ} \\ {GDD_{sum}^{n-1} \qquad \qquad \qquad {\rm for\; }T_{s,3} \le TKFRZ} \end{array}\right. + GDD_{sum}^{n} =\left\{\begin{array}{l} {GDD_{sum}^{n-1} +\left(T_{s,l} -TKFRZ\right)f_{day} \qquad {\rm for\; }T_{s,l} >TKFRZ} \\ {GDD_{sum}^{n-1} \qquad \qquad \qquad {\rm for\; }T_{s,l} \le TKFRZ} \end{array}\right. -where :math:`{T}_{s,3}` (K) is the temperature of the third soil layer, and :math:`f_{day} ={\Delta t\mathord{\left/ {\vphantom {\Delta t 86400}} \right.} 86400}`. The onset period is initiated if :math:`GDD_{sum} >GDD_{sum\_ crit}`, where +where :math:`{T}_{s,l}` (K) is the temperature of the soil layer prescribed by the *phenology_soil_depth* parameter (default is layer 3), and :math:`f_{day} ={\Delta t\mathord{\left/ {\vphantom {\Delta t 86400}} \right.} 86400}`. The onset period is initiated if :math:`GDD_{sum} >GDD_{sum\_ crit}`, where .. math:: - :label: ZEqnNum598907 + :label: GDDsum_crit - GDD_{sum\_ crit} =\exp \left(4.8+0.13{\kern 1pt} \left(T_{2m,ann\_ avg} -TKFRZ\right)\right) + GDD_{sum\_ crit} =sf\cdot \exp \left(4.8+0.13{\kern 1pt} \left(T_{2m,ann\_ avg} -TKFRZ\right)\right) -and where :math:`{T}_{2m,ann\_avg}` (K) is the annual average of the 2m air temperature, and TKFRZ is the freezing point of water (273.15 K). The following control variables are set when a new onset growth period is initiated: +and where *sf* is a tunable scaling parameter (*crit_onset_gdd_sf=1*), :math:`{T}_{2m,ann\_avg}` (K) is the annual average of the 2m air temperature, and TKFRZ is the freezing point of water (273.15 K). + +For boreal and arctic seasonal-deciduous plants, the spring onset environmental criteria is modified based on :ref:`Birch et al. (2021)`. Onset is initiated when all three of the following criteria are met: the 10-day average soil temperature at *phenology_soil_depth* exceeds :math:`0^\circ C`, the 5-day average 2 m air temperature exceeds :math:`0^\circ C`, and the 5-day snow depth falls below a threshold (*snow5d_thresh_for_onset = 0.2 m*). + +The following control variables are set when a new onset growth period is initiated: .. math:: - :label: 20.48) + :label: GDDsum_reset GDD_{sum} =0 .. math:: - :label: 20.49) + :label: Tonset_reset t_{onset} =86400\cdot n_{days\_ on} , -where :math:`{n}_{days\_on}` is set to a constant value of 30 days. Fluxes from storage into transfer pools occur in the timestep when a new onset growth period is initiated. Carbon fluxes are: +where :math:`{n}_{days\_on}` is a parameter with default value of 30 days. Fluxes from storage into transfer pools occur in the timestep when a new onset growth period is initiated. Carbon fluxes are: .. math:: - :label: ZEqnNum904388 + :label: Cflux_stor2xfer_leaf CF_{leaf\_ stor,leaf\_ xfer} ={f_{stor,xfer} CS_{leaf\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} CS_{leaf\_ stor} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.51) + :label: Cflux_stor2xfer_froot CF_{froot\_ stor,froot\_ xfer} ={f_{stor,xfer} CS_{froot\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} CS_{froot\_ stor} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.52) + :label: Cflux_stor2xfer_livestem CF_{livestem\_ stor,livestem\_ xfer} ={f_{stor,xfer} CS_{livestem\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} CS_{livestem\_ stor} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.53) + :label: Cflux_stor2xfer_deadstem CF_{deadstem\_ stor,deadstem\_ xfer} ={f_{stor,xfer} CS_{deadstem\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} CS_{deadstem\_ stor} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.54) + :label: Cflux_stor2xfer_livecroot CF_{livecroot\_ stor,livecroot\_ xfer} ={f_{stor,xfer} CS_{livecroot\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} CS_{livecroot\_ stor} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.55) + :label: Cflux_stor2xfer_deadcroot CF_{deadcroot\_ stor,deadcroot\_ xfer} ={f_{stor,xfer} CS_{deadcroot\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} CS_{deadcroot\_ stor} \Delta t}} \right.} \Delta t} .. math:: - :label: ZEqnNum195642 + :label: Cflux_stor2xfer_gresp CF_{gresp\_ stor,gresp\_ xfer} ={f_{stor,xfer} CS_{gresp\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} CS_{gresp\_ stor} \Delta t}} \right.} \Delta t} and the associated nitrogen fluxes are: .. math:: - :label: ZEqnNum812152 + :label: Nflux_stor2xfer_leaf NF_{leaf\_ stor,leaf\_ xfer} ={f_{stor,xfer} NS_{leaf\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} NS_{leaf\_ stor} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.58) + :label: Nflux_stor2xfer_froot NF_{froot\_ stor,froot\_ xfer} ={f_{stor,xfer} NS_{froot\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} NS_{froot\_ stor} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.59) + :label: Nflux_stor2xfer_livestem NF_{livestem\_ stor,livestem\_ xfer} ={f_{stor,xfer} NS_{livestem\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} NS_{livestem\_ stor} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.60) + :label: Nflux_stor2xfer_deadstem NF_{deadstem\_ stor,deadstem\_ xfer} ={f_{stor,xfer} NS_{deadstem\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} NS_{deadstem\_ stor} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.61) + :label: Nflux_stor2xfer_livecroot NF_{livecroot\_ stor,livecroot\_ xfer} ={f_{stor,xfer} NS_{livecroot\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} NS_{livecroot\_ stor} \Delta t}} \right.} \Delta t} .. math:: - :label: ZEqnNum605338 + :label: Nflux_stor2xfer_deadcroot NF_{deadcroot\_ stor,deadcroot\_ xfer} ={f_{stor,xfer} NS_{deadcroot\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} NS_{deadcroot\_ stor} \Delta t}} \right.} \Delta t} where :math:`{f}_{stor,xfer}` is the fraction of current storage pool moved into the transfer pool for display over the incipient onset period. This fraction is set to 0.5, based on the observation that seasonal deciduous trees are capable of replacing their canopies from storage reserves in the event of a severe early-season disturbance such as frost damage or defoliation due to insect herbivory. -If the onset criterion (:math:`{GDD}_{sum} > {GDD}_{sum\_crit}`) is not met before the summer solstice, then :math:`{GDD}_{sum}` is set to 0.0 and the growing-degree-day accumulation will not start again until the following winter solstice. This mechanism prevents the initiation of very short growing seasons late in the summer in cold climates. The onset counter is decremented on each time step after initiation of the onset period, until it reaches zero, signaling the end of the onset period: +If the onset criteria are not met before the summer solstice, then :math:`{GDD}_{sum}` is set to 0.0 and the growing-degree-day accumulation will not start again until the following winter solstice. This mechanism prevents the initiation of very short growing seasons late in the summer in cold climates. The onset counter is decremented on each time step after initiation of the onset period, until it reaches zero, signaling the end of the onset period: .. math:: - :label: 20.63) + :label: t_onset_decrement - t_{onfset}^{n} =t_{onfset}^{n-1} -\Delta t + t_{onset}^{n} =t_{onset}^{n-1} -\Delta t -14.3.2 Seasonal-Deciduous Offset Trigger +Seasonal-Deciduous Offset Trigger ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -After the completion of an onset period, and once past the summer solstice, the offset (litterfall) period is triggered when daylength is shorter than 39300 s. The offset counter is set at the initiation of the offset period: :math:`t_{offset} =86400\cdot n_{days\_ off}`, where :math:`{n}_{days\_off}` is set to a constant value of 15 days. The offset counter is decremented on each time step after initiation of the offset period, until it reaches zero, signaling the end of the offset period: +After the completion of an onset period, and once past the summer solstice, the offset (litterfall) period is triggered when daylength is shorter than 11 h. The offset counter is set at the initiation of the offset period: :math:`t_{offset} =86400\cdot n_{days\_ off}`, where :math:`{n}_{days\_off}` is a constant parameter with default value of 15 days. The offset counter is decremented on each time step after initiation of the offset period, until it reaches zero, signaling the end of the offset period: .. math:: - :label: 20.64) + :label: t_offset_decrement t_{offset}^{n} =t_{offset}^{n-1} -\Delta t +At high latitudes, :math:`\left|{\rm latitude}\right|>65{\rm {}^\circ }`, a more accurate timing for senescence is a daylength of 15 h :ref:`Eitel et al., (2019)`. As in :ref:`Birch et al., (2021)`, the daylength threshold is set to 15 h above :math:`65{\rm {}^\circ }` and scaled linearly along a latitudinal gradient to :math:`45{\rm {}^\circ }`. + Stress-Deciduous Phenology ------------------------------- -The stress-deciduous phenology algorithm was developed specifically for the CLM based in part on the grass phenology model proposed by White et al. (1997). The algorithm handles phenology for vegetation types such as grasses and tropical drought-deciduous trees that respond to both cold and drought-stress signals, and that can have multiple growing seasons per year. The algorithm also allows for the possibility that leaves might persist year-round in the absence of a suitable stress trigger. In that case the phenology switches to an evergreen habit, maintaining a marginally-deciduous leaf longevity (one year) until the occurrence of the next stress trigger. +The stress-deciduous phenology algorithm was developed specifically for the CLM based in part on the grass phenology model proposed by :ref:`(White et al., 1997)`. The algorithm handles phenology for vegetation types such as grasses and tropical drought-deciduous trees that respond to both cold and drought-stress signals, and that can have multiple growing seasons per year. The algorithm also allows for the possibility that leaves might persist year-round in the absence of a suitable stress trigger. In that case the phenology switches to an evergreen habit, maintaining a marginally-deciduous leaf longevity (one year) until the occurrence of the next stress trigger. -14.4.1 Stress-Deciduous Onset Triggers +Stress-Deciduous Onset Triggers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In climates that are warm year-round, onset triggering depends on soil water availability. At the beginning of a dormant period (end of previous offset period), an accumulated soil water index (:math:`{SWI}_{sum}`, d) is initialized (:math:`{SWI}_{sum} = 0`), with subsequent accumulation calculated as: .. math:: - :label: ZEqnNum503826 + :label: soil_water_index_accumulation SWI_{sum}^{n} =\left\{\begin{array}{l} {SWI_{sum}^{n-1} +f_{day} \qquad {\rm for\; }\Psi _{s,3} \ge \Psi _{onset} } \\ {SWI_{sum}^{n-1} \qquad \qquad {\rm for\; }\Psi _{s,3} <\Psi _{onset} } \end{array}\right. -where :math:`\Psi`\ :sub:`s,3` is the soil water potential (MPa) in the third soil layer and :math:`{\Psi}_{onset} = -0.6 MPa` is the onset soil water potential threshold. Onset triggering is possible once :math:`{SWI}_{sum} > 15`. To avoid spurious onset triggering due to soil moisture in the third soil layer exceeding the threshold due only to soil water suction of water from deeper in the soil column, an additional precipitation trigger is included which requires at least 20 mm of rain over the previous 10 days :ref:`(Dahlin et al., 2015) `. If the cold climate growing degree-day accumulator is not active at the time when the soil moisture and precipitation thresholds are reached (see below), and if the daylength is greater than 6 hours, then onset is triggered. Except as noted below, :math:`{SWI}_{sum}` continues to accumulate according to Eq. :eq:`ZEqnNum503826` during the dormant period if the daylength criterion prevents onset triggering, and onset is then triggered at the timestep when daylength exceeds 6 hours. +where :math:`\Psi`\ :sub:`s,3` is the soil water potential (MPa) in the third soil layer and :math:`{\Psi}_{onset} = -0.6 MPa` is the onset soil water potential threshold. Onset triggering is possible once :math:`{SWI}_{sum} > 15`. To avoid spurious onset triggering due to soil moisture in the third soil layer exceeding the threshold due only to soil water suction of water from deeper in the soil column, an additional precipitation trigger is included which requires at least 20 mm of rain over the previous 10 days :ref:`(Dahlin et al., 2015) `. If the cold climate growing degree-day accumulator is not active at the time when the soil moisture and precipitation thresholds are reached (see below), and if the daylength is greater than 6 hours, then onset is triggered. Except as noted below, :math:`{SWI}_{sum}` continues to accumulate according to Eq. :eq:`soil_water_index_accumulation` during the dormant period if the daylength criterion prevents onset triggering, and onset is then triggered at the timestep when daylength exceeds 6 hours. In climates with a cold season, onset triggering depends on both accumulated soil temperature summation and adequate soil moisture. At the beginning of a dormant period a freezing day accumulator (:math:`{FD}_{sum}`, d) is initialized (:math:`{FD}_{sum} = 0`), with subsequent accumulation calculated as: .. math:: - :label: 20.66) + :label: freezing_day_accumulation FD_{sum}^{n} =\left\{\begin{array}{l} {FD_{sum}^{n-1} +f_{day} \qquad {\rm for\; }T_{s,3} >TKFRZ} \\ {FD_{sum}^{n-1} \qquad \qquad {\rm for\; }T_{s,3} \le TKFRZ} \end{array}\right. . -If :math:`{FD}_{sum} > 15` during the dormant period, then a cold-climate onset triggering criterion is introduced, following exactly the growing degree-day summation (:math:`{GDD}_{sum}`) logic of Eqs. :eq:`ZEqnNum510730` and :eq:`ZEqnNum598907`. At that time :math:`{SWI}_{sum}` is reset (:math:`{SWI}_{sum} = 0`). Onset triggering under these conditions depends on meeting all three of the following criteria: :math:`{SWI}_{sum} > 15`, :math:`{GDD}_{sum} > {GDD}_{sum\_crit}`, and daylength greater than 6 hrs. +If :math:`{FD}_{sum} > 15` during the dormant period, then a cold-climate onset triggering criterion is introduced, following exactly the growing degree-day summation (:math:`{GDD}_{sum}`) logic of Eqs. :eq:`GDDsum_update` and :eq:`GDDsum_crit`. At that time :math:`{SWI}_{sum}` is reset (:math:`{SWI}_{sum} = 0`). Onset triggering under these conditions depends on meeting all three of the following criteria: :math:`{SWI}_{sum} > 15`, :math:`{GDD}_{sum} > {GDD}_{sum\_crit}`, and daylength greater than 6 hrs. -The following control variables are set when a new onset growth period is initiated: :math:`{SWI}_{sum} = 0`, :math:`{FD}_{sum} = 0`, :math:`{GDD}_{sum} = 0`, :math:`{n}_{days\_active} = 0`, and :math:`t_{onset} = 86400\cdot n_{days\_ on}`, where :math:`{n}_{days\_on}` is set to a constant value of 30 days. Fluxes from storage into transfer pools occur in the timestep when a new onset growth period is initiated, and are handled identically to Eqs. :eq:`ZEqnNum904388` -:eq:`ZEqnNum195642` for carbon fluxes, and to Eqs. :eq:`ZEqnNum812152` - :eq:`ZEqnNum605338` for nitrogen fluxes. The onset counter is decremented on each time step after initiation of the onset period, until it reaches zero, signaling the end of the onset period: +The following control variables are set when a new onset growth period is initiated: :math:`{SWI}_{sum} = 0`, :math:`{FD}_{sum} = 0`, :math:`{GDD}_{sum} = 0`, :math:`{n}_{days\_active} = 0`, and :math:`t_{onset} = 86400\cdot n_{days\_ on}`, where :math:`{n}_{days\_on}` is a constant parameter with default setting of 30 days. Fluxes from storage into transfer pools occur in the timestep when a new onset growth period is initiated, and are handled identically to Eqs. :eq:`Cflux_stor2xfer_leaf` -:eq:`Cflux_stor2xfer_gresp` for carbon fluxes, and to Eqs. :eq:`Nflux_stor2xfer_leaf` - :eq:`Nflux_stor2xfer_deadcroot` for nitrogen fluxes. The onset counter is decremented on each time step after initiation of the onset period, until it reaches zero, signaling the end of the onset period: .. math:: - :label: 20.67) + :label: t_onset_decrement_stress_deciduous - t_{onfset}^{n} =t_{onfset}^{n-1} -\Delta t + t_{onset}^{n} =t_{onset}^{n-1} -\Delta t -14.4.2 Stress-Deciduous Offset Triggers +Stress-Deciduous Offset Triggers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Any one of the following three conditions is sufficient to initiate an offset period for the stress-deciduous phenology algorithm: sustained period of dry soil, sustained period of cold temperature, or daylength shorter than 6 hours. Offset triggering due to dry soil or cold temperature conditions is only allowed once the most recent onset period is complete. Dry soil condition is evaluated with an offset soil water index accumulator (:math:`{OSWI}_{sum}`, d). To test for a sustained period of dry soils, this control variable can increase or decrease, as follows: .. math:: - :label: 20.68) + :label: offset_soil_water_index_accumulation OSWI_{sum}^{n} =\left\{\begin{array}{l} {OSWI_{sum}^{n-1} +f_{day} \qquad \qquad \qquad {\rm for\; }\Psi _{s,3} \le \Psi _{offset} } \\ {{\rm max}\left(OSWI_{sum}^{n-1} -f_{day} ,0\right)\qquad {\rm for\; }\Psi _{s,3} >\Psi _{onset} } \end{array}\right. @@ -473,33 +479,33 @@ where :math:`{\Psi}_{offset} = -0.8 MPa` is the offset soil water potential thre The cold temperature trigger is calculated with an offset freezing day accumulator (:math:`{OFD}_{sum}`, d). To test for a sustained period of cold temperature, this variable can increase or decrease, as follows: .. math:: - :label: 20.69) + :label: offset_freezing_day_accumulation OFD_{sum}^{n} =\left\{\begin{array}{l} {OFD_{sum}^{n-1} +f_{day} \qquad \qquad \qquad {\rm for\; }T_{s,3} \le TKFRZ} \\ {{\rm max}\left(OFD_{sum}^{n-1} -f_{day} ,0\right)\qquad \qquad {\rm for\; }T_{s,3} >TKFRZ} \end{array}\right. An offset period is triggered if the previous onset period is complete and :math:`{OFD}_{sum} > {OFD}_{sum\_crit}`, where :math:`{OFD}_{sum\_crit} = 15`. -The offset counter is set at the initiation of the offset period: :math:`t_{offset} =86400\cdot n_{days\_ off}`, where :math:`{n}_{days\_off}` is set to a constant value of 15 days. The offset counter is decremented on each time step after initiation of the offset period, until it reaches zero, signaling the end of the offset period: +The offset counter is set at the initiation of the offset period: :math:`t_{offset} =86400\cdot n_{days\_ off}`, where :math:`{n}_{days\_off}` is a constant parameter with default setting of 15 days. The offset counter is decremented on each time step after initiation of the offset period, until it reaches zero, signaling the end of the offset period: .. math:: - :label: 20.70) + :label: t_offset_decrement_stress_deciduous t_{offset}^{n} =t_{offset}^{n-1} -\Delta t -14.4.3 Stress-Deciduous: Long Growing Season +Stress-Deciduous: Long Growing Season ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Under conditions when the stress-deciduous conditions triggering offset are not met for one year or longer, the stress-deciduous algorithm shifts toward the evergreen behavior. This can happen in cases where a stress-deciduous vegetation type is assigned in a climate where suitably strong stresses occur less frequently than once per year. This condition is evaluated by tracking the number of days since the beginning of the most recent onset period (:math:`{n}_{days\_active}`, d). At the end of an offset period :math:`{n}_{days\_active}` is reset to 0. A long growing season control variable (*LGS*, range 0 to 1) is calculated as: .. math:: - :label: 20.71) + :label: long_growing_season LGS=\left\{\begin{array}{l} {0\qquad \qquad \qquad {\rm for\; }n_{days\_ active} <365} \\ {\left({n_{days\_ active} \mathord{\left/ {\vphantom {n_{days\_ active} 365}} \right.} 365} \right)-1\qquad {\rm for\; }365\le n_{days\_ active} <730} \\ {1\qquad \qquad \qquad {\rm for\; }n_{days\_ active} \ge 730} \end{array}\right. . The rate coefficient for background litterfall (:math:`{r}_{bglf}`, s\ :sup:`-1`) is calculated as a function of *LGS*: .. math:: - :label: 20.72) + :label: lgs_BGlitterfall_rate_coef r_{bglf} =\frac{LGS}{\tau _{leaf} \cdot 365\cdot 86400} @@ -508,139 +514,139 @@ where :math:`{\tau}_{leaf}` is the leaf longevity. The result is a shift to cont The rate coefficient for background onset growth from the transfer pools ( :math:`{r}_{bgtr}`, s\ :sup:`-1`) also depends on *LGS*, as: .. math:: - :label: 20.73) + :label: lgs_BGtr_rate_coef r_{bgtr} =\frac{LGS}{365\cdot 86400} . On each timestep with :math:`{r}_{bgtr}` :math:`\neq` 0, carbon fluxes from storage to transfer pools are calculated as: .. math:: - :label: 20.74) + :label: Cflux_stor2xfer_leaf_stress_deciduous CF_{leaf\_ stor,leaf\_ xfer} =CS_{leaf\_ stor} r_{bgtr} .. math:: - :label: 20.75) + :label: Cflux_stor2xfer_froot_stress_deciduous CF_{froot\_ stor,froot\_ xfer} =CS_{froot\_ stor} r_{bgtr} .. math:: - :label: 20.76) + :label: Cflux_stor2xfer_livestem_stress_deciduous CF_{livestem\_ stor,livestem\_ xfer} =CS_{livestem\_ stor} r_{bgtr} .. math:: - :label: 20.77) + :label: Cflux_stor2xfer_deadstem_stress_deciduous CF_{deadstem\_ stor,deadstem\_ xfer} =CS_{deadstem\_ stor} r_{bgtr} .. math:: - :label: 20.78) + :label: Cflux_stor2xfer_livecroot_stress_deciduous CF_{livecroot\_ stor,livecroot\_ xfer} =CS_{livecroot\_ stor} r_{bgtr} .. math:: - :label: 20.79) + :label: Cflux_stor2xfer_deadcroot_stress_deciduous CF_{deadcroot\_ stor,deadcroot\_ xfer} =CS_{deadcroot\_ stor} r_{bgtr} , with corresponding nitrogen fluxes: .. math:: - :label: 20.80) + :label: Nflux_stor2xfer_leaf_stress_deciduous NF_{leaf\_ stor,leaf\_ xfer} =NS_{leaf\_ stor} r_{bgtr} .. math:: - :label: 20.81) + :label: Nflux_stor2xfer_froot_stress_deciduous NF_{froot\_ stor,froot\_ xfer} =NS_{froot\_ stor} r_{bgtr} .. math:: - :label: 20.82) + :label: Nflux_stor2xfer_livestem_stress_deciduous NF_{livestem\_ stor,livestem\_ xfer} =NS_{livestem\_ stor} r_{bgtr} .. math:: - :label: 20.83) + :label: Nflux_stor2xfer_deadstem_stress_deciduous NF_{deadstem\_ stor,deadstem\_ xfer} =NS_{deadstem\_ stor} r_{bgtr} .. math:: - :label: 20.84) + :label: Nflux_stor2xfer_livecroot_stress_deciduous NF_{livecroot\_ stor,livecroot\_ xfer} =NS_{livecroot\_ stor} r_{bgtr} .. math:: - :label: 20.85) + :label: Nflux_stor2xfer_deadcroot_stress_deciduous NF_{deadcroot\_ stor,deadcroot\_ xfer} =NS_{deadcroot\_ stor} r_{bgtr} . -The result, in conjunction with the treatment of background onset growth, is a shift to continuous transfer from storage to display pools at a rate that would result in complete turnover of the storage pools in one year at steady state, once *LGS* reaches 1 (i.e. after two years without stress-deciduous offset conditions). If and when conditions cause stress-deciduous triggering again, :math:`{r}_{bgtr}` is rest to 0. +The result, in conjunction with the treatment of background onset growth, is a shift to continuous transfer from storage to display pools at a rate that would result in complete turnover of the storage pools in one year at steady state, once *LGS* reaches 1 (i.e. after two years without stress-deciduous offset conditions). If and when conditions cause stress-deciduous triggering again, :math:`{r}_{bgtr}` is reset to 0. Litterfall Fluxes Merged to the Column Level ------------------------------------------------- -CLM uses three litter pools, defined on the basis of commonly measured chemical fractionation of fresh litter into labile (LIT1 = hot water and alcohol soluble fraction), cellulose/hemicellulose (LIT2 = acid soluble fraction) and remaining material, referred to here for convenience as lignin (LIT3 = acid insoluble fraction) (Aber et al., 1990; Taylor et al., 1989). While multiple plant functional types can coexist on a single CLM soil column, each soil column includes a single instance of the litter pools. Fluxes entering the litter pools due to litterfall are calculated using a weighted average of the fluxes originating at the PFT level. Carbon fluxes are calculated as: +CLM uses three litter pools, defined on the basis of commonly measured chemical fractionation of fresh litter into labile (LIT1 = hot water and alcohol soluble fraction), cellulose/hemicellulose (LIT2 = acid soluble fraction) and remaining material, referred to here for convenience as lignin (LIT3 = acid insoluble fraction) (:ref:`(Aber et al., 1990)`; :ref:`(Taylor et al., 1989)`). While multiple plant functional types can coexist on a single CLM soil column, each soil column includes a single instance of the litter pools. Fluxes entering the litter pools due to litterfall are calculated using a weighted average of the fluxes originating at the PFT level. Carbon fluxes are calculated as: .. math:: - :label: 20.86) + :label: Cflux_leat2lit1 CF_{leaf,lit1} =\sum _{p=0}^{npfts}CF_{leaf,litter} f_{lab\_ leaf,p} wcol_{p} .. math:: - :label: 20.87) + :label: Cflux_leaf2lit2 CF_{leaf,lit2} =\sum _{p=0}^{npfts}CF_{leaf,litter} f_{cel\_ leaf,p} wcol_{p} .. math:: - :label: 20.88) + :label: Cflux_leaf2lit3 CF_{leaf,lit3} =\sum _{p=0}^{npfts}CF_{leaf,litter} f_{lig\_ leaf,p} wcol_{p} .. math:: - :label: 20.89) + :label: Cflux_froot2lit1 CF_{froot,lit1} =\sum _{p=0}^{npfts}CF_{froot,litter} f_{lab\_ froot,p} wcol_{p} .. math:: - :label: 20.90) + :label: Cflux_froot2lit2 CF_{froot,lit2} =\sum _{p=0}^{npfts}CF_{froot,litter} f_{cel\_ froot,p} wcol_{p} .. math:: - :label: 20.91) + :label: Cflux_froot2lit3 CF_{froot,lit3} =\sum _{p=0}^{npfts}CF_{froot,litter} f_{lig\_ froot,p} wcol_{p} , where :math:`{f}_{lab\_leaf,p}`, :math:`{f}_{cel\_leaf,p}`, and :math:`{f}_{lig\_leaf,p}` are the labile, cellulose/hemicellulose, and lignin fractions of leaf litter for PFT *p*, :math:`{f}_{lab\_froot,p}`, :math:`{f}_{cel\_froot,p}`, and :math:`{f}_{lig\_froot,p}` are the labile, cellulose/hemicellulose, and lignin fractions of fine root litter for PFT *p*, :math:`{wtcol}_{p}` is the weight relative to the column for PFT *p*, and *p* is an index through the plant functional types occurring on a column. Nitrogen fluxes to the litter pools are assumed to follow the C:N of the senescent tissue, and so are distributed using the same fractions used for carbon fluxes: .. math:: - :label: 20.92) + :label: Nflux_leaf2lit1 NF_{leaf,lit1} =\sum _{p=0}^{npfts}NF_{leaf,litter} f_{lab\_ leaf,p} wcol_{p} .. math:: - :label: 20.93) + :label: Nflux_leaf2lit2 NF_{leaf,lit2} =\sum _{p=0}^{npfts}NF_{leaf,litter} f_{cel\_ leaf,p} wcol_{p} .. math:: - :label: 20.94) + :label: Nflux_leaf2lit3 NF_{leaf,lit3} =\sum _{p=0}^{npfts}NF_{leaf,litter} f_{lig\_ leaf,p} wcol_{p} .. math:: - :label: 20.95) + :label: Nflux_froot2lit1 NF_{froot,lit1} =\sum _{p=0}^{npfts}NF_{froot,litter} f_{lab\_ froot,p} wcol_{p} .. math:: - :label: 20.96) + :label: Nflux_froot2lit2 NF_{froot,lit2} =\sum _{p=0}^{npfts}NF_{froot,litter} f_{cel\_ froot,p} wcol_{p} .. math:: - :label: 20.97) + :label: Nflux_froot2lit3 NF_{froot,lit3} =\sum _{p=0}^{npfts}NF_{froot,litter} f_{lig\_ froot,p} wcol_{p} . diff --git a/doc/source/users_guide/overview/introduction.rst b/doc/source/users_guide/overview/introduction.rst index 969dec6e49..28cba7917d 100644 --- a/doc/source/users_guide/overview/introduction.rst +++ b/doc/source/users_guide/overview/introduction.rst @@ -81,7 +81,7 @@ README file describing |version| The README (which can be found in ``$CTSMROOT/doc``) is repeated here. -.. include:: ../../../../README +.. include:: ../../../../README.md :literal: .. _best-practices-for-usage: diff --git a/doc/source/users_guide/testing/testing.rst b/doc/source/users_guide/testing/testing.rst index 301f59c891..8375e97902 100644 --- a/doc/source/users_guide/testing/testing.rst +++ b/doc/source/users_guide/testing/testing.rst @@ -19,7 +19,7 @@ We first introduce the test scripts that work for all CESM components. The CIME CTSM Fortran Unit Tests ======================= -.. include:: ../../../../src/README.unit_testing +.. include:: ../../../../src/README.unit_testing.md :literal: CTSM Build-namelist Tests diff --git a/doc/source/users_guide/trouble-shooting/index.rst b/doc/source/users_guide/trouble-shooting/index.rst index de6b0c053a..c92a7e3ba8 100644 --- a/doc/source/users_guide/trouble-shooting/index.rst +++ b/doc/source/users_guide/trouble-shooting/index.rst @@ -12,6 +12,6 @@ Troubleshooting ##################################### .. toctree:: - :maxdepth: 2 + :maxdepth: 5 trouble-shooting.rst diff --git a/doc/source/users_guide/trouble-shooting/trouble-shooting.rst b/doc/source/users_guide/trouble-shooting/trouble-shooting.rst index a971b7f2cb..0e1a5e241f 100644 --- a/doc/source/users_guide/trouble-shooting/trouble-shooting.rst +++ b/doc/source/users_guide/trouble-shooting/trouble-shooting.rst @@ -2,27 +2,256 @@ .. _trouble-shooting: -*************** -Troubleshooting -*************** +********************************************* +Introduction +********************************************* In this chapter we give some guidance on what to do when you encounter some of the most common problems. In general you may run into one of four types of problems: 1. *case-creation* -#. *setup-time* -#. *build-time* -#. *run-time* +2. *setup-time* +3. *build-time* +4. *run-time* -Start with the `CIME Trouble Shooting Guide `_ , especially if you encounter one of the first three types of problems. The CIME troubleshooting guide also provides some useful tips regarding run-time errors. If this doesn't identify and solve your problem, then try some of the suggestions below for run-time errors. +Start with the `CIME Trouble Shooting Guide `_ , especially if you encounter one of the first three types of problems. The CIME troubleshooting guide also provides some useful tips regarding run-time errors. If this doesn't identify and solve your problem, then try some of the suggestions below for run-time errors. +********************************************* General Advice on Debugging Run time Problems -============================================= +********************************************* -The model has been run for thousands and thousands of simulation years in many different configurations, both fully-coupled and in land-only modes, without problems. If you have modified the model in any way, by using either different input datasets or new or modified code, then that is the first place to look if you encounter an error. However, the model is not completely infallible, as noted below. +Release versions of the model have been run for thousands and thousands of simulation years in many different configurations, both fully-coupled and in land-only modes, without problems. If you have modified the model in any way, by using either different input datasets or new or modified code, then that is the first place to look if you encounter an error. In particular, see the following section :numref:`List of common problems to watch out for when developing / reviewing code` for advice on problems to watch out for when developing or reviewing code. -It is important to examine all of the component log files in the run directory for errors. An error in the land model may not appear in the lnd log file, it may show up in the cesm log. In a land-only simulation, errors associated with the data atmosphere model may show up in the atm log or the cesm log, or both. The two logs together may contain useful information about the error. Frequently, the error output in the log files will include a **traceback** of code where the error occurred. Identifying the specific line of code where the error occurred is the first step in diagnosing the error and developing a solution. If a traceback doesn't appear in the log files, then try running in debug mode as noted in the CIME troubleshooting guide. An example of a traceback in the cesm log is given below +.. _List of common problems to watch out for when developing / reviewing code: + +===================================================================================================== +List of common problems to watch out for when developing / reviewing code +===================================================================================================== + +----------------------------------------------------------------------------------------------------- +Possible sources of model crashes or non-physical results +----------------------------------------------------------------------------------------------------- + +Potential for divide-by-zero +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Solution: put code in a conditional that checks for 0, and handles 0 values specially + +Potential for other floating point exceptions (e.g,. raising 0 to a negative power, etc.) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Solution: put code in a conditional that handles mathematically impossible cases specially + +Potential for a quantity that should be non-negative to go negative, due to rounding errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Solutions: +:: + + foo = max(foo, 0._r8) + +or use the ``truncate_small_values`` subroutine in ``NumericsMod``. + +----------------------------------------------------------------------------------------------------- +Possible sources of science bugs and maintainability problems +----------------------------------------------------------------------------------------------------- + +Block of code is copy & pasted, or effectively duplicated +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This is one of the most common issues we encounter. It causes both maintainability problems and future bugs (when one block of code gets modified and thus becomes out of sync with the other block). Sometimes a block of code is copied and pasted entirely; other times this issue is more subtle, with logic effectively duplicated in two places even though the code looks somewhat different. + +This problem can be identified by asking yourself: If I make a change in place A, will I need to make a corresponding change in place B? + +Possible solutions: + +- Introduce a subroutine that holds the common code, with parameters to allow for any differences in behavior between the different locations + +- Save the result of a calculation in a variable that can be reused in multiple places + +Variable is missing from the restart file, or is on the restart file when it doesn't need to be +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Variables need to be written to and read from the restart file if their value persists from one time step to the next. This is mainly the case for the model's fundamental state variables. However, in order to minimize restart file size (reasons of disk usage, performance, and understandability), we try to avoid adding variables to the restart file unless they're truly needed. + +Some good rules of thumb to use are: + +- If a variable's value at time ``t`` directly depends on its value at time ``t-1``, often through evolution equations of the form ``x = x + flux*dtime``, then it likely needs to be on the restart file. + +- Imagine setting a variable to 0 at the start of each time step. Would this cause incorrect results? If so, it likely needs to be on the restart file. + +- However, if a variable can be recalculated based on other variables, then it probably should *not* be on the restart file. Instead, its initial value can be calculated in model initialization, after reading the restart file. + +There are also some cases where a variable is needed on the restart file because its value is referenced (i.e., it appears on the right-hand side of an equation) earlier in the driver loop than where it is set. This is a subtle issue, and needs to be kept in mind when developing and reviewing code. For example, the relevant parts of the driver loop could look like this: +:: + + foo = bar*2 + + (more code here) + + bar = ... + +In reality, these lines will be in subroutines called from the main driver loop, so an understanding is needed of the calling order of the model's subroutines. + +An ideal solution in this case is to reorder the code so that ``bar`` is calculated before it is used. The next most ideal solution is to recalculate ``bar`` from other variables in initialization after the restart file is read. However, if neither of these are possible, then ``bar`` needs to be added to the restart file. + +We have many restart tests in the automated test suite; these catch many problems with variables being absent from the restart file that should be there. However, these tests cannot catch all problems - particularly if a variable's value only needs to persist between time steps in certain circumstances (such as if the restart is done mid-day). In addition, these tests cannot catch problems with variables being added to the restart file unnecessarily. + +Variable is used on right-hand side of an equation before it has its "final" value +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Example: +:: + + bar = ... + + foo = bar + 1._r8 + + (more code here) + + bar = bar + 1._r8 + +In this case, it's possible that the ``foo`` assignment should really have happened after the increment to ``bar``. + +Solution: Check code carefully for assignments to variables that are used on the right-hand side of equations. Ideally, this search would only need to be done within the current subroutine. But in practice, variables in CTSM are sometimes updated in multiple subroutines, so you should extend this search to make sure your new code happens in the correct place in the driver loop. (i.e., make sure that there aren't subroutines called later in the driver that update the quantity that you're using on the right-hand side of the equation.) + +------------------------------------------------------------------------------------------------------------ +Possible sources of answer changes with changing processor count (PEM test failures, also seen in ERP tests) +------------------------------------------------------------------------------------------------------------ + +Problems specific to parallelization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +PEM and ERP tests are designed to catch problems specific to parallelization. In CTSM, these aren't the most common sources of errors with these tests, but we'll start with a few parallel-specific reasons that these tests could fail. + +Missing or incorrect broadcast for a namelist variable +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +Namelist variables are read on the master proc and then should be broadcast to all other processors. If a broadcast statement is missing or incorrect for a namelist variable, then the namelist value could be wrong on all other processors. This will lead to answer changes with changing processor count because changing processor count will change which grid cells are on the master proc (with the correct namelist value) vs. other processors. + +Processor count dependence of a parallel algorithm +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +An obvious source of answer changes with changing processor count is processor count dependence of a parallel algorithm. A common issue here is an MPI reduction that depends on the processor count – e.g., a sum across multiple processors, which could depend on the order in which the sum is taken. + +However, we do not have many parallel algorithms in CTSM; these would mainly apply in cases where there is communication between grid cells. + +Incorrect indexing of a subgrid variable +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +One common cause of processor count dependence is the incorrect indexing of a subgrid variable. For example, if a patch variable is indexed by ``g`` instead of ``p``, then it will access the wrong index. This will be picked up in a PEM (or ERP) test because exactly which point it accesses is processor count-dependent. + +Here are some ``git grep`` commands that can help find this problem: + +.. code:: shell + + git grep -i '_patch \*( \*[glc] \*)' + git grep -i '_col \*( \*[glp] \*)' + git grep -i '_lun \*( \*[gcp] \*)' + git grep -i '_grc \*( \*[lcp] \*)' + +However, since we often strip the suffix in associate statements, you cannot rely on these grep commands to detect this issue. + +Scalar variable used before it is set in a given loop iteration +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Another common cause of answer changes with changing processor counts is a scalar variable being used before it is set in a given loop iteration. This means that its value depends on a previous loop iteration, or possibly the value that was set in an earlier loop in this subroutine. Changing processor counts changes which grid cell is operated on first in a loop for a given processor, and also which grid cell is the previous loop iteration for a given grid cell. + +There are a few common specific ways that this appears in CTSM code, as noted below: + +Missing setting of ``c``, ``l`` or ``g`` in a loop +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +Often, a loop over one subgrid level will access variables in arrays at a coarser subgrid level. For example, a loop over patches will access column and gridcell-level variables. This requires settings like ``c = patch%column(p)``. Sometimes there is a bug where a given loop is missing one of these needed settings; instead its setting comes from the previous loop in that subroutine. In this case, all patches – on all grid cells – will use the same ``c`` value. + +Scalar variable set in a conditional but accessed outside that conditional +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +Sometimes a scalar variable is set inside a conditional but is accessed outside that conditional. There may be multiple branches of the conditional with the intent that the scalar is set for all cases, but there may be a missing branch, so in some situations the scalar doesn't end up getting set for a particular point. The value will then be taken from the previous loop iteration. + +------------------------------------------------------------------------------------------------------------ +Possible sources of threading bugs +------------------------------------------------------------------------------------------------------------ + +Whole-array assignment +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:: + + foo(:) = 0._r8 + +should be replaced by the following, assuming ``foo`` is a column-level array: +:: + + foo(bounds%begc:bounds%endc) = 0._r8 + +or, better, initialize ``foo`` within a loop over the appropriate filter, or a loop over ``bounds%begc`` to ``bounds%endc``, ideally subset by active points. + +Forgetting to index into a variable for assignment +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +E.g., ``variable_patch = 0._r8`` instead of ``variable_patch(p) = 0._r8``. + +Improper argument passing +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +See [this page on the old wiki](https://wiki.ucar.edu/display/ccsm/CLM+Coding+Conventions#CLMCodingConventions-ArgumentPassingargPass) + +Identify specific loops with issues by turning off threading for loops +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +One way to identify threaded loops with issues is to turn off more and more loops until you identify ones with issues. + +For example a subroutine with a loop like this... +:: + + !$OMP PARALLEL DO PRIVATE (nc,bounds_clump) + do nc = 1,nclumps + call get_clump_bounds(nc, bounds_clump) + ... + end do + !$OMP END PARALLEL DO + +Incorrect list of private variables in threaded loops +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For threading each processor thread needs to have its own version of temporary or loop indexing variables. For longer loops the list needed can be quite long, if you don't have the right list of variables in the private list, different threads will share these variables and result in strange behavior. + +So in the above example, if either ``nc``, or ``bounds_clump`` weren't in the private list the loop would not be able to function correctly. + +Turn off OpenMP parallelism by removing the first line or adding an extra comment character (!) to comment it out. + +----------------------------------------------------------------------------------------------------- +Possible sources of performance problems +----------------------------------------------------------------------------------------------------- + +Doing an operation on all array elements rather than just active points +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Active points are (generally, but not entirely) ones with > 0 weight on the grid cell. + +Solution: Use the filters, which only include active points + +Nested loops in the wrong order for cache-friendliness and/or vectorizability +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +----------------------------------------------------------------------------------------------------- +Other things to look for in a PR review +----------------------------------------------------------------------------------------------------- + +Binary files committed without the use of git lfs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If someone commits a binary file without git lfs enabled, it will actually be committed directly. The same thing will happen even if they have git lfs enabled if the file has an extension that isn't currently tracked by git lfs. Look for any such binary files when looking through the list of changed files. These will often appear in the doc directory. + +See the .gitattributes file at the top level of the repository for files typically handled by git lfs. + +.. _A specific troubleshooting example: + +===================================================================================================== +A specific troubleshooting example +===================================================================================================== + +First of all, it is important to examine all of the component log files in the run directory for errors. An error in the land model may not appear in the lnd log file, it may show up in the cesm log. In a land-only simulation, errors associated with the data atmosphere model may show up in the atm log or the cesm log, or both. The two logs together may contain useful information about the error. Frequently, the error output in the log files will include a **traceback** of code where the error occurred. Identifying the specific line of code where the error occurred is the first step in diagnosing the error and developing a solution. If a traceback doesn't appear in the log files, then try running in debug mode as noted in the CIME troubleshooting guide. An example of a traceback in the cesm log is given below (this specific example is from cesm2_2_beta05) :: 398: ERROR: Carbon or Nitrogen patch negative = -60.0630620423182 @@ -59,7 +288,7 @@ It is important to examine all of the component log files in the run directory f 398:libc.so.6 00002B8B95D306E5 __libc_start_main Unknown Unknown 398:cesm.exe 0000000000408C29 Unknown Unknown Unknown -Here, the output is identifying the sequence of Fortran statements involved in the error, starting with line 133 in cime_driver.F90 and ending with line 114 in shr_abort_mod.F90. In this case the run is triggering an error check in the model related to negative carbon/nitrogen at line 693 of CNPrecisionControlMod.F90. In addition, there is additional information related to the error indicating the carbon or nitrogen state is critically negative at line 209 in CNPrecisionControlMod.F90, which is +Here, the output is identifying the sequence of Fortran statements involved in the error, starting with line 133 in ``cime_driver.F90`` and ending with line 114 in ``shr_abort_mod.F90``. In this case the run is triggering an error check in the model related to negative carbon/nitrogen at line 693 of ``CNPrecisionControlMod.F90``. In addition, there is additional information related to the error indicating the carbon or nitrogen state is critically negative at line 207 in ``CNPrecisionControlMod.F90``, which is a subroutine call :: call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%leafc_patch(bounds%begp:bounds%endp), & @@ -72,7 +301,6 @@ So here we know that it is either leaf nitrogen (leafn) or leaf carbon (leafc) t At this point it is useful as a next step to identify the particular patch index and perhaps the pft type that is triggering the error. In this case, the endrun call is already written to provide this information: the patch index and pft type causing the error, along with some other information, are printed in the lines beginning with ``iam``. The ``iam`` value gives the CTSM processor number (this can be obtained in the code via the ``iam`` variable defined in ``spmdMod``). The local patch index is the value of ``p`` in the current patch loop; "local" implies that it refers to this processor's indexing. However, this same value of ``p`` may appear on other processors, since the local indexing on each processor starts with 1. So, to get the unique patch causing the problem, you either need to use the processor's ``iam`` index (there is only one patch with local index 482 on processor 362), or use the global indices printed below the local index. The "global" term here refers to the global index space across all processors (there is only one patch with a global index of 163723 across all processors). See below for how to use the ``get_global_index`` function to translate from local to global indices. If you are writing your own ``endrun`` call, you can get this additional information by specifying the ``subgrid_index`` and ``subgrid_level`` arguments; for example: - :: call endrun(subgrid_index=p, subgrid_level=subgrid_level_patch, msg=errMsg(sourcefile, __LINE__)) @@ -80,7 +308,6 @@ If you are writing your own ``endrun`` call, you can get this additional informa (The ``subgrid_level_patch`` constant, and similar constants for the other subgrid levels, are defined in ``decompMod``, so can be accessed via ``use decompMod, only : subgrid_level_patch``.) You can get this same information without aborting the run via a call to ``write_point_context``, which is also defined in the ``abortutils`` module; e.g.: - :: if (abs(carbon_patch(p)) < ccrit) then @@ -88,7 +315,6 @@ You can get this same information without aborting the run via a call to ``write end if Or, if all you want is the global index of ``p`` for the sake of writing extra diagnostic prints like the example below, then you can use the ``get_global_index`` function defined in ``decompMod``, like: - :: if (abs(carbon_patch(p)) < ccrit) then @@ -96,10 +322,9 @@ Or, if all you want is the global index of ``p`` for the sake of writing extra d p, get_global_index(subgrid_index=p, subgrid_level=subgrid_level_patch) end if -In all of these cases, the output will appear in either the cesm or lnd log file. In the above example, we see that the local patch index is 482 on processor 362 and the global patch index is 163723. From there, one can use this patch index to write out variables that are used in updating leafc, for example, leafc is updated a number of times in CNCStateUpdate1Mod.F90. +In all of these cases, the output will appear in either the cesm or lnd log file. In the above example, we see that the local patch index is 482 on processor 362 and the global patch index is 163723. From there, one can use this patch index to write out variables that are used in updating leafc, for example, leafc is updated a number of times in ``CNCStateUpdate1Mod.F90``. There are two equivalent methods to write a conditional statement to provide more output for the problem patch within a loop over all patches. The first method is to translate the local index to a global index: - :: use decompMod, only : get_global_index, subgrid_level_patch @@ -110,7 +335,6 @@ There are two equivalent methods to write a conditional statement to provide mor end if The second method is to use the local index along with the processor number: - :: use spmdMod, only : iam @@ -122,10 +346,13 @@ The second method is to use the local index along with the processor number: By placing these write statements in the code, one can get a sense of how leafc is evolving toward a negative state and why. This is a very complex example of troubleshooting. To make a long story short, as described `here `_, the error turned out to be caused by a few lines in the phenology code that weren't handling a 20 minute time step properly, thus an actual bug in the code. This was also a good example of where a much less computationally expensive land-only simulation was able to be used for debugging instead of the orginal expensive fully-coupled simulation. -Another method of troubleshooting is to use the ``point_of_interest`` module. +Another method of troubleshooting is to :ref:`Use the point_of_interest module`. + +.. _Use the point_of_interest module: +===================================================================================================== Use the point_of_interest module --------------------------------- +===================================================================================================== It is common, when debugging, to want to print the values of various variables for all patches or columns of certain landunit types within a certain grid cell of interest. For example, one might be able to identify a certain grid cell with an erroneous value for a particular history field variable (e.g., GPP) using for example ncview. Once the latitude and longitude of this grid cell has been determined, the point_of_interest module (``src/utils/point_of_interest.F90``) helps create the logical functions needed to do this. This module is compiled into every CTSM build, but is not invoked by default. To use it @@ -159,8 +386,9 @@ Here are some other suggestions on how to track down a problem encountered while #. *Run a simpler case* #. *Run with a debugger* +===================================================================================================== Run with a smaller set of processors ------------------------------------- +===================================================================================================== One way to simplify the system is to run with a smaller set of processors. You will need to clean the setup and edit ``env_mach_pes.xml``. For example, to run with four processors: :: @@ -171,8 +399,9 @@ One way to simplify the system is to run with a smaller set of processors. You w Another recommended simplification is to run without threading, so set the NTHRDS for each component to "1" if it isn't already. Sometimes, multiprocessing problems require a certain number of processors before they occur so you may not be able to debug the problem without enough processors. But, it's always good to reduce it to as low a number as possible to make it simpler. For threading problems you may have to have threading enabled to find the problem, but you can run with 1, 2, or 3 threads to see what happens. +===================================================================================================== Run in serial mode with a single processor ------------------------------------------- +===================================================================================================== Simplifying to one processor removes all multi-processing problems and makes the case as simple as possible. If you can enable ``MPILIB=mpi-serial`` you will also be able to run interactively rather than having to submit to a job queue, which sometimes makes it easier to run and debug. If you can use ``MPILIB=mpi-serial`` you can also use threading, but still run interactively in order to use more processors to make it faster if needed. :: @@ -190,18 +419,21 @@ Simplifying to one processor removes all multi-processing problems and makes the # Then build your case # And finally run, by running the *.run script interactively +===================================================================================================== Run at a lower resolution -------------------------- +===================================================================================================== If you can create a new case running at a lower resolution and replicate the problem it may be easier to solve. This of course requires creating a whole new case, and trying out different lower resolutions. +===================================================================================================== Run a simpler case ------------------- +===================================================================================================== Along the same lines, you might try running a simpler case, trying another compset with a simpler setup and see if you can replicate the problem and then debug from that simpler case. Again, of course you will need to create new cases to do this. +===================================================================================================== Run with a debugger -------------------- +===================================================================================================== Another suggestion is to run the model with a debugger such as: ``ddt``, ``dbx``, ``gdb``, or ``totalview``. Often to run with a debugger you will need to reduce the number of processors as outlined above. Some debuggers such as ``dbx`` will only work with one processor, while more advanced debuggers such as ``totalview`` can work with both MPI tasks and OMP threads. Even simple debuggers though can be used to query core files, to see where the code was at when it died (for example using the ``where`` in ``dbx`` for a core file can be very helpful. For help in running with a debugger you will need to contact your system administrators for the machine you are running on. diff --git a/doc/source/users_guide/working-with-documentation/common-docs-errors.md b/doc/source/users_guide/working-with-documentation/common-docs-errors.md index 746b470f2b..1a1410db31 100644 --- a/doc/source/users_guide/working-with-documentation/common-docs-errors.md +++ b/doc/source/users_guide/working-with-documentation/common-docs-errors.md @@ -18,6 +18,10 @@ You tried to build the documentation using our container (`./build_docs ... -d`) - {ref}`bld-prev-docs-mac` - {ref}`bld-prev-docs-windows` +### "Failed to fetch object" + +This can happen if you are trying to build from within a git worktree. The simplest solution is to clone a fresh copy of your working branch somewhere else and try from there. + (common-rst-errors)= ## Common docs errors: reStructuredText @@ -187,4 +191,13 @@ If you're sure the label you referenced actually exists, this probably means you ### "WARNING: malformed hyperlink target" -You may have forgotten the trailing `:` on a label line. \ No newline at end of file +You may have forgotten the trailing `:` on a label line. + +### "WARNING: Title underline too short" + +reStructuredText is just being difficult. It KNOWS that when you did something like this +```reStructuredText +Tips for working with reStructuredText +=================================== +``` +you meant to indicate that was a section header, but it's going to make you extend those equal signs (or hyphens or whatever) all the way out to match (or exceed) the length of the line above. diff --git a/doc/source/users_guide/working-with-documentation/converting-between-md-and-rst.md b/doc/source/users_guide/working-with-documentation/converting-between-md-and-rst.md new file mode 100644 index 0000000000..0cc7221910 --- /dev/null +++ b/doc/source/users_guide/working-with-documentation/converting-between-md-and-rst.md @@ -0,0 +1,56 @@ +(converting-between-md-and-rst)= + +# Converting between Markdown and reStructuredText + +You may find yourself wanting to convert a Markdown file to a reStructuredText file or vice versa. [`pandoc`](https://pandoc.org/) is a command-line utility that can do this for you, or at least get you something that's most of the way there. Installation instructions can be found [here](https://pandoc.org/installing.html), but it's pretty complicated. An easier alternative is to use the online demo page [here](https://pandoc.org/try/): + +1. Paste the contents of the file into the text box on the left. +1. Select the correct file types in the "from" and "to" menus (just use plain "Markdown", not one of the other flavors, unless you've copied something in one of those other flavors—e.g., if you've copied Markdown from a GitHub wiki page). +1. **Make sure "Preserve breaks" is selected, not "Auto wrap"**—see [style guide](#ctsm-docs-style-guide). +1. Click "Convert". You will be given the results of the conversion on the right side of the page. +1. Copy and paste that into a new file with the new extension. + +Note that `pandoc` doesn't support [MyST Markdown](https://mystmd.org/guide/quickstart-myst-markdown), the special flavor of Markdown we support in our docs. Thus, if you're converting a Markdown file from our docs to reStructuredText, there may be some MyST Markdown left over. E.g.: + +``` +(common-docs-errors)= + +# Common doc build errors and how to handle them + +(common-doc-builder-errors)= + +## Common docs errors: doc-builder + +### "RuntimeError: No compatible container software found: docker, podman" + +You tried to build the documentation using our container (`./build_docs ... -d`) but didn't have any software running that could handle the container. Try again after starting up container software according to the instructions for your platform: +- {ref}`bld-prev-docs-casper` **(recommended)** +- {ref}`bld-prev-docs-mac` +- {ref}`bld-prev-docs-windows` +``` + +becomes: + +```reStructuredText +(common-docs-errors)= + +Common doc build errors and how to handle them +============================================== + +(common-doc-builder-errors)= + +Common docs errors: doc-builder +------------------------------- + +"RuntimeError: No compatible container software found: docker, podman" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You tried to build the documentation using our container (``./build_docs ... -d``) but didn't have any software running that could handle the container. Try again after starting up container software according to the instructions for your platform: +- {ref}\ ``bld-prev-docs-casper`` **(recommended)** +- {ref}\ ``bld-prev-docs-mac`` +- {ref}\ ``bld-prev-docs-windows`` +``` + +The labels `(common-docs-errors)=` and `(common-doc-builder-errors)=` will need to be manually converted to their [reStructuredText equivalents](#rst-cross-references) `.. _common-docs-errors:` and `.. _common-doc-builder-errors:`, respectively. + +This can also happen when converting in the other direction, from reStructuredText to Markdown. In that case, however, there are tools that can convert from reStructuredText to MyST Markdown specifically. See the command-line tool [`rst-to-myst`](https://rst-to-myst.readthedocs.io/en/latest/) and the [MySTyc website](https://astrojuanlu.github.io/mystyc/), although at the time of writing the latter wasn't working. diff --git a/doc/source/users_guide/working-with-documentation/docs-style-guide.md b/doc/source/users_guide/working-with-documentation/docs-style-guide.md index 448481630d..ae9c30c72b 100644 --- a/doc/source/users_guide/working-with-documentation/docs-style-guide.md +++ b/doc/source/users_guide/working-with-documentation/docs-style-guide.md @@ -1,8 +1,8 @@ -(docs-style-guide)= +(ctsm-docs-style-guide)= # Documentation style guide - Please don't add manual line breaks when writing text, as this harms searchability. (Note that it's fine to do this in multi-line math blocks.) For more information, see [here](https://github.com/ESCOMP/CTSM/issues/2135#issuecomment-1764999337). -- You can write the degree symbol ° with Opt-Shift-8 on Mac or Alt+0176 on Windows, or you can copy it from here. Note that this is different from the [masculine ordinal indicator](https://en.wikipedia.org/wiki/Ordinal_indicator) º (typed with Opt-0 on Mac). This is much cleaner and more searchable than using RestructuredText syntax to write a superscript-o! +- You can write the degree symbol ° with Opt-Shift-8 on Mac or Alt+0176 on Windows, or you can copy it from here. Note that this is different from the [masculine ordinal indicator](https://en.wikipedia.org/wiki/Ordinal_indicator) (typed with Opt-0 on Mac). This is much cleaner and more searchable than using RestructuredText syntax to write a superscript-o! - Whenever possible, please give equations meaningful labels. E.g., for [eq. 2.26.2](https://escomp.github.io/ctsm-docs/versions/release-clm5.0/html/tech_note/Crop_Irrigation/CLM50_Tech_Note_Crop_Irrigation.html#equation-25-2), `:label: gdds_for_cfts` would be better than `:label: 25.2`. Numeric labels become obsolete—as you can see in that example!—whenever new equations and/or sections are added. (Note that the equation numbering in the rendered HTML is automatic.) - Tables defined with the [:table: directive](https://docutils.sourceforge.io/docs/ref/rst/directives.html#table) can be annoying because they're very sensitive to the cells inside them being precisely the right widths, as defined by the first `====` strings. If you don't get the widths right, you'll see "Text in column margin" errors. Instead, define your tables using the `:list-table:` directive. diff --git a/doc/source/users_guide/working-with-documentation/embed-example-markdown.md b/doc/source/users_guide/working-with-documentation/embed-example-markdown.md new file mode 100644 index 0000000000..01b966afb0 --- /dev/null +++ b/doc/source/users_guide/working-with-documentation/embed-example-markdown.md @@ -0,0 +1,10 @@ +--- +orphan: true +--- + +Everything in this paragraph is just the contents of +`doc/source/users_guide/working-with-documentation/embed-example-markdown.md`. It's in the same directory +as the "Tips for working with Markdown" source file, so we only had to specify the +filename. If it were in a different directory, we would specify the path relative to "Tips for +working with Markdown". (Note that this file does NOT follow the "no line breaks within +paragraphs" style convention; this is purely for readability of the embedded text.) diff --git a/doc/source/users_guide/working-with-documentation/embed-example-python.py b/doc/source/users_guide/working-with-documentation/embed-example-python.py new file mode 100644 index 0000000000..68641beb85 --- /dev/null +++ b/doc/source/users_guide/working-with-documentation/embed-example-python.py @@ -0,0 +1,6 @@ +""" +This is just an example Python file that will be literalinclude'ed +""" + +print("Hello world") +my_list = ["foo", "bar"] diff --git a/doc/source/users_guide/working-with-documentation/embed-example-rst.rst b/doc/source/users_guide/working-with-documentation/embed-example-rst.rst new file mode 100644 index 0000000000..8a8de1fbcb --- /dev/null +++ b/doc/source/users_guide/working-with-documentation/embed-example-rst.rst @@ -0,0 +1,7 @@ +Everything in this paragraph is just the contents of +``doc/source/users_guide/working-with-documentation/embed-example-rst.rst``. It's in the same +directory as the "Tips for working with reStructuredText" source file, so we only had to +specify the filename. If it were in a different directory, we would specify the path +relative to "Tips for working with reStructuredText". (Note that this file does NOT follow +the "no line breaks within paragraphs" style convention; this is purely for readability of +the embedded text.) diff --git a/doc/source/users_guide/working-with-documentation/esbonio-sphinx-buildcmd.png b/doc/source/users_guide/working-with-documentation/esbonio-sphinx-buildcmd.png new file mode 100644 index 0000000000..80a0006a1d --- /dev/null +++ b/doc/source/users_guide/working-with-documentation/esbonio-sphinx-buildcmd.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11f7d6821528a9b39a6de0a668f7b91a84ef2709d6276d68a4204258bb2b1e67 +size 15881 diff --git a/doc/source/users_guide/working-with-documentation/index.rst b/doc/source/users_guide/working-with-documentation/index.rst index 50735b4307..7bb4755bee 100644 --- a/doc/source/users_guide/working-with-documentation/index.rst +++ b/doc/source/users_guide/working-with-documentation/index.rst @@ -13,9 +13,11 @@ Working with CTSM Documentation bld-prev-docs-casper.md bld-prev-docs-mac.md bld-prev-docs-windows.md + vscode-doc-editing-setup.md docs-style-guide.md tips-for-working-with-markdown.md tips-for-working-with-rst.rst + converting-between-md-and-rst.md common-docs-errors.md building-docs-multiple-versions.rst building-docs-original-wiki.md diff --git a/doc/source/users_guide/working-with-documentation/tips-for-working-with-markdown.md b/doc/source/users_guide/working-with-documentation/tips-for-working-with-markdown.md index 8fdd7339cf..f22a6b68d4 100644 --- a/doc/source/users_guide/working-with-documentation/tips-for-working-with-markdown.md +++ b/doc/source/users_guide/working-with-documentation/tips-for-working-with-markdown.md @@ -104,3 +104,68 @@ Here's a hint. Synonyms you can put in the `{}` instead of `hint` include `impor ```{hint} Here's a hint. Synonyms you can put in the `{}` instead of `hint` include `important` and `tip`. ``` + +## Markdown: Embedding a different Markdown file +It can be useful to embed one Markdown file within another. This is done in this documentation documentation, for instance, to embed `doc/source/users_guide/working-with-documentation/embed-build-cmd.md` on three different pages. + +As an example, here's what an embedding looks like: +~~~ +That becomes: +```{include} embed-example-markdown.md +``` +~~~ + +That becomes: +```{include} embed-example-markdown.md +``` + +See [the MyST Markdown documentation for the "include" directive](https://mystmd.org/guide/directives#directive-include) for more information. + +You can also embed literal contents of any file without the rendering: +~~~ +That becomes the literal contents: +```{literalinclude} embed-example-markdown.md +``` +~~~ + +That becomes the literal contents: +```{literalinclude} embed-example-markdown.md +``` + +(The first three lines are to indicate to Sphinx that it's okay for that file to not be included in any Table of Contents; i.e., to suppress the `WARNING: document isn't included in any toctree [toc.not_included]` build message.) + +You can also get fancy: +~~~ +```{literalinclude} embed-example-python.py +:language: python +:linenos: +``` +~~~ + +Becomes (note syntax highlighting): + +```{literalinclude} embed-example-python.py +:language: python +:linenos: +``` + +And +~~~ +```{literalinclude} embed-example-python.py +:language: python +:linenos: +:start-at: print +:lineno-match: +``` +~~~ + +Becomes: + +```{literalinclude} embed-example-python.py +:language: python +:linenos: +:start-at: print +:lineno-match: +``` + +See [the MyST Markdown documentation for the `include` directive](https://mystmd.org/guide/directives#directive-include) for more information (all options apply to `literalinclude` as well). \ No newline at end of file diff --git a/doc/source/users_guide/working-with-documentation/tips-for-working-with-rst.rst b/doc/source/users_guide/working-with-documentation/tips-for-working-with-rst.rst index c356064ab4..12dda6d1f8 100644 --- a/doc/source/users_guide/working-with-documentation/tips-for-working-with-rst.rst +++ b/doc/source/users_guide/working-with-documentation/tips-for-working-with-rst.rst @@ -150,7 +150,70 @@ There are also a number of built-in admonition types that get their own special +reStructuredText: Embedding a different reStructuredText file +------------------------------------------------------------- + +.. code-block:: reStructuredText + + .. include:: embed-example-rst.rst + +Becomes: + +.. include:: embed-example-rst.rst + +You can also embed literal contents of any file without the rendering: + +.. code-block:: reStructuredText + + .. literalinclude:: embed-example-rst.rst + :language: restructuredtext + +That becomes the literal contents (note syntax highlighting): + +.. literalinclude:: embed-example-rst.rst + :language: restructuredtext + +You can also get fancy: + +.. code-block:: reStructuredText + + .. literalinclude:: embed-example-python.py + :language: python + :start-at: print + :linenos: + :lineno-match: + +Becomes: + +.. literalinclude:: embed-example-python.py + :language: python + :start-at: print + :linenos: + :lineno-match: + +See `the Sphinx documentation `_ for more options to the ``literalinclude`` directive. + + +reStructuredText: Text superscripts and subscripts +-------------------------------------------------------------- + +Note that these instructions apply to text (i.e., not in inline or block math). + +**Superscripts** + +- Incorrect: ``Fe:sup:`3+``` becomes Fe:sup:`3+` +- Incorrect: ``Fe :sup:`3+``` becomes Fe :sup:`3+` (note extraneous space) +- Correct: ``Fe\ :sup:`3+``` becomes Fe\ :sup:`3+` + +**Subscripts** + +- Incorrect: ``CO:sub:`2``` becomes CO:sub:`2` +- Incorrect: ``CO :sub:`2``` becomes CO :sub:`2` (note extraneous space) +- Correct: ``CO\ :sub:`2``` becomes CO\ :sub:`2` + + + reStructuredText: Common error messages and how to handle them -------------------------------------------------------------- -See :ref:`common-rst-errors`. \ No newline at end of file +See :ref:`common-rst-errors`. diff --git a/doc/source/users_guide/working-with-documentation/vscode-doc-editing-setup.md b/doc/source/users_guide/working-with-documentation/vscode-doc-editing-setup.md new file mode 100644 index 0000000000..4a531b7647 --- /dev/null +++ b/doc/source/users_guide/working-with-documentation/vscode-doc-editing-setup.md @@ -0,0 +1,92 @@ +(vscode-docs-editing-setup)= + +# Recommended setup for editing docs in VS Code + +## Set up Python +The Python packages needed for this setup are listed at `doc/ctsm-docs_container/requirements.txt`. If you recently installed [the `ctsm_pylib` conda environment](https://escomp.github.io/CTSM/users_guide/using-clm-tools/using-ctsm-pylib.html), they will already be included there. Check like so: +```shell +conda activate ctsm_pylib +pip show myst-parser +``` + +If you see `WARNING: Package(s) not found: myst-parser`, you'll need to install the doc-building Python modules. With your conda environment activated (or in whatever other environment you want to use), from the top level of a CTSM checkout, do: +```shell +pip install -r doc/ctsm-docs_container/requirements.txt +``` + +You will need to provide the path to your Python binary in various VS Code settings detailed below. You can get that with `which python` (after loading the relevant conda environment, if needed). + +## Install required [VS Code extensions](https://code.visualstudio.com/docs/getstarted/extensions) + +1. [Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python) +2. [MyST-Markdown](https://marketplace.visualstudio.com/items?itemName=ExecutableBookProject.myst-highlight) +3. [Esbonio](https://marketplace.visualstudio.com/items?itemName=swyddfa.esbonio) + +## Change VS Code settings for Esbonio extension +```{important} +This setup will work only if you've opened the top level of a CTSM checkout as a [VS Code workspace](https://code.visualstudio.com/docs/editing/workspaces/workspaces). +``` + +Open VS Code's settings. (To restrict the list to only settings related to this setup, you can access the Esbonio settings via the gear icon on its item in the Extensions menu.) You're going to change a few things, but note that VS Code can have up to three tabs (representing "scopes") across the top of the Settings page: User, Remote \[SSH: remotename], and Workspace. Below, we'll explain which setting should be set in which scope(s). Keep in mind that scopes going left to right get more specific, and a setting in a later (rightward) scope will always override the same setting in an earlier (leftward) scope. + +### Build command +`Esbonio > Sphinx: Build Command` in the Settings GUI: This is an annoying one. We want to tell it to use `sphinx-build doc/source ${defaultBuildDir} -c doc/doc-builder`, but each word there has to be its own element in a list. + +![](esbonio-sphinx-buildcmd.png) + +It might be easier to open your VS Code's `settings.json` file(s) for this. You'd simply add: +```json +"esbonio.sphinx.buildCommand": [ + "sphinx-build", + "doc/source", + "${defaultBuildDir}", + "-c", + "doc/doc-builder" +] +``` + +Note that it needs to be proper JSON syntax, though. So in context it looks like this if it's at the end of the file (your indentation may vary): +```json +"chat.disableAIFeatures": true, +"esbonio.sphinx.buildCommand": [ + "sphinx-build", + "doc/source", + "${defaultBuildDir}", + "-c", + "doc/doc-builder" +] +} +``` +Note the comma at the end of the preceding line, and the curly bracket on the very last line of the file. + +As far as which scope to use: If you're always or usually going to be using Esbonio to preview docs for CTSM, you should put this in the User scope. You can open your User `settings.json` by searching in the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) for `user settings json`. For other projects using Esbonio, you will be able to set a Workspace-level `esbonio.sphinx.buildCommand` to override your User default. + +### Python command +`Esbonio > Sphinx: Python Command`. Do not get this confused with `Esbonio > Sphinx: Build Command` from above, or the similar `Esbonio > Server: Python Command`. This one you're going to *have* to edit in `settings.json`: +```json +"esbonio.sphinx.pythonCommand": "/path/to/your/python", +``` +The path is what you got from `which python` above. See the note about proper JSON syntax in "Build command" above. + +Which settings scope? +- If you're working on your local machine, User: Search in the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) for `user settings json`. +- If you're working on a remote machine, Remote: Search in the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) for `remote settings json`. + +### Finishing up +Once you've made those settings changes, reload the window (search `reload window` in the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette)). + +## Previewing +This will take a while the first time you build the previews during a session. +1. (Optional but recommended, at least the first time) In the View menu, select Output. In the drop-down menu at the top right of the Output panel, select Esbonio. +2. Open a documentation source file (.rst or .md). +3. Search `Esbonio: Preview Documentation in Split Window` (or any subset of those words) in the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette). Select it and this should open a pane next to the documentation source file that is initially empty. +4. If you opened the Esbonio Output panel (or open it now), you'll see it working. This can take a while, especially if it's doing a clean build (such as the first time you do this). +5. Once it's done, the preview pane should fill in. + +When you make changes to and save a documentation source file, Esbonio will re-generate the preview for that file. This should be relatively quick, since it's not doing a clean build—just a new build of that file in particular. However, you may need to close and re-open the preview pane before you see your changes. Also, there are some types of changes you can make to one file that will affect *other* files (such as changing a section label that is cross-referenced in a different file). Esbonio will not know to rebuild those other files. To force a clean build, try the `Esbonio: Restart Language Server` command in the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette). Failing that, you can try deleting the directory referenced in the "The HTML pages are in" message printed in the Esbonio Output log. + +Some other tips: +- If you see long lines in the editor that require you to scroll far to the right, search the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) for "word wrap" and select `View: Toggle Word Wrap`. These long lines are intentional (see [style guide](#ctsm-docs-style-guide)). +- Once the preview is ready, you can scroll in either the source file or the preview and they will stay approximately in sync with each other. +- You should be able to open other source files and get their preview instantly. +- More info on features can be found on the [Esbonio VS Code Extension page](https://marketplace.visualstudio.com/items?itemName=swyddfa.esbonio) diff --git a/python/README.python_pkgs.rst b/python/README.python_pkgs.md old mode 100644 new mode 100755 similarity index 59% rename from python/README.python_pkgs.rst rename to python/README.python_pkgs.md index 59a9d97c8d..78aeebf505 --- a/python/README.python_pkgs.rst +++ b/python/README.python_pkgs.md @@ -1,32 +1,32 @@ -.. sectnum:: +# Requirements to consider for python packages to be included for CTSM python tools -.. contents:: +Any added dependencies should be discussed and approved by the CTSM-software team. Criteria for evaluation of third-party packages include: -===================================================================================== - Requirements to consider for python packages to be included for CTSM python tools -===================================================================================== +- How much value does this package provide to us beyond what we could get without it? -Requirements for CTSM python tools: +- How difficult it is to install this package (including: how much does this complicate / slow down the creation of the conda environment)? -Any added dependencies should be discussed and approved by the CTSM-software team. Criteria for evaluation of third-party packages -include: -- How much value does this package provide to us beyond what we could get without it? -- How difficult it is to install this package (including: how much does this complicate / slow down the creation of the conda -environment)? - How stable is this package? + - How well maintained is this package? + - Are there other packages that are more stable or better maintained that would provide nearly the same level of value? -- Tools that require extra packages should be done in a "contrib" type area out of the main part of tools (this would apply for -advanced plotting capability for example) -- We need to be able to reproduce working conda environments minimally on our test machines (currently derecho and izumi), but also -on any machine that we run CTSM on. If there is a machine that we can run CTSM on that we can't build the conda environments or run -the tools on -- that needs to be fixed. -- We need to tell the user how long to expect the conda environment to load, and give them options if the conda load is taking too -long -- Conda environments need to build robustly even for users who don't have ctsm_pylib loaded in their conda environment + +- Tools that require extra packages should be done in a "contrib" type area out of the main part of tools (this would apply for advanced plotting capability for example) + +- We need to be able to reproduce working conda environments minimally on our test machines (currently derecho and izumi), but also on any machine that we run CTSM on. If there is a machine that we can run CTSM on that we can't build the conda environments or run the tools on, that needs to be fixed. + +- We need to tell the user how long to expect the conda environment to load, and give them options if the conda load is taking too long + +- Conda environments need to build robustly even for users who don't have `ctsm_pylib` loaded in their conda environment + - Currently we won't use conda-lock + - We specify the black version exactly so that black will function identically for all users + - We specify the pylint version exactly because pylint is finicky with version and we need it to work identically for all developers + - We might remove the need for python packages that aren't providing enough utility -Packages where specific versions seem to be required will have the version requirements in a least the >= form if not an exact +- Packages where specific versions seem to be required will have the version requirements in a least the `>=` form if not an exact version + diff --git a/python/ctsm/test/README b/python/ctsm/test/README.md similarity index 64% rename from python/ctsm/test/README rename to python/ctsm/test/README.md index aa4f2e1c9b..f5e0c9c6b5 100644 --- a/python/ctsm/test/README +++ b/python/ctsm/test/README.md @@ -1,23 +1,28 @@ CTSM-specific boiler-plate needed for most unit test modules: -(1) If cime stuff is invoked by these unit tests (directly or - indirectly, then: the first ctsm import statement near the top of - the module should be: +(1) If cime stuff is invoked by these unit tests (directly or indirectly) then, the first ctsm import statement near the top of the module should be: -from ctsm import add_cime_to_path # pylint: disable=unused-import +``` +from ctsm import add_cime_to_path # pylint: disable=unused-import +``` (2) Import the ctsm-specific unit_testing module: +``` from ctsm import unit_testing +``` (3) Allow names that pylint doesn't like: - +``` # Allow names that pylint doesn't like, because otherwise I find it hard # to make readable unit test names # pylint: disable=invalid-name +``` (4) Have a 'main' block at the bottom: - +``` if __name__ == '__main__': unit_testing.setup_for_tests() unittest.main() +``` + diff --git a/src/README.unit_testing b/src/README.unit_testing deleted file mode 100644 index 897e7869ce..0000000000 --- a/src/README.unit_testing +++ /dev/null @@ -1,11 +0,0 @@ -# To run all CTSM unit tests, run the following command: -# -# This reuses the existing 'unit_tests.temp' directory (if present) in -# order to do an incremental rebuild of the unit tests from the last -# time you ran them from this directory. - -# From a standalone CTSM checkout: -../cime/scripts/fortran_unit_testing/run_tests.py --build-dir unit_tests.temp - -# If you are within a full CESM checkout, you would instead do: -# ../../../cime/scripts/fortran_unit_testing/run_tests.py --build-dir unit_tests.temp diff --git a/src/README.unit_testing.md b/src/README.unit_testing.md new file mode 100644 index 0000000000..de9fa66b47 --- /dev/null +++ b/src/README.unit_testing.md @@ -0,0 +1,16 @@ +To run all CTSM unit tests, run the following command: + +This reuses the existing `unit_tests.temp` directory (if present) in +order to do an incremental rebuild of the unit tests from the last +time you ran them from this directory. + +From a standalone CTSM checkout: +``` +../cime/scripts/fortran_unit_testing/run_tests.py --build-dir unit_tests.temp +``` + +If you are within a full CESM checkout, you would instead do: +``` +../../../cime/scripts/fortran_unit_testing/run_tests.py --build-dir unit_tests.temp +``` + diff --git a/tools/contrib/preview_docs_pr b/tools/contrib/preview_docs_pr new file mode 100755 index 0000000000..038951293b --- /dev/null +++ b/tools/contrib/preview_docs_pr @@ -0,0 +1,377 @@ +#!/usr/bin/env python +"""Given a GitHub PR URL, download the code as if it had been merged and then build the docs""" + +import urllib.request +import urllib.error +import json +import re +import os +import sys +import argparse +import subprocess +import time +import zipfile +import stat +import shutil + +# Get default location in which to clone the code +SCRATCH = os.getenv("SCRATCH") +DEFAULT_EXTRACTION_DIR_BASENAME = ( + "preview_docs_pr.{}.{}.pr-{}" # repo owner, repo name, PR number +) +DEFAULT_EXTRACTION_DIR = os.path.join( + SCRATCH if SCRATCH else "", + DEFAULT_EXTRACTION_DIR_BASENAME, +) + +INDENT = 4 * " " + + +def parse_pr_url(url): + """Extract owner, repo, and PR number from a GitHub PR URL.""" + pattern = r"https://github\.com/([^/]+)/([^/]+)/pull/(\d+)" + match = re.match(pattern, url.strip()) + if not match: + raise ValueError(f"Invalid GitHub PR URL: {url}") + owner, repo, pr_number = match.groups() + return owner, repo, int(pr_number) + + +def make_api_call(url, token): + """Helper function to make a GitHub API call""" + headers = { + "Accept": "application/vnd.github+json", + "X-GitHub-Api-Version": "2022-11-28", + } + if token: + headers["Authorization"] = f"Bearer {token}" + + req = urllib.request.Request(url, headers=headers) + with urllib.request.urlopen(req) as resp: + return json.loads(resp.read().decode()) + + +def fetch_pr_info(owner, repo, pr_number, token=None): + """Fetch PR metadata from the GitHub API.""" + + # Get overall PR info + pr_url = f"https://api.github.com/repos/{owner}/{repo}/pulls/{pr_number}" + pr_info = make_api_call(pr_url, token) + + # Get files touched by PR + files_url = pr_url + "/files" + pr_files = make_api_call(files_url, token) + + return pr_info, pr_files + + +def fetch_pr_info_with_mergeability(owner, repo, pr_number, token=None, retries=5): + """Fetch the PR info, retrying as needed if mergeability hasn't yet been computed""" + wait_time = 10 # seconds + for attempt in range(retries): + pr, files = fetch_pr_info(owner, repo, pr_number, token) + if pr["state"] != "open" or pr.get("mergeable") is not None: + return pr, files + print( + f" Mergeability not yet computed, waiting {wait_time} seconds and retrying" + f"({attempt + 1}/{retries})..." + ) + time.sleep(wait_time) + raise RuntimeError(f"Mergeability still unknown after {retries} retries.") + + +def pick_ref(pr): + """ + Choose the best ref to download, with explanation. + """ + state = pr["state"] + merge_commit_sha = pr.get("merge_commit_sha") + mergeable = pr.get("mergeable") + + # If the PR can't be merged, we can't preview what it'd look like after merge. + # Note that "mergeable" only refers to whether there are Git conflicts; it doesn't "know" + # anything about PR tests that are passing or failing. + if not mergeable: + print( + "PR branch has merge conflicts, so merged docs can't be previewed. Exiting." + ) + sys.exit(1) + + # If PR was closed without merging, GitHub supposedly nulls out merge_commit_sha, so that + # situation would require special handling. + if state == "closed" and not pr.get("merged_at"): + raise NotImplementedError("PR closed without merge") + + if not merge_commit_sha: + raise RuntimeError("How is this possible?") + + return merge_commit_sha + + +def download_zip(extraction_dir, token, pr_info, merge_commit_sha): + """Download the code as of the merge commit from GitHub""" + print("Downloading zip from GitHub...") + owner, repo, pr_number = pr_info + zip_url = f"https://api.github.com/repos/{owner}/{repo}/zipball/{merge_commit_sha}" + headers = { + "Accept": "application/vnd.github+json", + "X-GitHub-Api-Version": "2022-11-28", + } + if token: + headers["Authorization"] = f"Bearer {token}" + req = urllib.request.Request(zip_url, headers=headers) + pr_number = pr_info[2] + zip_path = os.path.join(extraction_dir, f"pr-{pr_number}.zip") + try: + with urllib.request.urlopen(req) as resp, open(zip_path, "wb") as f: + f.write(resp.read()) + except urllib.error.HTTPError as e: + raise RuntimeError(f"Failed to download zip from {zip_url}: {e}") from e + return zip_path + + +def extract_zip(extraction_dir, zip_path, overwrite): + """Unzip the code""" + try: + with zipfile.ZipFile(zip_path, "r") as zf: + # GitHub zips have a single top-level folder like "owner-repo-/" + top_level = zf.namelist()[0].split("/")[0] + extracted_path = os.path.join(extraction_dir, top_level) + + # If it already exists, it would be nice to skip re-extracting. But we would want to do + # a git reset to make sure it's actually at the right commit, and unfortunately the + # downloaded ZIP file doesn't include the git history. So instead, we delete the + # existing one first. + if os.path.exists(extracted_path): + if not overwrite: + raise FileExistsError( + "Clone directory exists; add -o/--overwrite to overwrite:" + f"'{extracted_path}'" + ) + print(f"Deleting existing clone dir: '{extracted_path}'") + shutil.rmtree(extracted_path) + + # Unzip + print("Unzipping...") + zf.extractall(extraction_dir) + os.remove(zip_path) + except: + os.remove(zip_path) + raise + + print(f"Code downloaded to: '{extracted_path}'") + return extracted_path + + +def download_pr_code(pr_url, extraction_dir, overwrite, token=None): + """Download code as if the pull request had been merged""" + # Fetch PR information via GitHub API + pr_info = parse_pr_url(pr_url) + pr, files = fetch_pr_info_with_mergeability(*pr_info, token) + + # Get the ref to download + merge_commit_sha = pick_ref(pr) + + if not os.path.exists(extraction_dir): + os.makedirs(extraction_dir) + + # Download the zip (follows redirects automatically) + zip_path = download_zip(extraction_dir, token, pr_info, merge_commit_sha) + + # Unzip + code_dir = extract_zip(extraction_dir, zip_path, overwrite) + + return code_dir, files, pr_info + + +def build_docs(code_dir, files, verbose, pr_info): + """Build the documentation""" + os.chdir(code_dir) + + # Handle verbosity for subprocess calls + if verbose: + stdout = None + else: + stdout = subprocess.DEVNULL + + # Set up so that git lfs works + set_up_git(pr_info, stdout) + + print("Getting submodules...") + os.chmod(path := "bin/git-fleximod", os.stat(path).st_mode | stat.S_IXUSR) + subprocess.check_call([path, "update"], stdout=stdout) + + print("Building docs...") + os.chdir("doc") + os.chmod(path := "./build_docs", os.stat(path).st_mode | stat.S_IXUSR) + output = [] + cmd = [path, "-b", "_build", "-d", "-c"] + if verbose: + cmd.append("--verbose") + with subprocess.Popen( + cmd, + cwd=os.path.join(code_dir, "doc"), + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, # Merge stderr into stdout + text=True, + bufsize=1, # Line buffering + env={**os.environ, "PYTHONUNBUFFERED": "1"}, # Force unbuffered output + ) as process: + for line in process.stdout: + print(line, end="") # Print to screen + output.append(line) # Save for later + output = "".join(output) + if output and os.path.exists(os.path.join("_build", "html", "index.html")): + print_files_msg(code_dir, files) + + +def set_up_git(pr_info, stdout): + """Initialize a git repo in the downloaded code so that git lfs works right""" + + owner, repo, _ = pr_info + remote_url = f"https://github.com/{owner}/{repo}.git" + subprocess.check_call(["git", "init", "-b", "preview-docs"], stdout=stdout) + subprocess.check_call(["git", "remote", "add", "origin", remote_url], stdout=stdout) + subprocess.check_call(["git", "add", "-A"], stdout=stdout) + subprocess.check_call( + [ + "git", + "commit", + "-m", + "PR snapshot for docs preview", + ], + stdout=stdout, + ) + + +def print_files_msg(code_dir, files): + """Print a message about the directly-affected files""" + build_dir = os.path.join(code_dir, "doc", "_build") + html_dir = os.path.join(build_dir, "html") + print(f"\nThe updated files are in {html_dir}") + print("Doc source files directly touched (not deleted) by PR:") + for f_dict in files: + f = f_dict["filename"] + # Slashes here are platform-independent, because f is returned from GitHub API call + # Skip deleted or otherwise nonexistent files + full_path = os.path.join(code_dir, f) + if f_dict["status"] == "removed" or not os.path.exists(full_path): + continue + + # Skip files not in doc source + if not f.startswith("doc/source/"): + continue + + # Get string to print + f_print = "/".join(f.split("/")[2:]) # Remove leading doc/source/ + root, extension = os.path.splitext(f_print) + basename = f.split("/")[-1] # pylint: disable=use-maxsplit-arg + if extension in [".rst", ".md"]: + # These types get converted to HTML + f_print = root + ".html" + assert os.path.exists(os.path.join(html_dir, f_print)) + elif os.path.exists(os.path.join(html_dir, "_images", basename)): + # Image files get put in _build/html/_images/ + f_print = os.path.join("_images", basename) + else: + f_print = "[NOT SURE WHERE THIS IS BUILT TO] " + f_print + print(INDENT + f_print) + print( + "Note that changes to these or other files may indirectly affect other doc files!" + " For example, if one of these files is a new/changed image, or a new/changed text" + " file that's `include`d somewhere, or a text file with an updated label that's cross-" + "referenced elsewhere. Or if a file outside doc/source/ that's `include`d in a doc file" + " got changed." + ) + + +def parse_args(): + """Parse arguments""" + parser = argparse.ArgumentParser( + description="Given a GitHub PR URL, download the merged version and build the docs." + ) + + parser.add_argument( + "pr_url", + help="GitHub pull request URL", + type=str, + ) + + extraction_dir_help_default = DEFAULT_EXTRACTION_DIR.format( + "REPO_OWNER", "REPO", "PR_NUM" + ) + parser.add_argument( + "--dir", + "--extraction-dir", + dest="extraction_dir", + help=( + "Directory to download and extract code versions to." + f" Default: {extraction_dir_help_default}" + ), + type=str, + default=None, + ) + + parser.add_argument( + "-o", + "--overwrite", + help="Overwrite existing clone dir, if any.", + action="store_true", + ) + + parser.add_argument( + "-v", + "--verbose", + help="Verbose output, including for build_docs command.", + action="store_true", + ) + + args = parser.parse_args(sys.argv[1:]) + + # Get clone dir, if not provided + pr_info = parse_pr_url(args.pr_url) + if not args.extraction_dir: + args.extraction_dir = DEFAULT_EXTRACTION_DIR.format(*pr_info) + elif os.path.abspath(args.extraction_dir) == os.getcwd(): + args.extraction_dir = os.path.join( + os.getcwd(), DEFAULT_EXTRACTION_DIR_BASENAME.format(*pr_info) + ) + print(f"Will clone to '{args.extraction_dir}'") + + # Check that clone dir parent exists + args.extraction_dir = os.path.abspath(args.extraction_dir) + clone_parent = os.path.dirname(args.extraction_dir) + if not os.path.exists(clone_parent): + raise NotImplementedError( + f"Clone parent directory does not exist: '{clone_parent}'" + ) + + # Check that clone dir parent is not (in) a git repo + result = subprocess.run( + ["git", "-C", clone_parent, "rev-parse", "--is-inside-work-tree"], + check=False, + capture_output=True, + ) + if not result.returncode: + raise RuntimeError( + "Clone parent directory is (in) a git repo, which would cause git-fleximod problems: " + f"'{clone_parent}'" + ) + + return args + + +def main(): + """Main function""" + args = parse_args() + # GitHub personal access tokens are currently not supported, but the code is all there. Just + # need to think about how to implement them in a way that will prevent people from putting their + # secrets into their shell history. + code_dir, files, pr_info = download_pr_code( + args.pr_url, args.extraction_dir, args.overwrite, token=None + ) + build_docs(code_dir, files, args.verbose, pr_info) + + +if __name__ == "__main__": + main() diff --git a/tools/mkmapgrids/README b/tools/mkmapgrids/README.md similarity index 81% rename from tools/mkmapgrids/README rename to tools/mkmapgrids/README.md index cc6d2cb644..2b455ae289 100644 --- a/tools/mkmapgrids/README +++ b/tools/mkmapgrids/README.md @@ -2,21 +2,23 @@ $CTSMROOT/tools/mkmapgrids/README June08/2018 NCL script to create a SCRIP grid file for a regular lat/lon grid. -To use the script, set the following environment variables - -Required (or defaults to a single point over Boulder Colorado) +To use the script, set the following environment variables: +Required (or defaults to a single point over Boulder Colorado): +``` PTNAME ! name of your grid S_LAT ! Southern latitude corner N_LAT ! Northern latitude corner E_LON ! Eastern longitude corner W_LON ! Western longitude corner +``` Optional: - +``` NX ! Number of grid points along longitude (default 1) NY ! Number of grid points along latitude (default 1) IMASK ! 0 or 1, mask to use if all points are active or not (default active) PRINT ! TRUE/FALSE do extra verbose printing or not (default FALSE) GRIDFILE ! Output filename +``` diff --git a/tools/mksurfdata_esmf/README.filecopies b/tools/mksurfdata_esmf/README.filecopies.md similarity index 86% rename from tools/mksurfdata_esmf/README.filecopies rename to tools/mksurfdata_esmf/README.filecopies.md index 44c9ef6918..64542cd5d8 100644 --- a/tools/mksurfdata_esmf/README.filecopies +++ b/tools/mksurfdata_esmf/README.filecopies.md @@ -9,19 +9,23 @@ directories as well. I. Files that are IDENTICAL: 1. cesm_share files copied that should be identical to share/src: - +``` shr_kind_mod.F90 shr_const_mod.F90 shr_string_mod.F90 shr_file_mod.F90 - +``` II. Files with differences 1. cesm_share files copied with differences: - shr_sys_mod.F90 - Remove mpi abort and reference to shr_mpi_mod.F90. +``` + shr_sys_mod.F90 # Remove mpi abort and reference to shr_mpi_mod.F90 +``` 2. Files in mksurfdata_esmf - +``` mkvarpar.F90 nanMod.F90 +``` + diff --git a/tools/modify_input_files/README.fsurdat_modifier b/tools/modify_input_files/README.fsurdat_modifier.md similarity index 55% rename from tools/modify_input_files/README.fsurdat_modifier rename to tools/modify_input_files/README.fsurdat_modifier.md index 885227c928..ca0decf9cf 100644 --- a/tools/modify_input_files/README.fsurdat_modifier +++ b/tools/modify_input_files/README.fsurdat_modifier.md @@ -5,7 +5,7 @@ Current applications are limited to the simplest CTSM(SP) mode, so bgc, fire, urban, vic, lake, transient, and crop-related variables in the fsurdat file remain unchanged. -It differs from modify_singlept_site_neon.py in that the latter specifically +It differs from `modify_singlept_site_neon.py` in that the latter specifically modifies soil properties of single-point surface datasets. It also differs from the subset_data tool in that the latter subsets fsurdat @@ -13,38 +13,51 @@ files to regional or single-point domains; subset_data does include some "modify" functionality when subsetting, but such functionality is more prescriptive in subset_data. In particular: -fsurdat_modifier options subset_data options ------------------------------------ ------------------- -std_elev (user sets STD_ELEV value) uniform-snowpack (sets STD_ELEV to 20) -max_sat_area (user sets FMAX value) cap-saturation (sets FMAX to zero) +|fsurdat_modifier options | subset_data options | +|----------------------------------- | ------------------- | +|std_elev (user sets STD_ELEV value) | uniform-snowpack (sets STD_ELEV to 20)| +|max_sat_area (user sets FMAX value) | cap-saturation (sets FMAX to zero) | Files involved --------------- +``` python/ctsm/modify_input_files/fsurdat_modifier.py python/ctsm/modify_input_files/modify_fsurdat.py tools/modify_input_files/fsurdat_modifier tools/modify_input_files/modify_fsurdat_template.cfg - +``` Instructions ------------ To run on various machines: 1) (Un)load, execute, and activate the following: + 1a) First step to activate conda on your system -1a) Casper: + +- Casper: +``` module unload python module load conda -1a) Izumi: +``` +- Izumi: +``` module load python -1a) Derecho (nothing needs to be done for this step) -1a) Elsewhere (do what's needed to activate conda) -1b) On all systems +``` +- Derecho (nothing needs to be done for this step) +- Elsewhere (do what's needed to activate conda) + +1b) On all systems: +``` ./py_env_create conda activate ctsm_pylib +``` (Use "deactivate" to reverse the latter.) -2) Copy, then modify the configure file named modify_fsurdat_template.cfg, which -contains all the arguments needed by the script. -3) Run the script ./fsurdat_modifier pointing to the copied/modified .cfg file, -e.g. modify_users_copy.cfg + +2) Copy, then modify the configure file named `modify_fsurdat_template.cfg`, which contains all the arguments needed by the script. + +3) Run the script `./fsurdat_modifier` pointing to the copied/modified `.cfg` file, e.g. `modify_users_copy.cfg` +``` ./fsurdat_modifier modify_users_copy.cfg -See modify_fsurdat_template.cfg for required and optional settings. -4) Use the --verbose option to see progress output on your screen +``` +See `modify_fsurdat_template.cfg` for required and optional settings. + +4) Use the `--verbose option` to see progress output on your screen. + diff --git a/tools/modify_input_files/README.mesh_mask_modifier b/tools/modify_input_files/README.mesh_mask_modifier.md similarity index 50% rename from tools/modify_input_files/README.mesh_mask_modifier rename to tools/modify_input_files/README.mesh_mask_modifier.md index b667ebf22f..91404de201 100644 --- a/tools/modify_input_files/README.mesh_mask_modifier +++ b/tools/modify_input_files/README.mesh_mask_modifier.md @@ -1,36 +1,45 @@ mesh_mask_modifier is a tool that modifies mesh_mask files. It reads a mesh_mask file and outputs a modified copy of the same file. -Files involved --------------- +# Files involved +``` python/ctsm/modify_input_files/mesh_mask_modifier.py python/ctsm/modify_input_files/modify_mesh_mask.py tools/modify_input_files/mesh_mask_modifier tools/modify_input_files/modify_mesh_template.cfg +``` +# Instructions -Instructions ------------- To run on various machines: 1) (Un)load, execute, and activate the following: + 1a) First step to activate conda on your system -1a) Casper: + +- Casper: +``` module unload python module load conda -1a) Izumi: +``` +- Izumi: +``` module load python -1a) Derecho (nothing needs to be done -1a) Elsewhere (do what's needed to activate conda) -1b) On all systems +``` +- Derecho (nothing needs to be done) +- Elsewhere (do what's needed to activate conda) + +1b) On all systems: +``` ./py_env_create conda activate ctsm_py +``` (Use "deactivate" to reverse the latter.) -2) Copy, then modify the configure file named modify_mesh_template.cfg, which -contains all the arguments needed by the script. -3) Run the script ./mesh_mask_modifier pointing to the copied/modified -.cfg file, e.g. modify_users_copy.cfg -Example use-case ----------------- +2) Copy, then modify the configure file named `modify_mesh_template.cfg`, which contains all the arguments needed by the script. + +3) Run the script .`/mesh_mask_modifier` pointing to the copied/modified `.cfg` file, e.g. `modify_users_copy.cfg` + +# Example use-case + F-Case, modifying the continental geometry User wants to make the Indian Ocean into grassland. They specify their @@ -38,30 +47,31 @@ own land fraction mask on the CESM 1-degree grid, as well as the area to be specified as grassland in a netcdf file. This has been obtained by modifying the default land fraction of CESM. The file contains two arrays: -- landmask = the new landmask -- mod_lnd_props = set to 1 where the new land surface has been specified -(i.e., where grassland needs to be specified) and zero elsewhere - -This use-case requires modification to the fsurdat and mesh files. To -modify the former, use the modify_fsurdat tool. See that tool for -instructions. Here are the steps to modify the mesh file: - -In your copy of the CTSM (say, ~user/ctsm), go to the appropriate tool: ->>> cd tools/modify_input_files ->>> cp modify_mesh_template.cfg modify_fill_indianocean.cfg +- `landmask` = the new landmask +- `mod_lnd_props` = set to 1 where the new land surface has been specified (i.e., where grassland needs to be specified) and zero elsewhere -Enter the following (or similar) selections in modify_fill_indianocean.cfg: +This use-case requires modification to the fsurdat and mesh files. To modify the former, use the `modify_fsurdat` tool. See that tool for instructions. Here are the steps to modify the mesh file: +In your copy of the CTSM (say, `~user/ctsm`), go to the appropriate tool: +``` +cd tools/modify_input_files +cp modify_mesh_template.cfg modify_fill_indianocean.cfg +``` +Enter the following (or similar) selections in `modify_fill_indianocean.cfg`: +``` mesh_mask_in = /glade/campaign/cesm/cesmdata/cseg/inputdata/share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc mesh_mask_out = fv0.9x1.25_141008_polemod_ESMFmesh_modified.nc landmask_file = .../path_to_your_copy_of/fill_indianocean.nc - +``` Run the tool ->>> ./mesh_mask_modifier modify_fill_indianocean.cfg +``` +./mesh_mask_modifier modify_fill_indianocean.cfg +``` A modified mesh file should appear in the directory where you ran. -Point to this file in your case's env_run.xml in the line that sets -MASK_MESH. If for some reason this fails, hardwire the ocean domain mesh -file name in ~user/ctsm/ccs_config/component_grids_nuopc.xml before +Point to this file in your case's `env_run.xml` in the line that sets +`MASK_MESH`. If for some reason this fails, hardwire the ocean domain mesh +file name in `~user/ctsm/ccs_config/component_grids_nuopc.xml` before starting your CTSM or CESM simulation. In the specific example shown -here, hardwire the mesh file name for domain name gx1v7. +here, hardwire the mesh file name for domain name `gx1v7`. +